Entity Framework

from Wikipedia, the free encyclopedia
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

Entity Framework 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

Basic functionality of the ADO.NET Entity Framework
Overview of important ADO.NET Entity Framework objects
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.
  1. While the EF5 uses the Db classes by default, a corresponding T4 template (EF4.x DbContext Generator) is required in the EF4.

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 InitializeSimpleMembershipattribute 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();
LINQ Selectors
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 nullif 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

credentials

  1. Microsoft.EntityFrameworkCore on nuget.org
  2. Holger Schwichtenberg: Microsoft provides OR-Mapper from .NET open source , in: heise online from July 19, 2012, accessed on Dec. 7, 2015.
  3. Holger Schwichtenberg: Asynchronous database access with Microsoft's Entity Framework 6.0 , in: heise online from Oct. 18, 2013, accessed on Dec. 7, 2015.
  4. Announcing Entity Framework Core 3.1 and Entity Framework 6.4 - .NET Blog. Retrieved December 7, 2019 .
  5. ^ Bipin Joshi: Understanding Database Initializers in Entity Framework Code First. February 10, 2012, accessed June 10, 2014 .
  6. Rick Anderson: InitializeSimpleMembership Attribute and SimpleMembership Exceptions. In: MSDN Blog. Microsoft, August 15, 2012, accessed June 10, 2014 .