2. Entity
Framework
- ObjectContext und DbContext
- EDMX/XML und POCO entity
- Entities [ Validierung | Concurrency, DetectChanges, Change-Tracking ]
- Mapping
- Migration
- Eager-, Lazy- und Explicit Loading, Query Projections
- Ausblick auf Entity Framework 6
3. ObjectContext und DbContext
DbContext seit EF4 eine vereinfachte alternative zum
ObjectContext und das primäre Objekt für die
Interaktion mit einer Datenbank mit einem eigenen
Modell. Trotzdem ist es möglich auf die darunter
liegenden Basistypen ObjectContext und ObjectSet
zuzugreifen.
Die primäre Ausrichtung seit EF4.3 ist der Code-First
bzw. Model-First Ansatz mit Datenbankinitialisierung
oder auch bei einer vorhandenen Datenbank.
public class DemoDBContext : DbContext
{
public DbSet<Postalcode> Postalcodes { get; set; }
public DemoDBContext() :
base(@"Data Source=VAIOSQLEXPRESS;Integrated" +
"Security=SSPI;Initial Catalog=Demo")
{
this.Configuration.ValidateOnSaveEnabled = true;
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.AutoDetectChangesEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
4. EDMX/XML und POCO entity
EDMX/XML
• Beim Model-First Ansatz, werden vom
Model-Designer die Information des
konzeptionellen Modells, des
Speichermodells und die Zuordnung
zwischen diesen Informationen in einer
XML Datei mit der Dateiendung EDMX
gespeichert.
• Grafische Unterstützung zur Entwicklung
des Modells
• Reverse Engineerung eines vorhandenen
Datenbankschemas
POCO (Plain Old CLR Object)
• POCO Entities sind einfache konzeptionelle
Klassen-Modelle mit öffentlichen Properties.
• Impementierung des IPOCO Interface nicht
notwendig, wenn DbContext verwendet wird ->
Verwendung des Interface wird nicht mehr
empfohlen
• POCO-Klassen erleichtert die Nutzung des EF im
Application Design (z.B. DDD)
• DB Schema Mapping durch Annotation oder
Fluent-API
• Bessere Validierung des Modells durch
Implementierung von IValidatableObject
5. Entities
Validierung (IValidatableObject)
• Server- und Client-seitige Validierung durch das EF möglich
• Vielfältige Valdierungsmöglichkeit durch Annotation und Fluent-Api
• Implementierung von IValidateObject ermöglicht komplexere und
anwendungsspezifische Validierung
Mapping Beispiel durch Fluent-Api
public class Blog : IValidatableObject
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string BloggerName { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public IEnumerable<ValidationResult>
Validate(ValidationContext validationContext)
{
if (Title == BloggerName)
{
yield return new ValidationResult
("Blog Title cannot match Blogger Name", new[]
{ "Title", “BloggerName” });
}
}
}
Concurrency, DetectChanges,
Change-Tracking
• Concurrency
• Pesimistic concurrency (Locking)
• Not supported in EF
• Optimistic concurrency
• Konflikhandhabung mit OptimisticConcurrencyException
• Concurrency Mode = Fixed, bzw. IsCurrencyToken überprüft
Model Property auf Veränderungen vor dem speichern.
(Ausnahme Navigation Properties)
• Funktioniert nicht mit Store Procedures
• Tracking Property „Timestamp“ anstelle von IsCurrencyToken
verwendbar.
• DetectChanges
• Default: „optimistic concurrency“
• Change-tracking proxies
Dynamische Proxy-Entity-Klassen die zur Laufzeit vom EF erstellt werden. EF
überprüft Änderungen vor dem Aufruf der SaveChanges Methode
Vorraussetzung:
• Implementierung von zwei IPOCO Interfaces (IEntityWithChange und
IEntityWithRelationships)
• Public/Protected virtual properties
6. Mapping
• Das Mapping wird beschreibt die Datentypen und
das Verhalten beim Laden und Speichern der Entität
• Migration und die Standart-Validierung durch
Mapping
• Model-First erstellt automatisch ein Mapping
zwischen dem konzeptionellen und dem
Datenbankschema
• Im Code-First Ansatz kann über die Annotation oder
über die Fluent-Api das Mapping zwischen Db und
Model manuell festgelegt oder überschrieben
werden
Mapping Beispiel durch Fluent-Api
public class CustomerMap : EntityTypeConfiguration<Customer>
{
public CustomerMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
// Table & Column Mappings
this.ToTable("Customer");
this.Property(t => t.Id)
.HasColumnName("cust_Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(t => t.Name)
.HasColumnName("cust_Name")
.HasMaxLength(100)
.IsRequired().IsConcurrencyToken();
this.Property(t => t.Address)
.HasColumnName("cust_Address")
.HasMaxLength(200);
}
}
7. Migration
Console:> add-migration <Name>
Migration vorbereiten
Optionale Parameter:
- Verbose
Ausgabe auf der Konsole
- Force
Überschreibt eine vorhandene Migration
Console:> updata-database
Ausführen der Migration
Optionale Parameter:
- Verbose
Ausgabe auf der Konsole
- TargetMigration:<„Name der Migration“|int>
Rollback oder Migration der Datebank zu einem bestimmten Stand
- Script
Erstellung der Migration als SQL-Skript. Das Verzeichnis für die Migration kann Konifguriert
werden
- Script –SourceMigration:$InitialDatabase –
TargetMigration:<„Name der Migration“>
Migration von ein SQL-Skript aus
- SourceMigration
Nur in Verbindung mit Script anwendbar. Angabe der Ausgangsmigration
• Migration des Datenbankschema durch Code-First
• Versionierung des Schemas mit Rollback-Funktion
• Automatischer Abgleich des Modells mit Db Schema
möglich – aber kein MUSS
• Plain SQL weiterhin möglich
8. Eager-, Lazy- und Explicit Loading, Query
Projections
• Lazy Loading
Laden der Daten erst beim Zugriff
Vorraussetzung ist
• POCO Klasse muss „Public“ und darf nicht „ Sealed“ sein
• Der Navigation Property der „Lazy“ geladen wird muss als „virtual“ deklariert
sein
DbContext.Configuration.LazyLoadingEnabled=true (Default)
• Eager Loading
Laden der Daten mit nur einem Query
Vorraussetzung ist
• LazyLoading ist deaktiviert
• Nutzung der Include(„<Name der Entität>“)-Methode in der Abfrage
DbContext.Configuration.LazyLoadingEnabled=false
from f in context.Families.Inclue(„Pets“).select f;
• Explicit Loading
Laden der Daten explizit mit der Load-Methode
Vorraussetzung ist
• LazyLoading ist deaktiviert
• Nutzung der Load()-Methode zum laden des Komplex-Typen einer Entität
DbContext.Configuration.LazyLoadingEnabled=false
var theFamilies = context.Families.ToList();
theFamilies[0].Pets.Load();
• Query Projections
Lade der Daten mit Filterung durch eigene queries (Linq oder SQL)
var famsandpets = from f in context.Families
let returnAllPets = f.Pets.Any(p => p.Type == "Reptile")
select new { Family = f, Pets = f.Pets .Where(p => returnAllPets
? true : false) };
9. Ausblick auf das Entity Framework 6
• Async Query und Save
Unterstützt das neue Feature async und await
• Custom Code First Convention
Größere Unterstützung zur Beschreibung der eigenen Namenskonvention
• Multi-Tenant Migrations (Multiple
Contexts per Database)
Unterstüzung für mehrere Models in einer Datenbank
• Configurable Migrations History Table
Möglichkeit zur Erweiterung der _migrationsHistroy Tabelle
• Code-Based Configuration
• Dependency Resolution
• Support für Enums, Spatial Datentypen
• Stored Procedures und Funktionen in
Code-First
• Connection Resiliency
Ermöglicht eine erneute Ausführung der Datenbankoperation wenn die
Datenbankverbindung verloren gegangen ist
• Und wie immer ….besser Performance