Hallo allerseits
Im folgenden Beitrag werde ich meinen OR Mapper für SQLite kurz erklären.
**Vorteile: ***einfach und schnell zu benutzen *recht gute Performance (Details siehe weiter unten) *keine SQL Kenntnisse notwendig
**Features: ***automatisches Erstellen/Einfügen von neuen Objekten *Updaten und Löschen von Objekten *rudimentäre Suche nach Objekten (wird noch erweitert) *OR Mapper kann eine vorhandene Datenbankstruktur nutzen, oder die Datenbank automatisch aus den C#-Klassen erstellen (im Demobeispiel wird alles automatisch erstellt) *Automatische Durchführung von Transaktionen
**Benutzung: **
Bei der Benutzung sind ein paar Kleinigkeiten zu beachten:
1.) Objekte die man verwalten/speichern möchte müssen eine Property des Typs Guid besitzen, die einen eindeutigen Schlüssel (PrimaryKey) darstellt. (Die Schlüssel werden vom OR-Mapper automatisch vergeben, es muss lediglich solch eine Eigenschaft vorhanden sein)
1.) Objekte müssen das Interface IPersistentObject implementieren.
Dieses Interface verlangt lediglich 2 Properties: 1) string TableName -> wie soll die Tabelle in der Datenbank heißen, die diesem Objekt entspricht; 2) string PrimaryKey -> wie heißt die Property die den Primärschlüssel darstellt (siehe Punkt 1)
Das war's auch schon.
Ein kleines Beispiel für solch ein Objekt könnte wie folgt aussehen:
public class TestObject: IPersistentObject
{
public Guid TestObjectID
{
get;
set;
}
public string Name
{
get;
set;
}
public DateTime TestDate
{
get;
set;
}
#region IPersistentObject Member
public string TableName
{
get { return "TestObject"; }
}
public string PrimaryKey
{
get { return "TestObjectID"; }
}
#endregion
}
ACHTUNG: SQLiteMapper versucht ALLE Properties (ausgenommen "TableName" und "PrimaryKey") in die Datenbank zu speichern. Daher nur primitive Datentypen benutzen (int, double, string, DateTime, ...)
Wird eine vorhandene Datenbankstruktur genutzt, müssen daher alle Properties als Attribute der Tabelle vorhanden sein.
Ein kleines Demo (ist auch im zip-Archiv enthalten):
string file = Path.Combine(Application.StartupPath, "test.db");
//--------- CREATE/CONNECT Database --------------------
//create mapper / db
DBAccess mapper = DBAccess.CreateDB(file);
////use next line instead to connect to an existing file
//DBAccess mapper = new DBAccess(file);
//--------- Create/Insert new objects ------------------
//create (and insert) two new objects
TestObject obj1 = mapper.NewBusinessOject<TestObject>();
obj1.Name = "TestObject 1";
TestObject obj2 = mapper.NewBusinessOject<TestObject>();
obj2.Name = "TestObject 2";
//--------- Get/Search objects -------------------------
//get all objects of a specific type
List<TestObject> all_objects = mapper.GetObjects<TestObject>();
//get only objects where a specific property (Name) has a specific value ("TestObject 2")
List<TestObject> filtered_objects = mapper.GetObjects<TestObject>("Name", "TestObject 2");
if (filtered_objects.Count == 1)
{
filtered_objects[0].TestDate = DateTime.Now.AddDays(1);
mapper.Update(filtered_objects[0]);
}
else
MessageBox.Show("ERROR: filter was wrong");
//every object has to have a PrimaryKey of the type Guid
Guid primaryKey = obj1.TestObjectID;
//you can access such an object very quickly by using the following method
TestObject found = mapper.GetByPrimaryKey<TestObject>(primaryKey);
if (found != obj1)
MessageBox.Show("ERROR: wrong PrimaryKey");
//--------- save changes into the database ------------------
//save changes (the two new objects (also the modified one) to disc/file)
mapper.SaveChanges();
MessageBox.Show("Finished", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information);
**Bezüglich Geschwindigkeit **
(Testsystem: Notebook mit 2x2 GHz, 3 Gig Ram und 120GB Festplatte mit 7200 rpm (zu 90% belegt))
Leider konnte ich das Projekt nicht als Anhang hinzufügen, da es recht groß ist (2 MB), kann aber hier heruntergeladen werden: www.saftware.net/SQLiteMapper_vers1.zip
Liebe Grüße
Preli
Hallo preli,
Ich hab mir zwar nur deinen Beitrag angesehen und nicht den ORMapper, aber der sieht auf dem ersten Blick nicht schlecht aus.
Was mich aber persönlich interessieren würde, wäre ein direkter Vergleich zu ADO.NET.
Was mich aber persönlich interessieren würde, wäre ein direkter Vergleich zu ADO.NET.
Meinst du einen Performancevergleich?
Dort würde ADO wahrscheinlich schon eine Spur schneller sein, da mein Mapper ja intern auch ADO benutzt.
Jedoch könnte SQLiteMapper schon in manchen Fällen trotzdem schneller sein, wenn man mit Objekten "arbeitet" die im Cache sind.
Liebe Grüße
Preli
Hallo preli
Ein direkter Vergleich zur Standard SQLite-API wäre interessanter, IMO 🙂
(Klar ist dein Mapper langsamer, aber der Faktor wäre interessant als das derzeitige Bild)
Die Typen- und PropertyInfo[]-Objekte könntest du ggf. noch cachen, wenn mehrere gleiche hintereinander kommen (Oder nach einer anderen Strategie).
foreach (PropertyInfo pi in temp.GetType().GetProperties())
Das hier könntest du mit einem Constraint einschränken, dann brauchst du keine Laufzeit-Prüfung mehr:
public T NewBusinessOject<T>()
{
T result = (T)Activator.CreateInstance(typeof(T));
if (result is IPersistentObject)
=> (Den Cast auf IPersistenceObject kannst du auch weglassen, mit dem Constraint)
public T NewBusinessOject<T>() where T: IPersistentObject
{
T result = (T)Activator.CreateInstance(typeof(T));
IPersistentObject po = result;
}
Die zwei GetObjects-Methoden könntest du auch ein bisschen zusammenfassen, die enthalten zuviel Redundanz.
<Command / Connection / etc..>.Close / Dispose müsstest du noch ergänzen.
Am besten ein using-Statement benutzen.
Alles in einer 3 Dateien ist ein bisschen knapp, ich würde das noch ein wenig trennen.
Die Medaille "Kürzester OR / Mapper ever" hast du von mir schon mal 🙂
BTW: Schau dir mal SubSonic an (http://subsonicproject.com/)
Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011
Danke für die Tipps (und die Medaille)
Liebe Grüße
Preli
Was hat dein Beitrag mit diesem ORMapper für SQLite zu tun? preli hat ein ORMapper erstellt und keine OODB.