Data Points

Mehr Licht bei EF6, EF7 und ASP.NET 5

Julie Lerman

Julie LermanIn meiner Data Points-Kolumne vom Januar 2015 "Ausblick auf Entity Framework 7" habe ich anhand des Status der EF7 Alpha-Version zum damaligen Zeitpunkt hervorgehoben, was in EF7 alles kommen wird. Im Dezember 2014, gerade als diese Ausgabe der Kolumne in Druck ging, traf das EF-Team eine wichtige Entscheidung zur Staffelung der EF7-Versionen. In letzter Minute gelang es mir noch, dem Artikel zwei Sätze hinzuzufügen: "Gemäß dem Beitrag unter bit.ly/1ykagF0, "EF7 – Priorities, Focus, and Initial Release", wird sich die erste Version von EF7 auf Kompatibilität mit ASP.NET 5 konzentrieren. In den Folgeversionen wird der Funktionsumfang erweitert."

Seither fand ich es etwas verwirrend herauszufinden, was das genau bedeuten soll. Ich möchte sicher sein, dass Sie tatsächlich verstehen, worauf diese erste Version von EF7 abzielt, ob Sie sie verwenden sollten und welche Optionen Sie haben.

Ich möchte den Unterschied zur nächsten Version von Microsoft .NET Framework vorstellen und erläutern, worauf ASP.NET 5-Apps ausgeführt werden. Ich biete eine allgemeine Beschreibung. Wenn Sie ausführlichere Informationen wünschen, lesen Sie den Artikel von Daniel Roth, "Die ASP.NET 5 Runtime im Detail", in der Ausgabe vom März 2015. Dann werde ich erläutern, wie EF6 und EF7 ins Bild passen.

ASP.NET 5 (auch bekannt als ASP.NET vNext) wurde so entwickelt, dass weniger Abhängigkeit vom vollständigen .NET Framework und sogar von Windows selbst besteht. Unter dem Dach von ASP.NET 5 können Sie Webanwendungen und Web-APIs mithilfe der neuen kombinierten Funktionen in ASP.NET MVC6, Klassenbibliotheken und sogar eine Konsolenanwendung erstellen. Wenn Sie sich ASP.NET als eine Möglichkeit zum Erstellen von Websites vorstellen, ist die Konsolenanwendung ein Rätsel. Doch ASP.NET 5 bietet tatsächlich eine neue "Version" von .NET Framework, auf dem Apps basieren können. In der Tat verfügt diese neue Version derzeit über zwei Ausprägungen – eine, die in der vollständigen Common Language Runtime (CLR) ausgeführt wird, und eine andere, die in der neuen CoreCLR ausgeführt wird. Eine dritte, die in einer plattformübergreifenden CLR ausgeführt wird, kommt in Kürze. Die am stärksten optimierte Version heißt .NET Core, die in der optimierten Runtime mit Namen CoreCLR ausgeführt wird. Wenn Sie zurück an Ihren Einstieg in .NET Framework denken, erinnern Sie sich vielleicht, dass Microsoft die Common Language Infrastructure (CLI) definiert hat, bei der es sich um eine Spezifikation handelt. Anschließend hat Microsoft die CLR basierend auf der CLI erstellt. Mono ist eine andere Implementierung der CLI, die unter Linux und Mac OS X ausgeführt wird. .NET-Apps waren immer von der Verfügbarkeit einer CLI-Implementierung abhängig. Die meisten von uns haben Visual Studio und Windows zum Erstellen von .NET-Apps verwendet, die von der CLR abhängig sind. Xamarin gewinnt immer mehr an Beliebtheit beim Entwickeln von Apps, die in Mono ausgeführt werden können.

CoreCLR und Entity Framework

Mittlerweile hat Microsoft eine optimierte Implementierung der CLI mit dem Namen CoreCLR entwickelt, die nicht nur Open Source ist, sondern auch über NuGet und andere Paket-Manager verteilt werden kann. Dies bietet Entwicklern die Möglichkeit, schlanke Apps zu erstellen, die sich hervorragend für mobile Geräte und cloudbasierte Serveranwendungen eignen. Außerdem entfällt die Einschränkung, dass Apps nur auf Windows-Computern bereitgestellt werden können.

Entity Framework 6 (und früher) ist vom vollständigen .NET Framework und der vollständigen CLR abhängig und kann nicht mit Apps ausgeführt werden, die auf die CoreCLR abzielen. Doch EF7 wurde mit einer Reihe kleinerer, zusammensetzbarer APIs entwickelt, die basierend darauf, was Sie brauchen, kombiniert und angepasst werden können. Wenn Sie beispielsweise mit einem nicht relationalen Datenspeicher arbeiten wollen, benötigen Sie nicht die relationalen oder Migrationsfeatures, die für relationale Datenbanken vorgesehen sind. Bei EF7 befindet sich diese Logik in einer separaten DLL, die Sie nicht benötigen, um Daten abzurufen und in den Speicher zu laden.

Wenn Sie auf die CoreCLR abzielen, erfolgt dies durch Auswahl der richtigen Laufzeitumgebung. Als Begleitung zu ASP.NET 5 hat Microsoft die K Runtime Environment (KRE) entwickelt. Hierbei handelt es sich laut ASP.NET MVP Gunnar Peipman um "... den Code, der für das Bootstrapping und Ausführen einer ASP.NET vNext-Anwendung erforderlich ist. Die K Runtime wird vor ihrer Veröffentlichung umbenannt werden. Halten Sie nach dieser Änderung Ausschau. Beispielsweise wird der KVM (Versions-Manager) zum DNVM (.NET-Versions-Manager). Die Runtime umfasst Elemente wie das Kompilierungssystem, SDK-Tools und die systemeigenen CLR-Hosts" (bit.ly/1x9rpOn). Es gibt 32-Bit- und 64-Bit-Versionen der KRE, die die CoreCLR unterstützen. In Abbildung 1 werden diese als ASP.NET 5-Zielanwendungsoptionen gezeigt.

Auswählen der Ziel-KRE in einer ASP.NET 5-Anwendung
Abbildung 1: Auswählen der Ziel-KRE in einer ASP.NET 5-Anwendung

Die einfachste Möglichkeit, EF7 in einer Anwendung in Aktion zu erleben (neben dem Demovideo in meinem Pluralsight-Kurs "Looking Ahead to Entity Framework 7" [bit.ly/18ct13F]), ist die Verwendung der ASP.NET 5-Projektvorlage, die Ihnen eine einsatzbereite Lösung mit EF7 zum Ermöglichen einer identitätsbasierten Authentifizierung für Ihre Anwendung bietet.

Starten Sie, indem Sie zunächst eine ASP.NET-Webanwendung und dann die Webvorlage "ASP.NET 5 Starter" wählen (siehe Abbildung 2).

Erstellen einer neuen ASP.NET 5-Anwendung mit vorkonfiguriertem Entity Framework 7
Abbildung 2: Erstellen einer neuen ASP.NET 5-Anwendung mit vorkonfiguriertem Entity Framework 7

Sie werden feststellen, dass die Pakete "EF7 EntityFramework.SqlServer" und "EntityFramework.Commands" bereits ausgewählt sind. Das Paket "SqlServer" bewirkt, dass seine Abhängigkeiten (EntityFramework.Core, EntityFramework.Relational) integriert werden.

Sie können dies in der Datei "project.json" erkennen, in der im Abschnitt mit den Abhängigkeiten die Pakete für NuGet aufgelistet sind. Es folgen einige Zeilen aus diesem Abschnitt:

"dependencies": {
  "EntityFramework.SqlServer": "7.0.0-beta2",
  "EntityFramework.Commands": "7.0.0-beta2",
  "Microsoft.AspNet.Mvc": "6.0.0-beta2",

Im Abschnitt mit den Verweisen werden standardmäßig die Verweise für die ASP.NET 5.0- und ASP.NET Core 5.0-Versionen der Anwendung aufgelistet. Abbildung 3 zeigt die Auflistung mit den erweiterten ASP.NET Core 5.0-Verweisen. Da die Vorlage derzeit auf die Version "beta2" abzielt, wird auf das Paket "Migrations" verwiesen. Doch in einer späteren Version wird "Migrations" Teil der relationalen API.

Beide ASP.NET 5.0- und ASP.NET Core 5.0-Verweise enthalten Entity Framework 7-Pakete und -APIs
Abbildung 3: Beide ASP.NET 5.0- und ASP.NET Core 5.0-Verweise enthalten Entity Framework 7-Pakete und -APIs

ASP.NET 5 und EF7 nutzen in großem Maß die Abhängigkeitsinjektion (Dependency Injection, DI). In der Datei "Startup.cs" des Projekts in Abbildung 4 gibt es Logik zum Informieren der App, dass sie Entity Framework, dessen SQL Server-API und den einzelnen vordefinierten "DbContext" für die Sicherheit, ApplicationDbContext, verwenden soll. Sie sehen auch, dass derselbe Kontext als Identitätsdienst für die Anwendung eingerichtet ist. Die Verbindungszeichenfolge wird in der Datei "config.json" gespeichert, und der Startkonstruktor richtet diese Datei so ein, dass die Anwendung sie bei Bedarf finden kann.

Abbildung 4: Auszug aus der Standarddatei "Startup.cs"

public class Startup {
  public Startup(IHostingEnvironment env) {
    Configuration = new Configuration()
      .AddJsonFile("config.json")
      .AddEnvironmentVariables();
  }
  public IConfiguration Configuration { get; set; }
  public void ConfigureServices(IServiceCollection services) {
    services.AddEntityFramework(Configuration)
      .AddSqlServer()
      .AddDbContext<ApplicationDbContext>();
    services.AddIdentity<ApplicationUser, IdentityRole>(Configuration)
      .AddEntityFrameworkStores<ApplicationDbContext>();
       services.AddMvc();  }

Die Projektvorlage wird nun standardmäßig zum Verwenden von EF7 und dessen Logik eingerichtet, und zwar unabhängig davon, ob Sie für die optimierte CoreCLR oder vollständiges .NET Framework entwickeln. Standardmäßig ist das Projekt nicht so definiert, dass es unter der CoreCLR ausgeführt werden soll, sondern das vollständige .NET Framework verwenden soll. Lassen Sie uns nun anschauen, wo diese Option passend ist.

Die vollständige CLR für ASP.NET 5 (und Entity Framework)

Für .NET Framework steht als Update .NET Framework 4.6 an, das Ihnen weiter ermöglicht, wie bislang alle möglichen Arten von Software zu entwickeln, von Windows Forms- und Web Forms- zu Windows Presentation Foundation (WPF)- und ASP.NET MVC 5-Anwendungen. Dank der anderen in Abbildung 1 gezeigten KRE-Versionen ("KRE-CLR-amd64" und "KRE-CLR-x86") ist es auch möglich, eine ASP.NET 5-Anwendung basierend auf dem vollständigen .NET Framework auszuführen. Dadurch haben Sie die volle Kontrolle, wenn Sie auch von anderen neuen Features von ASP.NET 5 profitieren möchten, z. B. von MVC 6 oder der neuen Web-API, die eine Fusion von MVC-Controllern und Web-API darstellt. Sie erhalten auch Abwärtskompatibilität, da Sie für das vollständige .NET Framework und die CLR entwickeln und auf dessen vollständigen Satz von Features zugreifen können. Standardmäßig gibt die Datei "project.json" an, dass die Anwendung unter beiden Versionen der CLR ausgeführt werden können soll:

"frameworks": {
      "aspnet50": { },
      "aspnetcore50": { }
    },

Sie könnten die Zeile "aspnetcore50" (und das Komma am Ende der vorherigen Zeile) vollständig entfernen, was zwei Auswirkungen hätte. Erstens würde der Abschnitt "ASP.NET Core 5.0" im Projektmappen-Explorer nicht mehr unter "Verweise" angezeigt. Zweitens würden sich die in Abbildung 1 gezeigten KRE-Ziele auf ausschließlich die KRE-CLR-Optionen reduzieren.

Sie würden immer noch für EF7 entwickeln und in den Genuss aller Vorzüge dieser neuen Version kommen. Aber was bislang nicht offensichtlich war, ist, dass die KRE-CLR mit Entity Framework 6 kompatibel ist, weil sie auf das vollständige .NET Framework abzielt. Das bedeutet, dass wenn Sie über vorhandene EF6-Logik verfügen, es möglich ist, diese in Kombination mit ASP.NET 5 (jedoch nicht mit der CoreCLR-Version) zu verwenden, und dabei in den Genuss der Vorteile der neuen Features von ASP.NET 5 zu kommen, ohne dass Sie Ihren EF6-Code an EF7 anpassen müssen.

ASP.NET 5 (vollständige CLR) mit EF6

Wohl wissend, dass es möglich ist, musste ich natürlich versuchen, mit EF6 in einer ASP.NET 5-Lösung zu arbeiten. Bedenken Sie allerdings, dass mein Ansatz hierfür sich sehr wohl ändern kann, und zwar aufgrund der sehr frühen Version, die ich (im Februar 2015) gerade nutze, im Vergleich zu freigegebenen Versionen von ASP.NET 5 und Visual Studio 2015.

Ich habe festgestellt, dass der wichtigste Faktor beim Erreichen meines Ziels das Hinzufügen der Entity Framework-Logik und Abhängigkeiten zu einem Projekt war, das vom ASP.NET 5-Projekt getrennt war. Ich entwerfe meine Anwendungen in der Regel immer auf diese Weise, anstatt alle Ebenen meiner App in einem einzelnen Projekt zu verwalten. Bei einem dedizierten Projekt für EF müssen Sie sich darum kümmern, dass die ASP.NET 5-App EF7-APIs dynamisch einbindet.

Anstatt mit dem Webprojekt "ASP.NET 5 Starter" zu beginnen, sollten Sie besser die leere ASP.NET-Projektvorlage wählen. In der Datei "project.json" ist mit "Microsoft.Asp.NET.Server.IIS" nur eine Abhängigkeit angegeben.

Als Nächstes erstellen Sie ein zweites Projekt. Ich habe ein .NET 4.6-Klassenbibliotheksprojekt gewählt. Ich habe dann über die Paket-Manager-Konsole EF6 installiert und dabei auf NuGet.org als Paketquelle und die Klassenbibliothek als Standardprojekt gezeigt. An diesem Punkt konnte ich wie schon immer "install-package entityframework" aufrufen. Dadurch wurden die Dateien "entityframework.dll" und "entityframework.sqlserver.dll" dem Projekt hinzugefügt.

Zum Testen habe ich die einfache Klasse "Ninja.cs" erstellt (weil EF6 für mich die Ninja-Edition und EF7 die Samurai-Edition ist):

public class Ninja {
    public int Id { get; set; }
    public string Name { get; set; }
  }

Ich habe auch einen "DbContext" erstellt, der ein "DbSet" von Ninjas verfügbar gemacht hat:

public class NinjaContext : DbContext {
  public NinjaContext()
    :base(@"Data Source=(localdb)\mssqllocaldb;
          Initial Catalog=NinjaContext;
          Integrated Security=True;"){ }
  public DbSet<Ninja> Ninjas { get; set; }
}

Zum Vereinfachen der Tests habe ich die SQL Server-Verbindungszeichenfolge direkt in meiner "DbContext"-Klasse hartcodiert.

Nachdem ich mein Modell definiert habe, kann ich wie schon immer Migrationen aktivieren, eine neue Migration hinzufügen und die Datenbank erstellen. Nachdem ich EF6 in das Datenprojekt installiert hatte, behielt ich die Datei "app.config" bei, die das Paket erstellt hat, damit ich dieses Projekt als Startprojekt festlegen konnte und die Migrationsbefehle anschließend ordnungsgemäß funktionieren würden. Ich habe auch die Seed-Methode "DbMigrationsConfiguration" verwendet, um für die Datenbank vorab ein Seeding mit ein paar Ninjas auszuführen.

Ich möchte EF nicht direkt aus der ASP.NET 5-Anwendung aufrufen, um eine Verwirrung bei den Versionen zu vermeiden. Ich verfüge deshalb in meinem EF6-Projekt über eine Klasse, die die Abfragen kapselt, die ich benötige. Ich habe sie "Repository" genannt, da dies meinem Zweck entspricht, doch ist dies keine Klasse, die dem Repositorymuster folgt. Dies ist bei einer Demo-App und einzelnen Abfrage keine große Herausforderung, doch bei komplexeren Apps können Sie Ihr bevorzugtes Muster für die zweckbezogene Trennung befolgen:

public class Repository  {
  public List<Ninja> GetAllNinjas() {
    using (var context=new NinjaContext())
    {
      return context.Ninjas.ToList();
    }
  }
}

Nach Einrichtung des Datenzugriffsprojekts kann ich zum ASP.NET 5-Projekt zurückkehren. Ich habe einen einfachen Controller zum Abrufen und Zurückgeben einer Sicht erstellt:

public class NinjaController : Controller
  {
    public IActionResult Index()
    {
      var repo = new Repository();
        return View(repo.GetAllNinjas());
      }
    }
  }

Außerdem habe ich eine einfache "Index.cshtml"-Datei erstellt, die die vom Controller übergebenen Ninjas auflistet:

@model List<EF6Model.Ninja>
@{
  ViewBag.Title = "EF6 Ninjas";
}
@foreach (var item in Model)
{
  @Html.Label(item.Name);
}

Abbildung 5 zeigt schließlich Code, der der Datei "Startup.cs" hinzugefügt wurde, um die MVC-Dienste einzufügen und die Weiterleitung zum Ninja-Controller anzugeben.

Abbildung 5: Startklasse zum Konfigurieren der ASP.NET 5-App, die Entity Framework 6 verwendet

public class Startup  {
  public void Configure(IApplicationBuilder app) {
    app.UseMvc(routes =>
    {
      routes.MapRoute(
      name: "default",
      template: "{controller}/{action}/{id?}",
      defaults: new { controller = "Ninja", action = "Index" });
     });
  }
  public void ConfigureServices(IServiceCollection services)  {
    services.AddMvc();
  }
}

Ich habe auch das Framework "aspnetcore50" aus der Datei "project.json" entfernt, um sicherstellen, dass ich nur für die vollständige CLR entwickle.

Dank der Datenbank und einiger von Migrationen erstellten Seeddaten kann ich erkennen, dass die ASP.NET 5-App im EF6-basierten Projekt funktioniert, indem ich Daten anzeige, die mit EF6 abgerufen wurden (siehe Abbildung 6).

ASP.NET 5-Anwendung, die Daten über Entity Framework 6 anzeigt
Abbildung 6: ASP.NET 5-Anwendung, die Daten über Entity Framework 6 anzeigt

Werde ich ab sofort mit EF7 und ASP.NET 5 arbeiten?

Ich möchte in die neuen Funktionen von EF7 gern kennenlernen und erfahren, wie sie optimal genutzt werden. Ich möchte mich auch näher mit dem neuen Weg bei der Programmierung beschäftigen, den ASP.NET 5 öffnet. Die CoreCLR wird während ihrer Weiterentwicklung ebenso wie EF7 funktionsreicher werden. Ich bin beeindruckt vom Stadium von EF7, das mit ASP.NET 5 veröffentlicht wird. Aber da ich keine Webentwicklerin bin, habe ich keinen Grund, in Produktionscode mit der topaktuellen Version von ASP.NET zu arbeiten. Das EF-Team hat außerdem klargestellt, dass die erste Version von EF7, die als Vorabversion gekennzeichnet wird, nur mit ASP.NET 5-Anwendungen verwendet werden sollte. Andernfalls gibt das Team den Rat zu warten, bis EF7 als markttaugliche Version freigegeben wird. Daher werde ich wohl die nachfolgenden Versionen von EF7 abwarten, aber dennoch weiter mit meinem Projekt experimentieren und es weiterentwickeln, um mich mehr mit den Features von EF6 vertraut zu machen, die ich ansonsten verpassen würde.

Die CoreCLR ist für meinen Geschmack derzeit noch zu sehr "das Neueste vom Neuesten". Wenn ich ein Szenario finde, das sich dafür eignet, was in der vollständigen CLR-Version von ASP.NET 5 sowie in der Featurepalette der Vorabversion von EF7 zur Verfügung steht, werde ich diesen Weg gern beschreiten. Es ist allerdings wahrscheinlicher, dass ich letztlich doch eher auf die nachfolgenden Versionen warte. Und bis dahin werden ASP.NET 5 und die CoreCLR wohl noch funktionsreicher sein. Für mich persönlich bietet die Zeit bis dahin eine Gelegenheit, mehr über diese Tools zu erfahren, die für die spätere Version in Vorbereitung sind.

In der Zwischenzeit empfehle ich die Lektüre von Scott Guthries Blogbeitrag mit der "Einführung in ASP.NET 5" unter bit.ly/1wV4zzm, um sich ein besseres Verständnis aller neuen Features zu verschaffen, die ASP.NET 5 zu bieten hat. Die zusammensetzbaren APIs sind nur eine der vielen interessanten Verbesserungen, von denen Entwickler profitieren werden.


Julie Lerman ist Microsoft MVP, .NET-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 dem folgenden technischen Experten für die Durchsicht dieses Artikels: Rick Strahl
Rick Strahl ist Chef von West Wind Technologies auf der schönen Hawaii-Insel Maui. Zwischen Windsurfausflügen und anderen Abenteuern beschäftigt sich Stachelfrisurträger Rick seit mehr als 25 Jahren mit der Softwareentwicklung. Seit den ganz frühen Tagen des Internets, als man noch eine Handkurbel oder (ein Paar Drahtspleißer) brauchte, um online zu gehen, arbeitet er an der Entwicklung von Unternehmens- und Webanwendungen. Heute entwickelt Rick clientorientierte Webanwendungen und -dienste für Kunden mit HTML5, JavaScript und mobilen Webtechnologien mithilfe AngularJS am Front-End und dem ASP.NET-Stapel und Microsoft-Technologien im Back-End. Ricks Unternehmen, West Wind Technologies, produziert auch verschiedene Tools für Entwickler, so z. B. West Wind WebSurge, West Wind Web Monitor und Html Help Builder.  Rick pflegt außerdem unter github.com/RickStrahl zahlreiche Open Source-Bibliotheken. Seinen Blog finden Sie unter weblog.west-wind.com. Über rstrahl@west-wind.com können Sie direkt Kontakt mit ihm aufnehmen.