Entity Framework
Entity Framework, kurz auch EF, ist ein Framework für objektrelationale Abbildung (ORM). Es wurde von Microsoft entwickelt und dient dem ORM auf .Net-Framework- sowie auf .NET-Objektstrukturen. Seine erste finale Version erschien als Teil des .NET Framework 3.5 (Service Pack 1) im Jahr 2008. Damals trug es den Namen ADO.NET Entity Framework. Für die folgende Version, die die Nummer 4.0 trägt und 2010 als Teil des .NET Framework 4.0 erschien, wurde das Framework deutlich erweitert. Ab der Version 4.1 wird das Entity Framework unabhängig von der Entwicklung des .NET Frameworks fortgeführt. Etwa seit dem Jahr 2012, in dem die Version 5.0 erschien und Microsoft das Framework quelloffen verfügbar machte, heißt es Entity Framework. Ab der Version 6.0, die 2013 erschien, gehört das Framework nicht mehr zum .NET Framework.[2][3] Einhergehend mit .NET Core gibt es seit 2016 das separate Framework Entity Framework Core, das auch EF Core genannt wird. Seit der .NET Core Version 3 ist dieses ein Zusatzpaket und nicht mehr automatisch Bestandteil von .NET Core.[4] Modellieransätze
Architektur![]()
VerwendungErstellen eines Mappings mit CodeFirstpublic class MyDbEntities : DbContext
{
public IDbSet<Person> Persons { get; set; }
// Fluent Configurations
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().ToTable("People");
modelBuilder.Entity<Person>().Property(p => p.FirstName).IsRequired();
// ...
}
}
[Table("People")]
public class Person
{
[Key]
[Column("PersonId")]
public int Id { get; set; }
[Required]
[MaxLength(255)]
public string FirstName { get; set; }
[Required]
[MaxLength(255)]
public string LastName { get; set; }
// ...
}
Datenbank-InitialisierungDie Datenbank wird im Entity Framework durch einen Initializer angelegt. Dieser wird ausgeführt, wenn das erste Entity dem Datenbankkontext hinzugefügt wird.[5] // setze Initialisierer
Database.SetInitializer(new DropCreateDatabaseAlways<MyDbEntities>());
using (var context = new MyDbEntities())
{
var person = new Person() {
FirstName = "William",
LastName = "Adama",
DateOfBirth = DateTime.Now
};
context.Persons.Add(person); // Datenbank-Initialisierer wird ausgeführt
context.SaveChanges();
}
In ASP.NET MVC Projekten kann das Hinzufügen von Entitiesusing (var context = new MyDbEntities())
{
// Erstelle zwei Personen-Entities
var person1 = new Person() {
FirstName = "William",
LastName = "Adama",
DateOfBirth = DateTime.Now
};
var person2 = new Person() {
FirstName = "Laura",
LastName = "Roslin",
DateOfBirth = DateTime.Now
};
// Erstelle ein Adressen-Entity
var address = new Address() {
Street = "Market Street 70",
City = "Philadelphia",
State = "PA",
Zip = "12345"
};
// Erste Variante
context.Persons.Add(person1);
// Zweite Variante
// mit dem Kontext verlinken und als hinzugefügt markieren.
context.Entry(person2).State = EntityState.Added;
// Dritte Variante
// Das Entity wird an ein bereits vom Kontext beobachtetes Entity gehängt
person1.Address.Add(address);
// Speichere Änderungen am Kontext in der Datenbank
context.SaveChanges();
}
Abfrage von DatenAbfragen aller Daten aus einem Datensatz: using (var context = new MyDbEntities())
{
foreach (var person in context.Persons) // entspricht SELECT * FROM [Persons]
{
// führt zusätzliche SQL-Abfragen an die Adresses-Tabelle
// mit einem entsprechenden JOIN aus
foreach (var address in person.Adresses)
{
// ...
}
}
}
Um zu verhindern, dass dieselbe Datenbankabfrage mehrfach ausgeführt wird, kann die using (var context = new MyDbEntities())
{
var persons = context.Persons;
// Datenbankabfrage wird ausgeführt und als Liste zurückgegeben
var allPersons = persons.ToList();
// Keine weitere Datenbankabfragen durch Verwendung der Liste
foreach (var person in allPersons) { /* ... */ }
foreach (var person in allPersons) { /* ... */ }
}
Sucht ein bestimmtes Objekt in der Datenbank: var person = context.Persons.SingleOrDefault(p => p.PersonId == personId);
oder in Comprehension Syntax: var person = (from p in context.Persons
where p.PersonId == personId
select p).SingleOrDefault();
Bei Db-Objekten steht zudem die var person = context.Persons.Find(personId);
Lazy, Eager und Explicit LoadingDas Entity Framework verwendet im Normalfall lazy loading, bei dem Daten aus der Datenbank erst dann geladen werden, wenn die Daten abgefragt werden: // lazy loading
// nur die Personen werden abgefragt und geladen
var persons = context.Peoples;
Falls weitere Daten mitgeladen werden müssen, wird eager loading verwendet: // eager loading
// Adressen werden bereits bei der Abfrage der Personen geladen
var persons = context.Peoples.Include("Addresses");
// LINQ-to-Entities Beispiel für eager loading
var persons = context.Peoples.Include("Addresses").Where(p => p.FirstName == fname);
oder typsicher ab EF5: // LINQ-to-Entities Beispiel für eager loading
var persons = context.Peoples.Include(p => p.Addresses).Where(p => p.FirstName == fname);
Das explizite Laden (explicit loading) der Daten ist ähnlich dem lazy loading, erlaubt jedoch das Laden der Navigationseigenschaften (navigation properties). // explicit loading
var persons = context.Peoples; // wie lazy loading; Adressen werden nicht mitgeladen
foreach (var person in persons)
{
person.Addresses.Load(); // explicit loading; navigation properties für Adressen werden geladen
foreach (var address in person.Addresses)
{
// ...
}
}
Delete EntitiesLöschen eines Entities im Entity Framework 4: using (var context = new MyDbEntities())
{
// Abfrage eines Entities aus der Datenbank
var person = context.Persons.SingleOrDefault(p => p.Id == id);
if (person == null)
return;
context.Persons.DeleteObject(person);
context.SaveChanges();
}
Löschen eines Entities im Entity Framework 5: using (var context = new MyDbEntities())
{
// Abfrage eines Entities aus der Datenbank
var person = (for p in context.Persons.SingleOrDefault(p => p.Id == id);
if (person == null)
return;
context.Entry(person).State = EntityState.Deleted; // Entity zur Löschung markieren
context.SaveChanges(); // Entity in der Datenbank löschen
}
Vorkompilierte AbfragenDatenbankanfragen werden vom Entity Framework in für die Datenbankschnittstelle passende Anfragen kompiliert. Dieser Vorgang kostet jedoch Zeit, weshalb kompilierte Anfragen – sofern diese erneut benötigt werden – nicht verworfen, sondern in einem Objekt gespeichert und später wiederverwendet werden sollten. Um bei der ersten Verwendung einer Abfrage mit dem Entity Framework 4 Zeit zu sparen, können Abfragen vorkompiliert werden. static Func<MyDbEntities, int, ObjectQuery<Person>> QueryContactById =
CompiledQuery.Compile<MyDbEntities, int, IQueryable<Person>>( (context, personId) => context.Persons.Select(p => p.Id == personId) );
Im Entity Framework 5 werden Abfragen automatisch bei der Erstellung vorkompiliert. Transaktionenusing (var context = new MyDbEntities())
{
using (var scope = new TransactionScope())
{
// Der TransactionScope sucht den neuesten Context auf dem
// Stacktrace und verlinkt sich automatisch mit diesem
try
{
// Bearbeitung von Entities
context.SaveChanges(); // Speichern der Änderungen in der Datenbank
scope.Complete(); // Transaktion wird abgeschlossen
}
catch (InvalidOperationException e)
{
// Transaktion fehlgeschlagen
}
} // scope.Dispose()
} // context.Dispose()
Code First MigrationsCode First Migrations ist eine Reihe von Powershell-Skripten, welche die Datenbankmigration erleichtern.
Literatur
Weblinks
Einzelnachweise
|
Portal di Ensiklopedia Dunia