Blog Home  Home RSS 2.0 Atom 1.0 CDF  
.NET (Compact) Framework - SQL Mobile
Haggy's technischer BLog
 
 Wednesday, November 15, 2006
Jeder Entwickler steht beim Entwickeln einer PDA Software früher oder später vor der Frage , welche Datenbank er verwenden möchte.

Hat man nur kleine Prozessdaten so reicht XML aus. Fallen aber größere Datenmengen an, welche z.bsp. auch über eine Synchronisation kommen wird die Sache schon etwas schwieriger, insbesondere da XML auf PocketPC's und Smartphones nichts wirklich schnell ist.

Eine sehr gute integrierte Möglichkeit stellt der SQL Mobile 5.0 dar, welcher sogar über Replication services ein Synchronisationsmodul hat.Allerdings ist dieser nur solange kostenlos wie keine "echten" SQL Server im Spiel sind. S. :
http://www.microsoft.com/sql/editions/sqlmobile/howtobuy.mspx

Eine alternative insbesondere für OpenSource projekte könnte db40 sein. Von dieser datenbank gibts viele ableger u.a. auch für das Compact Framework s.:
http://www.db4o.com/s/compactframeworkdb.aspx
Db4o unterliegt der GPL was zur folge hat dass man die eigene Anwendung auch der GPL unterwerfen muss. Wer das nicht möchte kann allerdings auch hier eine kommerzielle Lizenz erwerben.

Angeblich soll aber sogar der Oracle lite unter dem ComapctFramework 2 laufen, dies konnte ich bsi jetzt aber leider noch nicht testen. Hat jemand dazu Erfahrungen?

Wenn ja würde es mich freuen wenn ihr mir was zu kommen lassen könntet, ich werde die informationen dann hier veröffentlichen

11/15/2006 8:01:22 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [8]    | .NET Allgemein | Compact Framework | Controls | SQL Mobile  | 
 Tuesday, July 04, 2006

 

All the code tipps tricks and hints are providerer “As Is” and there are no garantuees that it works. You have to test ,evaluate and use these things at your own Risk!

 

Also think about that Storagecard don’t have unlimited write accesses!

 

When I started developping software for small devices like PocketPC’s the applications were first of all very small and the databasesize didn’t exceed 10 MB.

Also on WinCE4 devices there was plenty enough of space for the database.

 

Now with the time the application growed and WinMobile 5 appaered , the things changed.

First of all the Database size has grown dramatically also the aviable space for file storage (e.g. the T-Mobile MDA PRO) decreased.

On some devices t here was only 10MB space for Files left.
So I decided to put the Database on the storagecard. After the first run I thought “Great it works”.

 
But first of all some strange errors occured. For example an error said “The command needs an open and prepared connection” meanwhile in the same moment the state property of the connection said the database were open and ready.

 

Time after time I found out, that this problems only happen when the device were turned off or was in some kind of sleep state.
Therefore I found a nice class of the OpenNETCF (s. OpenNETCF.org) which gave me the abillity to react on the device open event.

So first of I all I bind the event like this:

 
DeviceManagement
.DeviceWake += new DeviceNotification(DeviceManagement_DeviceWake);

 

Then I add some code which reopens the SQL Connection. But attention! I experienced that the event doesn’t always fire IMMEDIATLY when the device is turned on and ofte n fire many times instead of exact one time per turn on!

 

So you have to handle that this mehtod aren’t going to run twice ore more times at once!

 

To Handle the multiple DeviceWake events I write back the DateTime of the DeviceWake events and I only execute code if some time (one second) has passed till the last Wakeevent.

I assume no one is quick enough to turn the PocketPC on and off again in one second...

 

/// <summary>

/// Time when the Devicewakeevent fired the last time

/// </summary>

DateTime LastWake = DateTime.Now;

 

/// <summary>

/// As long as an Wakeevent is in progress this flag is true!

/// </summary>

public bool lWakeInProgress = false;

 

 

      void DeviceManagement_DeviceWake()

        {

 

         //Gettin the Timespan till the last Wakeevent fired

  TimeSpan TimeLastWake = DateTime.Now.Subtract(this.LastWake);

           

 

//So if theres no other Wake in Progress and the last wake event was before one second or longer I run my wake code

            if (!this.lWakeInProgress && TimeLastWake.TotalSeconds > 1)

            {

               

                try

                {

                    //Setting a hint to see that a wake is in progress

                    this.lWakeInProgress = true;

 

                    //Showing the user that we do something

                    Program.SetCursor(true);

 

                    //Giving the OS the change to handle own events ( this seemed to be important du to incoming phone calls which could wake up the device)

                    Program.Sleep(2);

 

                    //Now look if the Database physically exists, if not..

                    if (!System.IO.File.Exists(Program.cDataBaseFile))

                    {

                        // We’ll waiit 2 Seconds ( after this I never had any problems of an missing database file

                        Program.Sleep(2);

                    }

 

                    //Now I call my code to reconnect to database (closing and reponing the conection)

                    Program.ReConnectToDataBase();

 

                    //Soll das Wake protokolliert werden?

                    if (Program.lLogWake)

                    {

                        Program.oLog.LogErr("DeviceWake()", "Wake beendet");

                    }

 

                    //Wieder aufbauen

                    Program.SetCursor(false);

 

                    this.lWakeInProgress = false;

                }

                catch

                {

                   

                }

                finally

                {

                    this.lWakeInProgress = false;

                }

 

                //Updating the LastWake event DateTime ...

   this.LastWake = DateTime.Now;

 

   //and resetting the hint that the wake is in progress

                this.lWakeInProgress = false;

            }

 

Some more hints:

-         Check that SQL Procedures triggered by timer or something similar have their on SQL Connection otherwise you could get some errors conecrning and “already in use “ error of the SQL Connection

 

-         Be aware of using the PowerDown event in combination with the DeviceWake event. Some times the order of these 2 Events are mixed up ! So the PowerDown fires after the DeviceWake.

 

-         The Code of the PowerDown event isn’T always execute before  the device is really off . Furthermore it seems like the code is put onto the stakc and executet when the device is turned on again

 

-         No code of your .NET Enviroment is beeing executed while de device is off ( no timmer, no events, etc...) But there are APIfunctions to set an wakeup time. For this s. s. Daniel Moth’s Blog

     -   All devices should have installed the Latest ROM and OS Version because they improved a lot of handling of internal storages !

So I hope this was some kind of help concerning database SQL Mobile on PocketPC’s with, .NET CF2.0 and Storagecards

 

It this was helpfull pls. Concider an paypal spent

7/4/2006 2:58:37 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]    | Compact Framework | OpenNETCF | SQL Mobile  | 
 Tuesday, April 25, 2006

Nun da ich endlich mit der Umstellung von .NET CF1 auf CF 2.0 fertig bin, muss ich sagen, dass das ganze sich schwieriger gestaltete als man es irgendwo hätte lesen können.

Keine Thirdparty controls liefen mehr, auch deren Portierung läuft zur Stunde noch, Forms einfach konvertieren klappt auch nur in den seltesten Fällen usw.

Aber das .NET CF 2.0 bringt auch einige neue Features die inzwischen zu einem "Must-Have" geworden sind.
Hier mal eine Liste meiner persönlichen Favoriten:
- Anchoring
- SQL Mobile 3.0 Welcher via SQL Server Management Studio angesprochen werden kann.
- Einbindung der PocketPC Tasten
- Notifications.
- using () anweisung

Auf all diese Features möchte ich schon alleine wegen der neuen WinMobile geräte mit Querydisplay gar nicht mehr vermissen.

Auch stieg die Performance mit dem SQL Mobile 3 deutlich.
Gerade die using() anweisung zum Begrenzen der Lebenszeit von einigen Objekten hatte auf WindowsMobile5 geräten mit einem eh knappen RAM große Vorteile gebracht.

Hat jemand ähnliche oder andere Erfahrungen gemacht?
4/25/2006 7:42:25 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [2]    | Compact Framework | SQL Mobile  | 
 Thursday, April 20, 2006


Gerade bei Anwendungen auf den kleinen Geräten ist es wichtig darauf zu achten, möglichst performante Algorithmen zu haben, welche Zentral liegen.
Der Nachfolgende Text zeit eine Möglichkeit hierzu. Das ganze lässt sich auch analog im "normalen" .NET Framework realisieren.

Ein gut strukturierter Aufbau der Klassen, sowie ein Zentrales Datenhandling kommt da schon sehr entgegen.
Aufgrund einiger Optimierungen konnte ich eine PDA Anwendung um 75% beschleunigen und dabei den RAM Verbrauch sogar halbieren.

Eine Strategie davon ist der sinnvolle Einsatz von Hashtables.

Hashtables sind "Arrayähnliche" Objekte in welchen man über einen Objectkey Werte ablegen kann.
Z.bsp. so :

[code]
Hastable htWerte = new Hastable();
htWerte.Add("MeinKey","MeinWert");
[/code]

Da eine Hashtable sowohl für die Keys als auch für den Wert Objects erwartetm kann ich auch andere Typen als String hinterlegen und das sogar gemischt.

bsp:

DateTime ldDatum = DateTime.Now;
htGeburtsTage.Add(ldDatum,"heutiger Geburtstag");

Abrufen kann man die Werte über den Key z.bsp. so:
DateTime Gebtag = (DateTime) htGeburtsTage[DateTime.Now];

Was das ganze der Performance birngt ist klar.
Nehmen wir mal an wir haben eine Zentrale Methode welches aus dem Primary Key aus einer Tabelle mit Benutzern, den Namen des jeweiligen USers zurück liefert.
So ist doch die Abfrage ob wir hierfür jedes mal explizit ein SQL Conneciton brauchen.

Viel mehr wäre folgendes performanter:

Hastable htNamen = new Hashtable();
public string Id2Name(int tnId)
{
    string lcName;
   
    //Nachsehen ob der Wert schon gecached wurde
    if(this.htNamen.ContainsKey(lcName))
    {
        //Wert steht in der Hashtable => Direkt hieraus übernehmen
        lcName = (string) this.htNamen[tnId];
    }
    else
    {

         // Wert noch nciht vorhanden => Selektierne und danach für zukünftige Anfragen cachen
         lcName = oDaten.Id2Name(tnID);
         this.htNamen.Add(tnID,lcName);
    }


    return lcName
}


Das dies Performance bringt erklärt sich fast von selbst. Die Daten liegen im RAM vor und gerade bei neuen PocketPC 's welche einen langsamen ROM nutzen ist der Unterschied deutlich fühl- und messbar. Bei Desktopanwendungen wird zudem auch noch das Netzwerk weniger belastet und einige Selects können durch das einsparen von joins vereinfacht werden.

So wirkt sich der Vorteil auf sämtliche Clients aus.
4/20/2006 11:32:45 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [4]   .NET Allgemein | Compact Framework | SQL Mobile  | 
 Thursday, April 06, 2006



Am 3. Mittwoch im Mai startet der von mir geleitetet .NET (Compact) Framework Stammtisch.
Der erste Stammtisch wird im Rahmen des DFPUG Stammtischs Speyer stattfinden. Dort wird man Besprechen, wann und wo es weiter geht.

Die ersten Sessions werden wir damit beginnen, anhand einer kleinen Beispielanwendung, die Erstellung einer PocketPC Anwendung durchzugehen wird.

Währen der Entwicklung werden wir wohl auf einige Eigenheiten des CF stoßen und diese dann gleich Vorort durchdiskutieren und lösen.

Ich hoffe auf möglichst viele Interessierte.

Über Feedback und Wünsche freue ich mich!

In den nächsten Tagen werde ich das Beispiel, einer Indexbasierten Suche auf dem SQL Mobile / SQLCE hier noch eintragen und zur Verfügung stellen.
4/6/2006 2:39:19 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [2]    | .NET Allgemein | Compact Framework | SQL Mobile  | 
 Thursday, March 09, 2006



So mein letztes BLog posting ist schon eine ganze Weile her, da überall viel zu erledigen war. Nun habe ich aber einen kleinen Augenblick gefunden um die CompactFramework (.NET Framework für PDA) Section etwas füllen z

Meine Heimatsprache liegt ja eigentlich in VFP insofern bin ich es gewohnt viele schnelle Datenbankoperationen direkt in meiner Entwicklungsumgebung zu haben. Wie Z.bsp. ein LookUp() oder der Seek()

In .NET speziell im Compact Framework gibt es auch eine ganze Reihe von Möglichkeiten, welche aber nicht so einfach zur Verfügung stehen.
Im Rahmen eines Imports benötigte ich jedoch eine Methode, welche es ermöglicht so schnell wie möglich feststellen zu können ob ein Datensatz bereits existiert, diese wird auch Mehrfach hinterinander aufgerufen.


Deswegen habe ich versucht 2 Methoden zu implementeieren welche den VFP SEEK() und LOOKUP sehr nahe kommen. Hierzu habe insbesodnere in den Newsgroups anleitung gefunden.
Diese Methode läuft sowohl mit SQLCe also auch dem SQL Mobile 3.0

///

/// SqlCeCommand Objekt für die Seek und lookup methode

///

SqlCeCommand Seekcmd;

 

///

/// SQlCEDataReader für Lookup() und Seek

///

SqlCeDataReader rdr;

 

///

/// Prüft auf einem Indes ob die angebene ID in dem Index Felder der angegebenen Tabelle existiert

///

///

Tabelle in der gesucht wird

///

ID nach der gesucht wird

///

Indiziertes Feld in dem gesucht wird, ohne Index -> Exception

/// bool ob gefunden

public bool Seek(string tcTable, string tcID, string tcIndexField)

{

// BaseTable Search = VFP indexbased Seek() Like Suche

bool llFound = false;

 

// Wir suchen auf der angebenen Tabelle

Seekcmd.CommandText = tcTable;

 

// und dem angebenen Index

Seekcmd.IndexName = tcIndexField;

 

// Die Range gibt an für welchen Bereich espäter ein Reader erzeugt werden soll.

// In unserem Fall eben genau dieser eine Wert. Ein Reader hat den Vortiel dass wir nicht erst selektieren

// müssen sondern uns einfach direkt auf den Zielsatz setzen werden.

Seekcmd.SetRange(DbRangeOptions.Match , new object[] { tcID }, null);

 

// wir erzeugen uns aus TableName,Index und Range einen Reader

using (this.rdr = Seekcmd.ExecuteReader())

{

 

//// Prüfen ob wir einen Reader erzeugen konnten.

if (this.rdr != null && !this.rdr.IsClosed && this.rdr.HasRows)

{

 

//Wenn nun das erste lesen klappt haben wir einen satz gefunden!

if (rdr.Read())

{

llFound = true;

}

 

}

 

// Reader schliesen

this.rdr.Close();

}

return llFound;

}

War dieser Eintrag hilfreich ? Wenn ja würde ich mich über eine kleine Spende freuen:

3/9/2006 3:31:46 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]    | Compact Framework | SQL Mobile  | 
Copyright © 2010 Haggy. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme: