HowTo: Erste Schritte mit EF CodeFirst & SQL CE 4.0 in ASP.NET MVC 3

imageWenn man mal “schnell” eine kleine Datenbank braucht – ohne großen SQL Server oder sich erst mit Sqlite und co. rumzuschlagen kann auch auf SQL CE 4.0 zurückgegriffen werden. Zusammen mit dem Entity Framework CodeFirst Modell kann man recht schnell eine kleine Anwendung zusammenbauen. CodeFirst kann natürlich auch in Verbindung mit einem richtigen SQL Server angewandt werden. Hier mal ein kurzes Tutorial, wie man das Initial zum Laufen bekommt.

SQL CE 4.0? Warum nicht Sqlite, eine XML Datei etc.?

Geht natürlich auch – allerdings muss man dann auf das Entity Framework verzichten (ob das schlimm ist, muss jeder für sich entscheiden ;) ). SQL CE 4.0 ist der Mini-Bruder vom SQL Server – demzufolge könnte man auch später ein Upgrade ohne Probleme vollziehen. SQL CE 4.0 läuft mit im Prozess und bedarf keiner weiteren Installation beim Betrieb. Man muss nur die passenden Dlls mit ausliefern und es läuft.

Eine genauere Beschreibung liefert ScottGu: VS 2010 SP1 and SQL CE

EF CodeFirst? Was das?

Das Entity Framework mit seinem gigantischen .EDMX Model ist schon etwas ziemlich gewaltiges und meiner Meinung nach nicht gerade elegant und nützlich. Mit EF CodeFirst wird ein “leichtes” Modell angeboten, in dem man sowohl die Vorzüge des EFs (LINQ!) und das Mappen auf eigene POCOs nutzen kann. (Andere Frameworks (z.B. NHibernate) bieten solch ein Feature bereits seit einiger Zeit an, aber diesen fehlte (?) zum Teil lange ein netter LINQ Support.)

Ganz detailliert natürlich auch bei ScottGu: Code-First Development with Entity Framework 4

Beispielapp – wie sieht der Entwicklungsprozess aus?

Da das erste Setup mit Code-First & SQL CE 4.0 etwas Forschungsarbeit mit sich gebracht hat, zeige ich mal ganz kurz wie man die ersten Schritte unternimmt.

Vermutlich ist es besser, wenn man das VS2010 SP1 installiert hat – bin mir aber jetzt nicht ganz sicher ob es wirklich von Nöten ist.

Wir fangen an und erstellen eine ASP.NET MVC 3 Applikation. Wichtig: Vorher das ASP.NET MVC 3 Tools Update installieren. Damit kommt das Entity Framework Update als NuGet Package gleich mit. Nachprüfen kann man das, indem man die Assembly “EntityFramework” in den Referenzen sucht. Diese wird benötigt! Ansonsten via NuGet z.B. nach Code First suchen :)

image

Prüfen ob SQL 4.0 Dev Tools installiert sind

Um zu schauen ob die Dev Tools installiert sind, kann man ein Blick in das “Add Items” (irgendwo in einem Ordner im Projekt *rechtsklick*) Menü werfen:

Sieht man das SQL Server Compact 4.0 Item ist alles ok. Empfehlung von mir: Legt euch eine SQL Server Compact 4.0 DB an, damit werden alle benötigten Referenzen automatisch ins Projekt eingebunden. Anschließend aber die DB wieder rauslöschen, weil diese uns weiter unten ein paar Probleme bereitet :)

image

Wenn man das Item nicht sieht: Im Web Platform Installer die “VS 2010 SP1 Tools for SQL Server Compact” installieren (Alternativ über diesen Link – allerdings fängt dann sofort der Download an und dummerweise nimmt er bei mir immer die deutsche Version (welche ich aber nicht haben will) – besser Web PI)

image

Nach dem Installieren bekam ich diese Meldung:

image

Nach der Installation muss das VS 2010 neugestartet werden – nun im Projekt eine SQL CE DB anlegen um die benötigten Referenzen zu bekommen.

Nächster Schritt: App_Data Verzeichnis erstellen

image

Dieser Schritt sollte bereits erledigt sein: Wenn ihr die DB angelegt habt, sollte euch VS auch gleich das App_Data Verzeichnis angelegt haben. Wenn nicht: Im App_Data Verzeichnis sollen alle Datenbanken und sonstige “Data” Sachen landen. Allerdings wird der Ordner nicht sofort mit angelegt – daher müssen wir den noch manuell hinzufügen (über *rechtsklick* auf das Projekt *Add* – *Add ASP.NET Folders* – App_Data).

ConnectionString anlegen

Nun hinterlegen wir in der Web.config z.B. folgenden ConnectionString:

  <connectionStrings>
    <add name="DatabaseContext" connectionString="Data Source=|DataDirectory|TestWebsiteModelDatabase.sdf" providerName="System.Data.SqlServerCe.4.0"/>
  </connectionStrings>

Ein paar Anmerkungen:

  • DataDirectory steht für das App_Data Verzeichnis der Anwendung.
  • .SDF ist ein SQL Server Compact File (anders als das .MDF vom großen SQL Server)
  • Der Providername ist auf SQL CE 4.0 eingestellt.
  • Der Name des ConnectionStrings wird später noch eine wichtige Rolle spielen!

Ein Model erstellen – Code-First Style

Wir haben User und Kommentare dazu – nichts wirklich aufregendes. Wichtig hierbei: Keine Attribute von irgendwelchen Entity Framework Sachen – simple POCOs.

    public class User
    {
        public string Name { get; set; }
        public Guid Id { get; set; }
        public List<Comment> Comments { get; set; }
    }

    public class Comment
    {
        public Guid Id { get; set; }
        public User User { get; set; }
        public string Text { get; set; }
    }

Controller mit Scaffolding erzeugen

Nun fügen wir ein MVC Controller dazu (auf den Controller Ordner *Rechtsklick* – *Add Controller*).

Hier geben wir den Controller-Namen an, wählen das Scaffolding Template mit den EF Options und wählen die User Klasse aus. Falls die Klasse dort nicht erscheint: Vorher ein Rebuild ausführen!

Als Data context class muss derselbe Name genommen werden wie der Name des Connection Strings! (in meinem Fall also: DatabaseContext).

“Convention over configuration” ist hier das Motto.

image

In den Advanced Options kann man auch noch eine Masterpage auswählen:

image

Ergebnis:

Es wurde dieser Controller automatisch erstellt:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcEFCodeFirst.Models;

namespace MvcEFCodeFirst.Controllers
{
    public class UserController : Controller
    {
        private DatabaseContext db = new DatabaseContext();

        //
        // GET: /User/

        public ViewResult Index()
        {
            return View(db.Users.ToList());
        }

        //
        // GET: /User/Details/5

        public ViewResult Details(Guid id)
        {
            User user = db.Users.Find(id);
            return View(user);
        }

        //
        // GET: /User/Create

        public ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /User/Create

        [HttpPost]
        public ActionResult Create(User user)
        {
            if (ModelState.IsValid)
            {
                user.Id = Guid.NewGuid();
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(user);
        }

        //
        // GET: /User/Edit/5

        public ActionResult Edit(Guid id)
        {
            User user = db.Users.Find(id);
            return View(user);
        }

        //
        // POST: /User/Edit/5

        [HttpPost]
        public ActionResult Edit(User user)
        {
            if (ModelState.IsValid)
            {
                db.Entry(user).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

        //
        // GET: /User/Delete/5

        public ActionResult Delete(Guid id)
        {
            User user = db.Users.Find(id);
            return View(user);
        }

        //
        // POST: /User/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(Guid id)
        {
            User user = db.Users.Find(id);
            db.Users.Remove(user);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

Es wurden diese Views angelegt (voll funktionsfähig) :

image

Es wurde eine DatabaseContext Klasse angelegt:

using System.Data.Entity;

namespace MvcEFCodeFirst.Models
{
    public class DatabaseContext : DbContext
    {
        // You can add custom code to this file. Changes will not be overwritten.
        //
        // If you want Entity Framework to drop and regenerate your database
        // automatically whenever you change your model schema, add the following
        // code to the Application_Start method in your Global.asax file.
        // Note: this will destroy and re-create your database with every model change.
        //
        // System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<MvcEFCodeFirst.Models.DatabaseContext>());

        public DbSet<User> Users { get; set; }
    }
}

Über diese Klasse passieren (siehe Controller) die Zugriffe und es geschieht das Mapping auf das POCO. Interessant ist noch Zeile 14. Wenn man den Anweisungen folgt und diese Zeile in der Global.asax einfügt, wird bei Schemaänderungen eine neue Datenbank angelegt. Datenmigrationen erfolgen aber nicht!

Für Development-Zwecke aber sehr praktisch.

Achtung: Es darf aber keine Datenbank diesen Namens bereits existieren – weil das Framework sonst damit nicht umgehen kann.

Die erstellte Datenbank sieht von der Struktur so aus:

image

Was ist mit den Comments? Tauchen die auch irgendwo auf?

In unserem Model hatten wir weiter oben eine Verbindung zwischen User und Comment gemacht – in der DB wird diese auch abgebildet, allerdings sind diese in den Templates nicht wiederzusehen. Man kann allerdings sicherlich das Scaffolding anpassen, sodass dies nur eine Frage der verfügbaren Templates ist – passender Google Suchbegriff: MvcScaffolding.

Wie sieht so ein View aus:

Da wir nicht wirklich viele Properties festgelegt haben (“ID” wird auch vom Framework erzeugt und kann daher nicht angepasst werden – auch eine Konvention) sieht es nur so aus:

image

image

usw.

Fazit

Für schnelle Prototypen sehr praktisch. Wie sich das Mapping bei komplexeren Sachverhalten verhält: Keine Ahnung. Durch die LINQ Unterstützung und das Scaffolding macht es trotz mancher Setup-Sachen durchaus Spaß.

Deployment

Wer alle Assemblies sich für ein sicheres Deployment zusammensuchen möchte, dem empfehle ich *Rechtsklick* auf das Projekt zu machen und *Add Deployable Dependencies* auszuwählen (in dem Fall hier: Alles anklicken ;) ) :

image

Dann wird noch ein recht großer Ordner in das Projekt ein gehangen in dem die Abhängigkeiten mit drin sind.

Soviel zum kurzen Einstieg in das Thema :)

[ Download Democode ]

Wenn dir der Blogpost gefallen hat, dann hinterlasse doch einen Kommentar. Wenn du auf dem Laufenden bleiben willst, abonniere unseren RSS Feed oder folge uns auf Twitter.

About the author

Written by Robert Mühsig

Hi, ich bin Robert Mühsig und bin Webentwickler und beschäftige mich mit Web-Frameworks auf dem Microsoft Web Stack und scheue mich auch nicht vor Javascript. Der Blog begann als "Problemsammelstelle und Lösungshilfe" und seitdem schreibe ich hier alles auf. Seit 2008 bin ich Microsoft MVP für ASP.NET. Treffen kann man mich online via Twitter (@robert0muehsig) oder hier.

2 Responses

  1. Super Artikel, vielen Dank dafür!

    Reply
  2. db.users ist bei mir immer leer!

    Reply

Comment on this post

Letzte Posts

  • image.png
    IIS & Windows Authentication – Troubleshooting mit Negotiate & NTLM

    Windows Authentifizierung ist eine einfache (und naheliegende) Authentifizierungs-Option für “Haus-interne” Webapplikationen. Setup Im IIS selbst kann man die Windows Authentifzierung sehr leicht anschalten: Natürlich kann man dies auch über die web.config steuern: <system.web> ... <authentication mode="Windows"/> ... </system.web> ... Fehlermeldung “HTTP Error 401.2 – Unauthorized”: Dies kann (wie fast immer) viele Gründe haben, z.B. weil ...

  • image.png
    Json-Online-Tools: Viewer & Json2Csharp Generator

    Wo APIs im Spiel sind, ist das JSON Format nicht weit. Da ich immer mal wieder zwei Tools benutze, möchte ich diese hier auch mal kurz würdigen. JSON Viewer Wer nur den JSON-Text vor sich hat sieht meist die Struktur nicht. Über JSON Viewer kann man sich recht einfach einen Überblick verschaffen: [URL] JSON2CSharp Der ...

  • image.png
    Tools & Vorgehen für Entwicklung rund um OpenXml oder wie erstelle ich Office Dokumente mit .NET?

    Durch meine Tätigkeit bei der  OneOffixx AG habe ich recht tiefe Einblicke in die Erstellung von Microsoft Office Dokumente mit .NET bekommen. Da das Problem “Office Dokumente per Code” zu erstellen recht verbreitet ist, schreib ich mal Empfehlungen für die ersten Schritte. Must Have Tools Ganz klar sollte man das Office in der jeweiligen Version ...

  • image.png
    Windows Phone SDK- & “System”-Icons

    Zwar legt das Metro Design viel Wert auf Typografie – jedoch sind auch Icons sehr wichtig. Wer das Windows Phone SDK installiert hat, bekommt 36 Icons mitgeliefert. Diese sind unter diesem Pfad zu finden: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons Viele Icons, welche man von den eingebauten Anwendungen kennt, sind allerdings nicht enthalten. Pedro Lamas hat ...

  • image.png
    Wie finde ich heraus ob mein ADFS 2.0 funktioniert?

    Ich hatte mich recht lange mti dem Thema ADFS 2.0 (“Active Directory Federation Services”) beschäftigt und da kam die recht einfache Frage auf: Wie stelle ich fest ob die Verbindung zwischen ADFS und AD “funktioniert”? Hier eine simple Variante es zu testen… Was ist ein ADFS überhaupt? Wenn man über AD-Grenzen hinweg “Vertrauensstellungen” braucht, dann ...

Unterstützt von…

Facebook