ADO.NET Entity Framework mit einer SQLite Datenbank

Daten können auf verschiedenste Weise gespeichert werden. Diese können entweder ganz einfach in Textdateien gespeichert werden, welche je nach Technologie erst geparst werden muss. Die bessere Alternative wäre eine komplette Serialisierung von Objekten, welche in XML-Dateien gespeichert werden. Doch diese Speicherung hat auch einen Nachteil, denn die komplette Datei muss erst eingelesen werden. Das kann bei großen Datenmengen einige Zeit in Anspruch nehmen.

Deshalb ist es bei großen Datenmengen ratsam, seine Daten komfortabel in eine Datenbank zu speichern. Wenn es nicht unbedingt gleich ein Microsoft SQL Server oder eine Oracle Datenbank sein muss, tut es auch eine SQLite Datenbank. Der große Vorteil dieses relationalen Datenbanksystems ist, dass die Daten in einer Datei gespeichert werden. Es muss daher kein Datenbanksystem auf dem Zielrechner installiert werden.

Eine einfache SQLite-Anwendung

Um SQLite in einer .NET-Anwendung zu benutzen, reichen die Binaries von der SQLite-Seite, welche man in sein Projekt einbindet und mit bisschen Code würzt. Das könnte folgendermaßen aussehen:

// Create sqlite connection
SQLiteConnection connection = new SQLiteConnection(string.Format(
@"Data Source={0}\SimpleDatabase.s3db", 
Environment.CurrentDirectory));

// Open sqlite connection
connection.Open();

// Get all rows from example_table
SQLiteDataAdapter db = new SQLiteDataAdapter("SELECT * FROM Names", connection);

// Create a dataset
DataSet ds = new DataSet();

// Fill dataset
db.Fill(ds);

// Create a datatable
DataTable dt = new DataTable("Names");
dt = ds.Tables[0];

// Close connection
connection.Close();

// Print table
foreach (DataRow row in dt.Rows)
{
    Console.WriteLine(string.Format("{0} {1}", row["Firstname"], row["Surname"]));
}

Durch die vielen manuell eingegebenen Strings wird der Code leider nicht sehr nachhaltig gestaltet.

SQLite mit dem Entity Framework

Mit dem ADO.NET Entity Framework wird das ganze jedoch stark vereinfacht. Der Code wird dadurch wesentlich besser wartbar und durch das unterstützte IntelliSense wird das Code schreiben zum Erlebnis.

Um loslegen zu können bedarf es jedoch noch einiger wichtiger Schritte. Es wird im folgenden eine komplette Datenbank erstellt, mit der wir ein automatisches Entity Model generieren lassen. Für unser Szenario dient uns eine Filmdatenbank.

Datenbank anlegen

Es gibt eine Vielzahl von Programmen mit dem man eine SQLite-Datenbank erstellen können, diese sind entweder Freeware oder kostenpflichtig. Eine Liste von verschiedenen Programmen findet Ihr im Wiki von sqlite.com.

Am einfachsten geht es mit dem Tool SQLite Administrator, optional wäre aber auch das Firefox-Plugin SQLite Manager zu nennen, welches auch sehr einfach aufgebaut ist.

Nachdem Download vom SQLite Administrator und dem Entpacken starten wir das Tool. Unter Database » New können wir eine neue Datenbank erstellen. Als Dateinamen wählen wir “MovieDatabase”. Die Datenbank wird erstellt und es kann eine neue Tabelle angelegt werden.

Mit einem Rechtsklick auf Tables und einem Klick auf “Create Table” können wir die Struktur der neuen Tabelle festlegen..:

sqlite_create_db_2

Wir könnten jetzt schon nach Herzenslust Daten eingeben. Das wollen wir jedoch in der .NET-Anwendung verrichten.

Entity Framework Konsolenanwendung

Wir starten Mit Microsoft Visual Studio 2012 erstellen wir ein neue Konsolenanwendung mit dem Namen “EntityFrameworkWithSQLite” :

sqlite_ef_1

Damit das Programm inklusive Datenbank auch weitergegeben werden kann, kopieren wir die Datenbank zum Ausgabeordner (Debug oder Release). Zur Vereinfachung lassen wir die Datenbank automatisch beim Compilierungsprozess in den Ausgabeordner kopieren. Dazu fügen wir die Datenbank mit “Add Existing Item” zum Projekt hinzu und stellen in den Properties der Datei “Copy to Output Directory” auf “Copy always”.

sqlite_ef_2

Damit wir unter Visual Studio mit SQLite arbeiten können, benötigen wir die noch ein Setup mit Visual Studio 2012 – Unterstützung, welches auf der SQLite-Seite zu finden ist. Wenn wir für x64-Systeme entwickeln, brauchen wir trotzdem das Setup für 32-Bit. Da nur dieses Setup die Unterstützung für Visual Studio mitbringt. Die Setups sind sehr schön mit dem Hinweis:

This is the only setup package that is capable of installing the design-time components for Visual Studio 2012.

zu erkennen. Daher downloaden wir für unser Beispiel folgendes Setup: Setups for 32-bit Windows (.NET Framework 4.5) und installieren es. Im Setup muss unbedingt noch “Install the designer components for Visual Studio 2012” aktiviert werden, damit die Visual Studio Unterstützung installiert wird!

sqlite_ef_3

Als nächstes müssen wir noch die SQLite.dll als Referenz einbinden. Diese befindet sich bei der 32-Bit Version standardmäßig (bei der momentan aktuellen Version: 2012-1.0.88.0) unter “C:\Program Files (x86)\System.Data.SQLite\2012\bin”. Wir benötigen nur die “System.Data.SQLite.dll”, da wir Linq vom .NET-Framework benutzen.

ADO.NET Entity Data Model genieren

Jetzt beginnt endlich der interessantere Teil. Wir öffnen als erstes den Server Explorer (VIEW » Server Explorer) und klicken rechts auf “Data Connections” und dann auf “Add Connection…”.

Als “Data source”, bzw. “Data provider” wählen wir “System.Data.SQLite Database File”.

sqlite_ef_4

Im Anschluss wählen unsere erstellte Datenbank (MovieDatabase.s3db). Die anderen Einstellungen können wir so belassen und bestätigen die Connection mit OK.

sqlite_ef_4b

Als nächstes fügen wir unserem Projekt ein “ADO.NET Entity Data Model” hinzu:

sqlite_ef_5

Natürlich möchten wir das Model automatisch generiert haben und somit im nächsten Schritt “Generate from database” ausgewählt.

sqlite_ef_6

Da wir nur eine Verbindung angelegt haben, wird diese standardmäßig ausgewählt.

sqlite_ef_7

Mit einem Klick auf “Next >” können wir unsere Objekte auswählen. Wir wählen “Tables” aus und klicken auf Finish.

sqlite_ef_8

Jetzt steht unser erfolgreich erstelltes Entity Model zur Verfügung.

sqlite_ef_9

Damit wir das Programm samt Datenbank weitergeben können, müssen wir noch den Connectionstring in der Datei “App.config” anpassen. Da wir immer die Datenbank in das Zielverzeichnis der compilierten Anwendung kopieren, geben wir den relativen Pfad (data source=MovieDatabase.s3db) an:

<connectionStrings>
    <add name="MovieDatabaseEntities" 
         connectionString="metadata=res://*/MovieDatabaseModel.csdl|res://*/MovieDatabaseModel.ssdl|res://*/MovieDatabaseModel.msl;provider=System.Data.SQLite;provider connection string="data source=MovieDatabase.s3db"" 
         providerName="System.Data.EntityClient" />
</connectionStrings>

Beispiel-Operationen mit dem Entity Framework

Jetzt ist alles eingerichtet und wir können uns an das Programmieren machen. Zum Verständnis möchte daher 4 Beispiel-Szenarien aufzeigen:

  1. Daten hinzufügen
  2. Einen Datensatz ändern
  3. Einen einzelnen Datensatz anzeigen
  4. Alle Datensätze anzeigen

Daten hinzufügen

Ohne ein SQL-Statement wird ein Datensatz hinzugefügt. Dazu erstellen wir eine neue Instanz von “Movies” und befüllen die Propertiers. Im Anschluss fügen wir den Film zur Tabelle und speichern die Datenbank.

using (var instance = new MovieDatabaseEntities())
{
    // Create new movie
    Movies movie = new Movies();
    movie.Name = "Kill Bill: Vol. 1";
    movie.Director = "Quentin Tarantino";
    movie.Playtime = 111;

    // Add movie to database table
    instance.Movies.Add(movie);

    // Save 
    instance.SaveChanges();
}

So einfach ist das! Damit wir nachher viele Datensätze anzeigen können, fügen wir einfach noch ein paar hinzu. Um den Code ein kleinwenig übersichtlicher zu gestalten, fügen wir noch 2 Konstruktoren des Objektes Movies (MovieDatabaseModel.edmx » MovieDataseModel.tt » Movies.cs) hinzu. Das ist zum einen der Standardkonstruktor ohne Parameter und zum Anderen ein überladener Konstruktor, welcher die Daten zur Initialisierung bekommt.

/// 
/// Initialisize object
/// 
public Movies()
{ }

/// 
/// Initialisize object with data
/// 
///
///
///
public Movies(string name, string director, long playtime)
{
    Name = name;
    Director = director;
    Playtime = playtime;
}

Somit können wir bequem die Filme hinzufügen:

```csharp>// Add more movies

instance.Movies.Add(new Movies("Pulp Fiction", "Quentin Tarantino", 1540)); instance.Movies.Add(new Movies("Reservoir Dogs", "Quentin Tarantino", 99)); instance.Movies.Add(new Movies("Wall-E", "Andrew Stanton", 98)); instance.Movies.Add(new Movies("Drive ", "Nicolas Winding Refn", 100));


### Einen Datensatz ändern Bei solchen statischen Daten ändert sich in der Regel nichts. Daher hab ich einen kleinen Fehler bei dem Film-Datensatz “Pulp Fiction” eingebaut. Denn die Spielzeit ist nicht 1540, sondern nur 154 Minuten. Fast 26 Stunden für einen Film wäre dann doch ein wenig zu lange <img class="wlEmoticon wlEmoticon-smile" src="files/data/blog/2013/10/wlEmoticon-smile_2.png" alt="Smiley">. Daher beziehen wir mittels Linq unseren Datensatz und korrigieren die Spielzeit: ```csharp // Get a movie Movies wantedMovie = instance.Movies.SingleOrDefault(item => item.Name == "Pulp Fiction"); wantedMovie.Playtime = 154; // Save changed movie instance.SaveChanges();

Einen einzelnen Datensatz anzeigen

Die Properties des geänderten Objektes können wir uns schließlich ausgeben lassen:

// Show changed movie
Console.WriteLine(string.Format(
    "Filmname: {0}, Regisseur: {1}, Spielzeit: {2} min",
        wantedMovie.Name,
        wantedMovie.Director,
        wantedMovie.Playtime.ToString()));

Alle Datensätze anzeigen

Eine komplette Tabelle anzeigen zu lassen ist nicht viel schwerer. Dazu brauchen wir nur das “Movies-Objekt” in eine einfache Liste speichern. Natürlich könnten wir dieses Objekt auch binden. Da es sich hierbei nur um eine Konsolenanwendung handelt, werden die Datensätze in einer foreach-Schleife ausgegeben:

// Get all movies
List allMovies = instance.Movies.ToList();

// Show all movies
foreach (Movies showMovie in allMovies)
{
    Console.WriteLine(string.Format(
        "Filmname: {0}, Regisseur: {1}, Spielzeit: {2} min",
            showMovie.Name,
            showMovie.Director,
            showMovie.Playtime.ToString()));
}

Den Quellcode von diesem Tutorial befindet sich wieder auf Github für das einfache Beispiel und für das Entity Framework Beispiel.