Datenpunkte

Coole (und kostenlose) Tools für Entity Framework

Julie Lerman

Julie Lerman Da Entity Framework inzwischen eine Open Source-Lösung darstellt, kann die Entwicklungscommunity Code unter entityframework.codeplex.com bereitstellen. Aber beschränken Sie sich nicht darauf, dort nur nach Tools und Erweiterungen zu suchen. Es gibt weitere großartige Tools, die sowohl kommerziell als auch communitygestützt sind, mit den Sie mehr aus Entity Framework herausholen können. In dieser Rubrik möchte ich einige dieser Tools und Erweiterungen hervorheben, die aus der Community stammen. Sie sind allesamt kostenlos und über die Visual Studio Gallery (für IDE-Erweiterungen) oder NuGet (für Codebibliotheken) erhältlich. Einige stammen sogar von Mitgliedern des Entity Framework-Teams, die ihr Steckenpferd sind und mit den offiziellen Lösungen nicht in Verbindung stehen.

Entity Framework Reverse POCO Code First Generator

Es gibt immer noch etliche Leute, die annehmen, der Database First-Workflow sei die einzige Möglichkeit zum Erstellen eines Modells für Entity Framework aus einer vorhandenen Datenbank. In diesem bestimmten Workflow wird eine EDMX-Datei erstellt, die Ihnen ermöglicht, mit Ihrem Modell in einem Designer zu interagieren. Die Verwendung eines Designers hat zur Folge, dass Sie von einem Codegenerator abhängig sind, um Ihre Entitätenklassen zu erstellen. Es ist jedoch dank der Rückentwicklungstools möglich, EF Code First mit einer vorhandenen Datenbank zu verwenden. Dafür stehen nun drei Möglichkeiten zur Verfügung. Bevorzugen würde ich diese Vorlage: EntityFramework Reverse POCO Code First Generator von Simon Hughes (efreversepoco.codeplex.com). Um fair zu sein, bei den anderen beiden handelt es sich um Tools, die von Microsoft erstellt wurden, welche ich ebenfalls intensiv verwendet habe. Bei einem handelt es sich um ein Feature der Betaversion von EF Power Tools, die Sie ab Mai 2011 im Blogbeitrag unter bit.ly/1ky2SAJ in Aktion erleben dürfen. Das andere ist eine Erweiterung im Visual Studio EF Designer, die im Release von Entity Framework 6.1 Tools für Visual Studio inbegriffen war. Der EF Designer bietet nun eine visuelle Möglichkeit zum Erstellen von POCOs aus einer vorhandenen Datenbank. Außerdem löst er ein Problem, das mich lange Zeit geärgert hat, indem nunmehr ausgewählt werden kann, welche Tabellen in ein Modell einbezogen werden sollen. Ich habe dieses Feature in meinem Blogbeitrag im Februar 2014 unter bit.ly/1rOqUv4 veranschaulicht.

Die Vorlage von Hughes wurde erstmals im Oktober 2012 auf CodePlex veröffentlicht, und sie beinhaltete die Möglichkeit, aus einer Teilmenge einer Datenbank von Beginn an auszuwählen. Im Prinzip bietet das Tool anscheinend sämtliche von Features, auf deren Hinzufügung oder Verbesserung ich in EF Power Tools und im neueren EF6.1 Designer gehofft hatte. Und ich bin nicht der Einzige, dem es so ergeht: Seitdem ich diese Rubrik schreibe, gab es nahezu 77.000 Downloads des Entity Framework Reverse POCO Code First Generator.

Sie können die Vorlage über das Feature für die Visual Studio-Erweiterungen und -Aktualisierungen installieren und verfügen für künftige Projekte über Offlinezugriff darauf. Alternativ können Sie es direkt im Web verwenden, wenn Sie POCOs aus einer Datenbank generieren möchten. Vor dem Hinzufügen der Vorlage sollten Sie Ihrem Projekt Entity Framework hinzufügen und die Datenbank-Verbindungszeichenfolge in Ihrer Konfigurationsdatei ausdrücklich angeben, da die Vorlage darauf beruht. Sobald Sie über EF und Ihre Verbindungszeichenfolge verfügen, initiieren Sie die Vorlage, indem Sie einem Projekt in Visual Studio ein neues Element hinzufügen. Wenn Sie die Vorlage installiert haben, finden Sie sie unter "Installiert". Öffnen Sie andernfalls den Abschnitt "Online". Beachten Sie, dass ich die Vorlagen in Abbildung 1 nicht gefiltert habe, der EntityFramework Reverse POCO Code First Generator befindet sich jedoch ganz oben in der nach Beliebtheit sortierten Liste. Diese Position hat mich ziemlich beeindruckt.

Abbildung 1 – Abrufen von EntityFramework Reverse POCO Code First Generator
Abbildung 1 – Abrufen von EntityFramework Reverse POCO Code First Generator

Das Auswählen dieses Elements führt zu einer neuen "database.tt"-Vorlagendatei in Ihrem Projekt. Die Vorlage weist eine Menge an Konfigurationen mit bereits angewendeten Standardeinstellungen auf. Sie können einen Ausschnitt der Vorlagendatei in Abbildung 2 sehen. Darin sind einige der einfacheren Konfigurationen enthalten, die Sie verwenden können, um auf den generierten Code Einfluss zu haben. Mit der Einstellung "ElementsToGenerate" können Sie die generierten (POCOs, Kontext, Fluent-Konfigurationen, UnitOfWork) Klassentypen steuern. Ein Vorteil dieser Konfiguration besteht darin, dass Sie unterschiedliche Elemente für unterschiedliche Projekte generieren können. Sie können Namespaces und die Art und Weise steuern, wie Typen benannt werden. Sie können u. a. einige grundlegenden Windows Communication Foundation-Klassen (WCF) generieren. Die Konfigurationen ermöglichen Ihnen zudem mithilfe von Regexes, anzugeben, welche Datenbanktabellen einbezogen/ausgeschlossen werden sollten, um die Muster der Tabelle anzugeben oder Namen anzuzeigen. Das Angeben von Objekten war ein wichtiges Feature für mich. Da der EF6.1 Designer jedoch mittlerweile das visuelle Auswählen von Datenbankobjekten für das Erstellen eines Code First-Modells unterstützt, erscheint mir das Angeben der Objektnamen in der ".tt"-Datei im Vergleich dazu ein wenig schwerfällig.

Abbildung 2 – ein Abschnitt der EntityFramework Reverse POCO Generator-Konfigurationsdatei
Abbildung 2 – ein Abschnitt der EntityFramework Reverse POCO Generator-Konfigurationsdatei

Ein weiterer erheblicher Vorteil den der Reverse POCO Code First Generator im Vergleich zum Reverse Engineering-Feature der EF Power Tools mit sich bringt, besteht in der Leistung. Der neue EF6.1 Designer beschleunigt die Codegenerierung jedoch erheblich, sodass dies kein maßgeblicher Umstand mehr für mich ist. Der Reverse POCO Code First Generator weist ungeachtet dessen so viele tolle Features (wie das Einbeziehen von standardmäßigen Werten für Spalten als Standardwerte für Eigenschaften) und Möglichkeiten auf, die ich immer noch mag, mit denen angepasst werden kann, wie Klassen generiert (wie das Angeben, welcher Sammlungstyp für die Navigationseigenschaften verwendet werden sollte) werden. Ich wünschte, ich könnte ihn mit dem EF Designer zusammenführen.

Die Vorlage bringt so viel mit sich, und anstelle sämtliche Features hier aufzulisten, verweise ich hiermit auf die Dokumentation und das 30-minütige Demonstrationsvideo (reversepoco.com), sodass Sie bei der Verwendung dieser Vorlage einen exzellenten Start hinlegen können. Sie werden sehen, dass Hughes Beiträge zum Projekt auf CodePlex akzeptiert. Wichtig zu beachten ist, dass der EntityFramework Reverse POCO Code First Generator derzeit mit SQL Server und SQL Server CE ausgeführt wird. Der EF6.1 Designer funktioniert mit diesen Datenbanken und allen anderen Datenbanken, die von Anbietern so aktualisiert wurden, dass sie mit EF6.1 ausgeführt werden können. Mir wurde mitgeteilt, dass die nächste große Version (v3) des Generators von Hughes in der Lage sein wird, für andere Datenbanken wie Oracle oder MySQL ein Reverse-Engineering vorzunehmen, so wie dies auch beim EF6.1 Designer der Fall ist.

Entity Framework Utilities

Die nächste Bibliothek, welche ich hervorhebe, wird durch Mikael Eliasson auf GitHub (bit.ly/UeWHGW) verwaltet. Sie können die Dienstprogramme in Ihre Projekte einbeziehen, indem Sie in NuGet nach EFUtilities suchen.

Diese Dienstprograme zielen hauptsächlich auf die Leistung ab und fügen Funktionalitäten hinzu, die Entity Framework-Entwickler lange Zeit vermisst haben: die Möglichkeit, Massenvorgänge – wie das Einfügen, Aktualisieren und Löschen – in der Datenbank auszuführen. Die Klasse "EFBulkOperation" in diesen Dienstprogrammen funktioniert mit "DbContext", sodass Sie sie nicht mit "ObjectContext" verwenden können. Auch wenn einige Entwickler das Problem angeprangert haben, kenne ich Mikael lange genug, um sein Angebot gut einschätzen zu können. Auf der CodePlex-Website für Entity Framework wird zudem eine Diskussion über die besten Ansätze geführt, wie Massenvorgänge in die systemeigene API versetzt werden können.

Mit dem Dienstprogramm können Sie LINQ-Abfragen in der Klasse "EFBulk­Operation" schreiben, um den entsprechenden Vorgang auszuführen. Zum Testen habe ich ein Modell (mithilfe des von mir erläuterten EntityFramework Reverse POCO Code First Generators) aus der AdventureWorks2012-Datenbank erstellt. In meinem Code habe ich anschließend eine Liste von 1.000 Instanzen des "BusinessEntity"-Typs erstellt:

var entityList = new List<BusinessEntity>();
for (int i = 0; i < 1000; i++)
{
  entityList.Add(new BusinessEntity{});
}

Ich habe diesen mithilfe des standardmäßigen Entity Framework-Codes eingefügt und dann "SaveChanges" benannt:

using (var context = new AWModel()) {
  context.BusinessEntities.AddRange(entityList);
  context.SaveChanges();
}

Dies führte dazu, dass 1.000 einzelne Einfügeanweisungen zu meiner SQL Server-Datenbank gesendet wurden. Der vollständige Vorgang dauerte durchschnittlich etwa 6 Sekunden über eine Anzahl wiederholter Ausführungen. Ich habe EF-Aufwärmzeiten aus diesem Timing entfernt.

Anschließend habe ich die Klasse "EFBatchOperation" verwendet, um dieselben 1.000 "BusinessEntity"-Objekte einzufügen.

using (var context2 = new AWModel()) {
  EFBatchOperation.For(context2, 
    context2.BusinessEntities).InsertAll(entityList);
}

Die durchschnittliche Ausführung dauerte etwa 12 Millisekunden.

Beachten Sie, dass ich im standardmäßigen EF-Code alle Instanzen zum Kontext hinzufügen musste, sodass über die Änderungsprotokollierung bestimmen werden könnte, welche SQL-Elemente zum Server gesendet werden müssten. Auf der anderen Seite beruht die Klasse "EFBatchOperation" nicht auf der EF-Änderungsprotokollierung, um das SQL-Element zu erstellen. Vielmehr erstellt sie eine "DataReader", die eine Klasse in "EFUtilities" ist, und streamt diese mithilfe der Klasse ".NET SqlBulkCopy" zur Datenbank, die vor einiger Zeit in ADO.NET 2.0 eingeführt wurde. Ich war erfreut darüber, da es sich um die von mir empfohlene Möglichkeit zum Lösen dieses Problems handelte. Diese Methode erzwingt nicht nur, dass der Kontext 1.000 Entitäten nachverfolgt, sie sendet auch einen einzelnen Befehl zusammen mit dem einzufügenden Binärdatenstream zur Datenbank. SQL Profiler zeigt den Stream nicht an, sodass als Ergebnis der Methode "EFBatchoperation.InsertAll" nur ein einzelner Befehl in SQL Profiler angezeigt wird:

insert bulk BusinessEntity
  ([rowguid] UniqueIdentifier,
  [ModifiedDate] DateTime)

Ein nützlicher Schutz besteht hier darin, wenn der von Ihnen verwendete Datenbankanbieter über keine Methode für Massenvorgänge verfügt, dass das Dienstprogramm auf die EF-Standardeinstellung für das Verarbeiten der Anforderung zurückgesetzt wird. In diesem Fall würde das bedeuten, dass 1.000 Einfügebefehle an die Datenbank gesendet würden.

"EFBatchOperation" weist auch Methoden auf, um Massenaktualisierungen und Massenlöschungen vorzunehmen. Und das Tolle bei diesen ist, dass Sie die Entitäten im Vorfeld weder in den Arbeitsspeicher noch in den Kontext laden müssen, wie dies mit EF der Fall wäre. Stattdessen finden Sie im Folgenden ein Beispiel, wie Sie eine Zeilenauswahl aus der Datenbank mithilfe von "EFBatchOperation" löschen würden:

EFBatchOperation.For(context, context.BusinessEntityContacts).Where(
  p => p.ContactTypeId == 11).Delete();

Es sendet das relevante SQL-Element an die Datenbank:

DELETE FROM [Person].[BusinessEntityContact] WHERE 11 = [ContactTypeID]

Die Befehle für den Massenvorgang bringen bereits erhebliche Leistungsverbesserungen mit sich. Eliasson arbeitet zudem an einem Ersatz für die Methode "DbContext.Include", um die Leistung des Eager Loading zu verbessern. Anstelle die Daten zu vereinfachen und Ressourcen in Bezug auf jede Menge redundante Daten in den Ergebnissen zu verschwenden, besteht das Ziel der Methode in EF Utilities darin, "load every Included collection as a separate query instead and then manually fix the relations. The goal is also to provide child collection filtering, sorting and, if possible, paging." (jede enthaltene Sammlung stattdessen als eine getrennte Abfrage zu laden und anschließend die Bezüge zu beheben. Das Ziel besteht außerdem darin, eine untergeordnete Sammlungsfilterung, Sortierung und Auslagerung bereitzustellen.) Unter bit.ly/1hBsGf5 finden Sie weitere Informationen über dieses Feature und können in Bezug auf seinen Fortschritt auf dem Laufenden bleiben. Beachten Sie auch die "readme.md"-Datei für dieses Projekt.

Entity Framework 6 Contrib

Entity Framework 6 Contrib ist ein Projekt auf CodePlex von Microsoft MVP Unai Zorrilla (ef6contrib.codeplex.com). Zorrilla hat sich mit einer Vielzahl an Beiträgen am Microsoft EF-Paket (beispielsweise benutzerdefinierte Pluralisierungen, "AddRange", "RemoveRange" und "AddFrom­Assembly") eingebracht – allesamt Features, die ich in früheren Rubriken oder Artikeln beschrieben habe. Zorrilla umfasst eine Handvoll an zusätzlichen Helfern, die er auf der Website ef6contrib.codeplex.com verwaltet, dazu zählen:

  • Ein vorkonfigurierter spanischer Pluralisierungsdienst (der im zuvor von mir erläuterten EntityFramework Reverse POCO Code First Generator-Projekt integriert wurde).
  • Zwei weitere bequeme Methoden für das Hinzufügen von Fluent-API-Konfigurationen zu einem Code First-Modell zur Laufzeit.
  • Einige Vorgänge, die Sie mit Code First-Migrationen verwenden können, welche nicht in EF enthalten sind, dazu zählen "DatabaseCollation", "GrantTablePermission" und "RevokeTablePermission".
  • Ein Initialisierer, der mit Migrationen funktioniert, die "DropAndMigrateDatabaseToLatestVersion" genannt werden.
  • Eine Reihe an Query Analyzer-Typen, die EF6-Interceptors und Abhängigkeitskonfliktlöser nutzen.

An Zorrillas Ergänzungen an EF mochte ich immer, dass er seinen selbst geschriebenen Code verwendet und wiederholt in seinen Arbeiten nutzt und kapselt, um ihn mit anderen zu teilen. Vor allem die Analyzer sind besonders cool. Sie können die Parameter festlegen, mit denen Sie die Leistung der EF-Datenbankausführung messen und überwachen möchten, inwiefern Ihr Code mit Ihren Erwartungen übereinstimmt. Es steht auch ein Analyzer zur Verfügung, der nach nicht parametrisierten Abfragen sucht. Wenn Sie der Klassen "DbConfiguration" (ein weiteres EF6-Feature) den Interceptor hinzufügen, analysiert er sämtliche Befehle aus einem angegebenen "DbContext". Das CodePlex-Projekt weist einige Tests und Beispiele auf, mit denen Sie den Analyzer sowie die anderen Tools kennenlernen können, die in Entity Framework 6 Contrib enthalten sind. Abbildung 3 zeigt eine "DbConfiguration"-Klasse aus den Beispielen, die den "PerformanceInterceptor" hinzufügt und dann angibt, dass er drei der vier Analyzer in der Sammlung prüfen sollte.

Abbildung 3 – Konfigurieren einiger Analyzer aus Entity Framework 6 Contrib

public class Configuration : DbConfiguration  {
    public Configuration() {
      this.AddDependencyResolver(new CustomResolver());
      this.AddInterceptor(new PerformanceInterceptor((msg =>
      {
        Console.WriteLine(msg.Message);
      })));
    }
    private class CustomResolver : IDbDependencyResolver{
      public object GetService(Type type, object key) {
        return null;
      }
      public IEnumerable<object> GetServices(Type type, object key) {
        // You can use here your preferred IoC container
        if (typeof(IPerformanceAnalyzer).IsAssignableFrom(type)) {
          return new List<IPerformanceAnalyzer>(){
             new ExecutionTimePerformanceAnalyzer(TimeSpan.FromSeconds(3)),
             new UnparametrizedWhereClausesPerformanceAnalyzer(),
             new TopSlowQueriesPerformanceAnalyzer(10)
          };
        }
        return Enumerable.Empty<object>();
      }
    }
  }

Das Konsolenfenster zeigt auf Grundlage der Konfiguration den oder die Berichte aus den Analyzern an.

EF-Erweiterungen und Tools im Überfluss

Diese sind nur einige wenige der Tools, die ich für wirklich hilfreich erachtet habe. Es gibt aber noch andere, die Sie sich ansehen sollten, aber ich kann sie hier nicht detailliert erläutern. Erik Ejlskov Jensen hat eine Liste einiger mehr oder weniger beachtenswerte Erweiterungen in seinem Blogbeitrag: "Entity Framework 6 (& SQL Server Compact) (5)–Entity Framework 6 Extensions" (bit.ly/SxxPc5) zusammengetragen. Die Liste umfasst eine aktualisierte Version von EF Caching Provider, was die Zwischenspeicherung auf zweiter Ebene für EF6 (bit.ly/UePlmU), nachverfolgbare Entitäten, einen Ersatz für die nicht mehr unterstützten Self-Tracking Entities (trackable.codeplex.com) und einige zusätzliche Projekte ermöglicht, die Massenvorgangsfunktionalitäten lösen. Ejlskov Jensen, der als SQL Server CE-MVP arbeitet, hat nicht nur zahlreiche SQL CE-bezogene Funktionen direkt in EF6 integriert, sondern verfügt auch über die äußerst beliebte Visual Studio-Erweiterung SQL Server Compact Toolbox, die viele Features umfasst, die bei der Verwendung von EF hilfreich sind. Wenn Sie SQL CE mit oder ohne EF verwenden, ist die Toolbox eine wichtige Erweiterung. Schließlich möchte ich noch auf die Arbeit von Jimmy Bogard hinweisen. Seine Blogbeiträge, die er als "Missing EF Feature Workarounds" (Lösung für fehlendes EF-Feature) bezeichnet, beinhalten eine Lösung, die EF6 so erweitert, dass es somit globale Filter für ein EF-Modell bereitstellt und als ein NuGet-Paket verfügbar ist. Weitere Informationen darüber finden Sie in seinem Blogbeitrag unter bit.ly/1prZv0a.


Julie Lerman ist Microsoft MVP, .NET Framework-Mentor und Unternehmensberaterin. Sie lebt in den Bergen von Vermont. Sie hält bei User Groups und Konferenzen in der ganzen Welt Vorträge zum Thema Datenzugriff und anderen .NET-Themen. Julie Lerman führt unter thedatafarm.com/blog einen Blog. Sie ist die Autorin von "Programming Entity Framework" (2010) sowie der Ausgaben "Code First" (2011) und "DbContext" (2012). Alle Ausgaben sind im Verlag O’Reilly Media erschienen. Folgen Sie ihr auf Twitter unter twitter.com/julielerman, und besuchen Sie ihre Pluralsight-Kurse unter juliel.me/PS-Videos.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Mikael Eliasson, Simon Hughes und Unai Zorrilla