Entity Framework
ADO.NET Entity Framework (until approx. 2012) , Entity Framework |
|
---|---|
Basic data
|
|
Maintainer | GitHub |
developer | Microsoft (originally) |
Publishing year | 2008 |
Current version | 6.2 (October 26, 2017) |
programming language | C # |
category | ORM framework |
License | Apache 2.0 |
GitHub |
Entity Framework Core also: EF Core |
|
---|---|
Basic data
|
|
Maintainer | GitHub |
developer | Microsoft |
Current version | 2.0.3 (May 8, 2018) |
Current preliminary version | 2.1 (May 7, 2018) |
programming language | C # |
category | ORM framework |
License | Apache 2.0 |
GitHub |
Entity Framework , or EF for short , is a framework for object-relational mapping (ORM). It was developed by Microsoft and is used for ORM on .NET object structures. Its first final version appeared as part of the .NET Framework 3.5 (Service Pack 1) in 2008. At that time it was still part of ADO.NET and was called the ADO.NET Entity Framework . For the following version, which bears the number 4.0 and appeared in 2010 as part of the .NET Framework 4.0, the framework has been significantly expanded. From version 4.1 the framework is developed independently of the .NET framework. It has been called Entity Framework since around 2012, when version 5.0 appeared and Microsoft made the framework available as an open source . From version 6.0, which appeared in 2013, the framework no longer belongs to the .NET framework.
Along with .NET Core , there has been a separate Entity Framework Core , also called EF Core , since 2016 . Since .NET Core version 3, this is an additional package and no longer automatically part of .NET Core.
Modeling approaches
Code first | Model first | |
---|---|---|
No database available | Existing classes are marked with annotations ( Table , Column ), which control the mapping to a database. Based on this, the database and database tables are modeled by the DbContext and created when the SaveChanges() method is called.
|
The entity classes are modeled with a graphic designer. On the one hand, the model is converted into entity classes with the help of the Text Template Transformation Toolkit (T4) and the associated T4 scripting language. In addition, the designer allows a SQL script to be created with which the database is created. |
Use of an existing database | The entity classes can be created, modeled and tagged manually according to the given database. However, this is very labor intensive. | With the help of an assistant, the database is queried and a suitable model is created according to the database structure. This is converted into the corresponding classes with a T4 script. |
architecture
DbContext API (EF5) | EF4 | task |
---|---|---|
DbContext | ObjectContext | Establishes a connection to the database. Provides methods for queries ( Query ), change tracking ( Tracking ) and saving ( Save ). |
DbQuery | ObjectQuery | Provides methods for adding ( Add ), attachments ( Attach ) and removing ( Remove ) of entities ready. |
DbSet | ObjectSet | Inherits from DbQuery / ObjectQuery and provides the appropriate methods for entity types. |
Change Tracker API | ObjectContext.ObjectStateManager | Provides methods for tracking changes. This includes querying the original and current state of entities. |
Validation API | - | Automatic validation of the data in the data layer. |
Code First Model Building | - | Reflects on code-based classes in order to create suitable database objects and the associated metadata in memory and in the database for them. |
|
use
Create a mapping with CodeFirst
public 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; }
// ...
}
Database initialization
The database is created in the Entity Framework by an initializer. This is executed when the first entity is added to the database context.
// 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();
}
The InitializeSimpleMembership
attribute can be used in ASP.NET MVC projects to ensure that the database is initialized.
Adding entities
using(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();
}
Query of data
Querying all data from a data record:
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)
{
// ...
}
}
}
To prevent the same database query from being executed multiple times, the ToList()
method can be used:
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) { /* ... */ }
}
Searches for a specific object in the database:
var person = context.Persons.SingleOrDefault(p => p.PersonId == personId);
or in comprehension syntax:
var person = (from p in context.Persons
where p.PersonId == personId
select p).SingleOrDefault();
method | Result |
---|---|
Single() |
Returns the one element that returned the request. Throws an exception if none or more results are returned. |
SingleOrDefault() |
Returns the one element that returned the request. Returns null if no results are returned. Throws an exception if several results are returned. |
First() |
Returns the first element if the query returns one or more results. Throws an exception if no results are returned. |
FirstOrDefault() |
Returns the first element if the query returns one or more results. Returns null if no results are returned.
|
The Find()
method is also available for Db objects . This first searches for the object in memory and makes a database query if the object is not found in memory:
var person = context.Persons.Find(personId);
Lazy, eager and explicit loading
The Entity Framework normally uses lazy loading , in which data is loaded from the database when the data is queried:
// lazy loading
// nur die Personen werden abgefragt und geladen
var persons = context.Peoples;
If further data has to be loaded, eager loading is used:
// 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);
or type safe from EF5:
// LINQ-to-Entities Beispiel für eager loading
var persons = context.Peoples.Include(p => p.Addresses).Where(p => p.FirstName == fname);
The explicit loading of the data is similar to the lazy loading , but allows the loading of the 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 Entities
Deleting an entity in 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();
}
Deleting an entity in 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
}
Precompiled queries
Database queries are compiled by the Entity Framework into queries suitable for the database interface. However, this process costs time, which is why compiled queries - if they are needed again - should not be discarded, but rather saved in an object and reused later.
To save time the first time you use a query with Entity Framework 4, queries can be precompiled.
static Func<MyDbEntities, int, ObjectQuery<Person>> QueryContactById =
CompiledQuery.Compile<MyDbEntities, int, IQueryable<Person>>( (context, personId) => context.Persons.Select(p => p.Id == personId) );
In Entity Framework 5, queries are automatically precompiled when they are created.
Transactions
using (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 Migrations
Code First Migrations is a set of PowerShell - scripts that facilitate the database migration.
- Enable migrations
- creates a migration script
- Add migration
- Create a script to create the current database structure
- Update database
- Brings the database structure to a certain state. The latest migration script is used by default.
literature
- Andrew Troelsen: Pro C # 5.0 and the .Net 4.5 Framework . Springer, 2012, ISBN 978-1-4302-4233-8 , pp. 1560 .
- Julia Lerman, Rowan Miller: Programming Entity Framework: DbContext; Querying, Changing, and Validating Your Data with Entity Framework . O'Reilly Media , 2012, ISBN 978-1-4493-1296-1 , pp. 258 .
- Julia Lerman, Rowan Miller: Programming Entity Framework: Code First; Creating and Configuring Data Models from Your Classes . O'Reilly Media, 2012, ISBN 978-1-4493-1294-7 , pp. 194 .
Web links
- Microsoft .NET Entity Framework. In: CodePlex. Microsoft, accessed on March 12, 2015 (English, project page with source code of the Entity Framework).
- Entity Framework Tutorial. Retrieved March 12, 2015 .
- Entity Framework Basics Video. Retrieved March 15, 2015 .
- Performance Considerations for Entity Framework 5. Retrieved November 11, 2012 .
- Get Started with Entity Framework (EF). In: Data Developer Center. Microsoft , accessed November 12, 2012 .
- Entity Framework Power Tools. In: Data Developer Center. Microsoft, accessed March 30, 2013 .
credentials
- ↑ Microsoft.EntityFrameworkCore on nuget.org
- ↑ Holger Schwichtenberg: Microsoft provides OR-Mapper from .NET open source , in: heise online from July 19, 2012, accessed on Dec. 7, 2015.
- ↑ Holger Schwichtenberg: Asynchronous database access with Microsoft's Entity Framework 6.0 , in: heise online from Oct. 18, 2013, accessed on Dec. 7, 2015.
- ↑ Announcing Entity Framework Core 3.1 and Entity Framework 6.4 - .NET Blog. Retrieved December 7, 2019 .
- ^ Bipin Joshi: Understanding Database Initializers in Entity Framework Code First. February 10, 2012, accessed June 10, 2014 .
- ↑ Rick Anderson: InitializeSimpleMembership Attribute and SimpleMembership Exceptions. In: MSDN Blog. Microsoft, August 15, 2012, accessed June 10, 2014 .