Entity Framework – Erste Schritte und Erfahrungen

Meinen Einstieg ins Entity Framework von Microsoft hatte ich bereits vor etwa einem Jahr und seitdem kann ich mir keinen schnelleren und einfacheren Weg mehr vorstellen, um „mal eben“ einen Datenbankzugriff zu realisieren – kein Abstimmen von SQL-Befehlen auf Entity-Klassen, kein Verwalten von Fremdschlüsseln, kein explizites DDL-Skript zur Anlage der Tabellen. Dank des Entity Frameworks kann ich weiter in C# arbeiten, mich auf meine Klassen und Geschäftslogik konzentrieren und das DB-Management delegieren.

Erste Schritte

Das Entity Framework (EF) lässt sich leicht fast jedem Projekt mit dem NuGet-Paket-Manager hinzufügen.

Da ich den „Code First“-Ansatz, bei dem die Klassen automatisch in Tabellen umgewandelt werden, bevorzuge, konzentriere ich mich auf den Entwurf meiner Datenklassen und modifiziere sie leicht, um dem EF Hinweise zu geben, was wie umgesetzt werden soll.

Ein kleines Beispiel

Aus den beiden folgenden Klassen…

public class Diagram
{
    public Guid Id { get; set; }
    public String Name { get; set; }
    public ICollection<Symbol> ContainedSymbols { get; set; }
}

public class Symbol
{
    public Guid Id { get; set; }
    public String Name { get; set; }
    public Diagram ContainingDiagram { get; set; }
}

wird…

public class Diagram
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    public String Name { get; set; }

    public virtual ICollection<Symbol> ContainedSymbols { get; set; }
}

public class Symbol
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    public String Name { get; set; }

    public Guid ContainingDiagramId { get; set; }

    [ForeignKey("ContainingDiagramId")]
    public virtual Diagram ContainingDiagram { get; set; }
}

Das Attribut „Key“ definiert den Primärschlüssel, „Required“ legt fest, dass dieser Wert in der Datenbank nicht NULL sein darf, und „ForeignKey“ definiert die Schlüsseleigenschaft, über die eine „Navigationseigenschaft“ aufgelöst werden soll (oder alternativ die Navigationseigenschaft, die die so gekennzeichnete Schlüsseleigenschaft auflöst). Weiteres dazu findet sich online unter dem Begriff „Code First Data Annotations„.

Bleibt noch der Hinweis, dass die Kennzeichnung der „Navigationseigenschaften“ (Eigenschaften, die „Entitäten“/Datenobjekte miteinander verbinden) mit virtual dafür sorgt, dass das EF „lazy loading“ einsetzen kann, um den Inhalt bereitzustellen, sprich: die Daten werden nicht sofort bereitgestellt, sondern erst abgerufen, wenn sie wirklich benötigt werden.

Einen Kontext erstellen

Nachdem die Datenklassen wie oben beschrieben bereitstehen, fehlt nur noch der DbContext, der den Zugriff auf die Datenbank kapselt:

public class DiagramContext : DbContext
{
    public DbSet<Diagram> Diagrams { get; set; }

    public static void PopulateDatebase()
    {
        using (DiagramContext dc = new DiagramContext())
        {
            Diagram dgm = new Diagram();
            dgm.Id = Guid.NewGuid();
            dgm.Name = "Ein erstes Diagramm";

            dc.Diagrams.Add(dgm);
            dc.SaveChanges();
        }
    }
}

Erfahrungen

Bislang habe ich meinen DbContext in jeder ASP.NET MVC-Action neu erstellt und mit using geklammert. Inzwischen hat sich aber gezeigt, dass beim weiterreichen von Abfrageergebnissen an Views Probleme entstehen können, wenn die Abfragen nicht mit .ToArray() oder .ToList() komplett ausgeführt wurden, da nach dem verlassen des using-Blocks der DbContext bereits „disposed“ ist. Ein besserer Weg ist das definieren eines DbContext-Attributs in der MVC-Controller-Klasse, das im Konstruktor (oder direkt) initialisiert und in einer Dispose()-Überschreibung „disposed“ wird.