EF@Work
EF@Work
EF 5.0 Code First
Luca Cestola
Luca.cestola@domusdotnet.org
http://it.linkedin.com/pub/luca-cestola/9/652/122
EF@Work
• Configuration & Mapping
• Validazione
• Entity, oggetti «transient»
• Query Custom
• Concorrenza
Agenda
EF@Work
• L’origine di tutto: la classe DbContext
• I passi minimi nell’approccio Code First:
• Costruire le classi che definiscono l’object
Model as Data Model
• Costruire una classe derivata da DbContext
• Esporre proprietà
System.Data.Entity.DBSet<> per ognuna delle
classi dell’Object Model che si vuole rendere
direttamente accessibili
• Se ci basiamo solo sulle convezioni:
nient’altro.
Configuration & Mapping
EF@Work
• Convezioni
• Nome database e stringa di connessione
• Di default: LocalDb o SQLEXPRESS, Full Qualified
Type Name del DbContext derivato
• Type Discovery
• Tipi definiti nei DbSet<>
• Tipi referenziati dai DbSet (anche se in assembly differenti)
Configuration & MappingIn assenza di una ConnectionString specifica viene utilizzato localDb o SQLExpress. Nel caso in cui siano
installati entrambi, viene privilegiato SQLExpress.
Default
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
{
...
}
}
Nome database
“CarRental.EF5.DataAccess.CarRentalDB”
Nome specifico
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
: base("CarRentalDatabase")
{
...
}
}
Nome database “CarRentalDatabase”
Connection string
<configuration>
<connectionStrings>
<add name="CarRentalDatabase"
providerName="System.Data.SqlServerCe.4.0"
connectionString="Data
Source=CarRental.sdf"/>
</connectionStrings>
</configuration>
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
: base("CarRentalDatabase")
{
...
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
: base("name=CarRentalDatabase")
{
...
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
: base("<connection string SQLServer> ")
{
...
namespace CarRental.EF5.DataAccess
{
public class CarRentalDB : DbContext
{
public DbSet<Domain.Car> Cars { get; set; }
public DbSet<Domain.Optional> Optionals { get; set; }
public DbSet<Domain.Customer> Customers { get; set; }
public DbSet<Domain.Rent> Rent { get; set; }
}
}
EF@Work
• Convenzioni
• Nomi delle tabelle (Plurale basato su grammatica inglese)
• Nomi delle colonne (nome della property)
• Chiave primaria (property «Id» o «ClasseId», identity se int o guid)
• Navigation properties
• Proprietà che hanno per tipo un’altra entity
• Foreign Key
• Proprietà con stesso tipo della PK a cui si riferiscono, con nome:
[NomeProprietà][NomePK]
[NomeClassePK][NomePK]
[NomePK]
• Tipi i tipi base (in EF5 anche enum, DbGeography e DbGeometry)
• Ecc… (http://msdn.microsoft.com/en-US/data/jj679962)
Configuration & Mapping
EF@Work
• Convenzioni
• Complex type
• Ogni classe referenziata nel model senza PK e non
inclusa in collection
• Tipi di relazioni
• Sono relazioni tutte le property che fanno riferimento ad
un’altra entity
• Rimuovere le convenzioni
• PluralizingTableNameConvention,
ComplexTypeDiscoveryConvention, ecc… (http://msdn.microsoft.com/en-
us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx)
• Custom Convention?
• … in EF6!
Configuration & Mapping
DEMO
EF@Work
• Convezioni
• Possiamo cambiarle ? Ovviamente si:
• Utilizzando gli attributi del
System.ComponentModel.Annotations
• Fluent API
Configuration & Mapping
EF@Work
• Convezioni
• Annotation
• Key
• Column
• MaxLength
• ForeignKey
• …
• L’utilizzo degli attributi può rendere «difficile» la
lettura del codice della definizione del nostro
modello dati.
Configuration & Mapping
DEMO
[MetadataType(typeof(CarMetadata))]
public partial class Car
{
...
}
public class CarMetadata
{
// I metadati sono associati a semplici Field
// con lo stesso nome e tipo della Property che descrivono.
[Required]
[Display(Name = "Engine size (cc)")]
public string EngineSize;
...
}
EF@Work
• Fluent Api
• Stesse funzionalità di mapping degli attributi
• Necessarie per scenari di mapping più complessi (nel 99,99 % dei
casi reali )
• Entity Splitting (1 entità «spalmata» su N tabelle)
• Gerarchie di Ereditarietà
• Table per Class
• Table per Class Hierarchy
• Table per Concrete Class
• Table Splitting (1 tabella «spalmata» su N entità)
• Configurazione & mapping concentrato in un solo punto:
• Override OnModelCreating della classe DbContext
• Relazioni: http://msdn.microsoft.com/en-us/data/jj591620
Configuration & Mapping
DEMO
EF@Work
Configuration & Mapping
DEMO
• Durante la fase di «mapping» possiamo utilizzare la
collezione Configurations per:
• Aggiungere nuove configurazioni a quelle già presenti
• Classi derivate da
• EntityTypeConfiguration<>
• ComplexTypeConfiguration<>
• Per ogni istanza della classe derivata da DbContext,
tramite la proprietà DbContext.Configuration possiamo
impostare (abilitate per default):
• AutoDetectChangesEnabled
• LazyLoadingEnabled
• ProxyCreationEnabled
• ValidateOnSaveEnabled
EF@Work
• Inizializzazione del database
• Cancella e crea in ogni caso
• Database.SetInitializer<Db>(new
DropCreateDatabaseAlways<Db>());
• Crea se non esiste
• Database.SetInitializer<Db>(new CreateDatabaseIfNotExists<Db>());
• Cancella e crea se il modello cambia (Attenzione!)
• Database.SetInitializer<Db>(new
DropCreateDatabaseIfModelChanges<Db>());
• Strategia Custom derivante da IDatabaseInitializer<>
• Database.SetInitializer<Db>(new DbCustomDatabaseStrategy());
Configuration & Mapping
EF@Work
• Perché ‘Validare’ ?
• Dati corretti (ma dai  ?)
• Risparmiare round trip sul server (SQL Azure)
• In EF 5
• Abilitata per default
• Utilizza attributi (DataAnnotations.ValidationAttribute)
• Validazione automatica dei Complext Type
• Supporta l’interfaccia IValidatableObject
• IEnumerable<ValidationResult> Validate(ValidationContext
validationContext)
• È buona pratica non alterare i dati durante una validazione
custom
Validazione
EF@Work
• Quando viene eseguita ?
• Prima della persistenza dei dati (SaveChanges)
• On-demand per singola entità
• On-demand per singola proprietà
• Se la validazione non ha successo:
• Exception DbEntityValidationException (EntityValidationErrors)
• DbEntityValidationResult (ValidationErrors)
• ValidationError
Validazione
DEMO
EF@Work
• Per ogni proprietà di un’entità:
• Current Value (getset)
• Context.Entry(entity).Property(n=>n.name).CurrentValue
• Original Value (getset)
• Context.Entry(entity).Property(n=>name).OriginalValue
• Verificare proprietà modificate:
• Context.Entry(entity).Property(n=>n.name).IsModified
(GetSet)
• Forzare l’Update durante il SaveChanges() anche se Original
Value e Current Value coincidono
• Current, Original e Database Values:
• Context.Entry(entity).CurrentValues()
• Context.Entry(entity).OriginalValues()
• Context.Entry(entity).GetDatabaseValues()
Entity e oggetti «transient»
EF@Work
• Original e Current Values da un altro
oggetto:
• Consideriamo un DTO del tipo:
• new Book {Title=‘Pippo’ , ISBN=‘Franco’};
• Il DTO viene utilizzato da Services Layer per
la
comunicazione tra strati dell’applicazione
• Valorizzare la entity da modificare:
• Context.Entry(entity).CurrentValues.SetValues(dto)
Entity e oggetti «transient»
DEMO
EF@Work
• Non c’è un supporto diretto al mapping di
Stored Procedure se non tramite il
designer, come ad esempio in Model
First.
• Possiamo utilizzare alcuni «helper» di
DbContext e DbSet
• DbContext.Cars.SqlQuery (con Tracking)
• DbContext.Database.SqlQuery<Cars> (No Tracking)
• DbContext.Database.ExecuteSqlCommand("EXECUTE
[dbo].[GetAllCars]"); (No Tracking)
Query custom
DEMO
EF@Work
• Concorrenza (ottimistica):
• Specifichiamo le proprietà interessate
• Attributo [ConcurrencyCheck]
• Due possibili strategie:
• Database wins:
Utilizziamo il metodo
DbContext.Entity(istanza).Reload() per sovrascrivere i
dati dell’entity con quelli presenti nel database
• Client Wins:
Sostituiamo i valori originali dell’entity con quelli del
database GetDatabaseValues() (eliminazione delle
incongruenze)
Concorenza
DEMO
EF@Work
Entity Framework 5:
http://msdn.microsoft.com/it-it/data/ef
Blog Entity Framework Design:
http://blogs.msdn.com/b/efdesign
Ado.Net Team Blog:
http://blogs.msdn.com/b/adonet
DomusDotNet:
http://www.domusdotnet.org
Link utili
EF@Work
Grazie agli sponsor

Advanced ef code first 5.0 - EF@work

  • 1.
    EF@Work EF@Work EF 5.0 CodeFirst Luca Cestola Luca.cestola@domusdotnet.org http://it.linkedin.com/pub/luca-cestola/9/652/122
  • 2.
    EF@Work • Configuration &Mapping • Validazione • Entity, oggetti «transient» • Query Custom • Concorrenza Agenda
  • 3.
    EF@Work • L’origine ditutto: la classe DbContext • I passi minimi nell’approccio Code First: • Costruire le classi che definiscono l’object Model as Data Model • Costruire una classe derivata da DbContext • Esporre proprietà System.Data.Entity.DBSet<> per ognuna delle classi dell’Object Model che si vuole rendere direttamente accessibili • Se ci basiamo solo sulle convezioni: nient’altro. Configuration & Mapping
  • 4.
    EF@Work • Convezioni • Nomedatabase e stringa di connessione • Di default: LocalDb o SQLEXPRESS, Full Qualified Type Name del DbContext derivato • Type Discovery • Tipi definiti nei DbSet<> • Tipi referenziati dai DbSet (anche se in assembly differenti) Configuration & MappingIn assenza di una ConnectionString specifica viene utilizzato localDb o SQLExpress. Nel caso in cui siano installati entrambi, viene privilegiato SQLExpress. Default namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext { ... } } Nome database “CarRental.EF5.DataAccess.CarRentalDB” Nome specifico namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext : base("CarRentalDatabase") { ... } } Nome database “CarRentalDatabase” Connection string <configuration> <connectionStrings> <add name="CarRentalDatabase" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=CarRental.sdf"/> </connectionStrings> </configuration> namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext : base("CarRentalDatabase") { ... namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext : base("name=CarRentalDatabase") { ... namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext : base("<connection string SQLServer> ") { ... namespace CarRental.EF5.DataAccess { public class CarRentalDB : DbContext { public DbSet<Domain.Car> Cars { get; set; } public DbSet<Domain.Optional> Optionals { get; set; } public DbSet<Domain.Customer> Customers { get; set; } public DbSet<Domain.Rent> Rent { get; set; } } }
  • 5.
    EF@Work • Convenzioni • Nomidelle tabelle (Plurale basato su grammatica inglese) • Nomi delle colonne (nome della property) • Chiave primaria (property «Id» o «ClasseId», identity se int o guid) • Navigation properties • Proprietà che hanno per tipo un’altra entity • Foreign Key • Proprietà con stesso tipo della PK a cui si riferiscono, con nome: [NomeProprietà][NomePK] [NomeClassePK][NomePK] [NomePK] • Tipi i tipi base (in EF5 anche enum, DbGeography e DbGeometry) • Ecc… (http://msdn.microsoft.com/en-US/data/jj679962) Configuration & Mapping
  • 6.
    EF@Work • Convenzioni • Complextype • Ogni classe referenziata nel model senza PK e non inclusa in collection • Tipi di relazioni • Sono relazioni tutte le property che fanno riferimento ad un’altra entity • Rimuovere le convenzioni • PluralizingTableNameConvention, ComplexTypeDiscoveryConvention, ecc… (http://msdn.microsoft.com/en- us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx) • Custom Convention? • … in EF6! Configuration & Mapping DEMO
  • 7.
    EF@Work • Convezioni • Possiamocambiarle ? Ovviamente si: • Utilizzando gli attributi del System.ComponentModel.Annotations • Fluent API Configuration & Mapping
  • 8.
    EF@Work • Convezioni • Annotation •Key • Column • MaxLength • ForeignKey • … • L’utilizzo degli attributi può rendere «difficile» la lettura del codice della definizione del nostro modello dati. Configuration & Mapping DEMO [MetadataType(typeof(CarMetadata))] public partial class Car { ... } public class CarMetadata { // I metadati sono associati a semplici Field // con lo stesso nome e tipo della Property che descrivono. [Required] [Display(Name = "Engine size (cc)")] public string EngineSize; ... }
  • 9.
    EF@Work • Fluent Api •Stesse funzionalità di mapping degli attributi • Necessarie per scenari di mapping più complessi (nel 99,99 % dei casi reali ) • Entity Splitting (1 entità «spalmata» su N tabelle) • Gerarchie di Ereditarietà • Table per Class • Table per Class Hierarchy • Table per Concrete Class • Table Splitting (1 tabella «spalmata» su N entità) • Configurazione & mapping concentrato in un solo punto: • Override OnModelCreating della classe DbContext • Relazioni: http://msdn.microsoft.com/en-us/data/jj591620 Configuration & Mapping DEMO
  • 10.
    EF@Work Configuration & Mapping DEMO •Durante la fase di «mapping» possiamo utilizzare la collezione Configurations per: • Aggiungere nuove configurazioni a quelle già presenti • Classi derivate da • EntityTypeConfiguration<> • ComplexTypeConfiguration<> • Per ogni istanza della classe derivata da DbContext, tramite la proprietà DbContext.Configuration possiamo impostare (abilitate per default): • AutoDetectChangesEnabled • LazyLoadingEnabled • ProxyCreationEnabled • ValidateOnSaveEnabled
  • 11.
    EF@Work • Inizializzazione deldatabase • Cancella e crea in ogni caso • Database.SetInitializer<Db>(new DropCreateDatabaseAlways<Db>()); • Crea se non esiste • Database.SetInitializer<Db>(new CreateDatabaseIfNotExists<Db>()); • Cancella e crea se il modello cambia (Attenzione!) • Database.SetInitializer<Db>(new DropCreateDatabaseIfModelChanges<Db>()); • Strategia Custom derivante da IDatabaseInitializer<> • Database.SetInitializer<Db>(new DbCustomDatabaseStrategy()); Configuration & Mapping
  • 12.
    EF@Work • Perché ‘Validare’? • Dati corretti (ma dai  ?) • Risparmiare round trip sul server (SQL Azure) • In EF 5 • Abilitata per default • Utilizza attributi (DataAnnotations.ValidationAttribute) • Validazione automatica dei Complext Type • Supporta l’interfaccia IValidatableObject • IEnumerable<ValidationResult> Validate(ValidationContext validationContext) • È buona pratica non alterare i dati durante una validazione custom Validazione
  • 13.
    EF@Work • Quando vieneeseguita ? • Prima della persistenza dei dati (SaveChanges) • On-demand per singola entità • On-demand per singola proprietà • Se la validazione non ha successo: • Exception DbEntityValidationException (EntityValidationErrors) • DbEntityValidationResult (ValidationErrors) • ValidationError Validazione DEMO
  • 14.
    EF@Work • Per ogniproprietà di un’entità: • Current Value (getset) • Context.Entry(entity).Property(n=>n.name).CurrentValue • Original Value (getset) • Context.Entry(entity).Property(n=>name).OriginalValue • Verificare proprietà modificate: • Context.Entry(entity).Property(n=>n.name).IsModified (GetSet) • Forzare l’Update durante il SaveChanges() anche se Original Value e Current Value coincidono • Current, Original e Database Values: • Context.Entry(entity).CurrentValues() • Context.Entry(entity).OriginalValues() • Context.Entry(entity).GetDatabaseValues() Entity e oggetti «transient»
  • 15.
    EF@Work • Original eCurrent Values da un altro oggetto: • Consideriamo un DTO del tipo: • new Book {Title=‘Pippo’ , ISBN=‘Franco’}; • Il DTO viene utilizzato da Services Layer per la comunicazione tra strati dell’applicazione • Valorizzare la entity da modificare: • Context.Entry(entity).CurrentValues.SetValues(dto) Entity e oggetti «transient» DEMO
  • 16.
    EF@Work • Non c’èun supporto diretto al mapping di Stored Procedure se non tramite il designer, come ad esempio in Model First. • Possiamo utilizzare alcuni «helper» di DbContext e DbSet • DbContext.Cars.SqlQuery (con Tracking) • DbContext.Database.SqlQuery<Cars> (No Tracking) • DbContext.Database.ExecuteSqlCommand("EXECUTE [dbo].[GetAllCars]"); (No Tracking) Query custom DEMO
  • 17.
    EF@Work • Concorrenza (ottimistica): •Specifichiamo le proprietà interessate • Attributo [ConcurrencyCheck] • Due possibili strategie: • Database wins: Utilizziamo il metodo DbContext.Entity(istanza).Reload() per sovrascrivere i dati dell’entity con quelli presenti nel database • Client Wins: Sostituiamo i valori originali dell’entity con quelli del database GetDatabaseValues() (eliminazione delle incongruenze) Concorenza DEMO
  • 18.
    EF@Work Entity Framework 5: http://msdn.microsoft.com/it-it/data/ef BlogEntity Framework Design: http://blogs.msdn.com/b/efdesign Ado.Net Team Blog: http://blogs.msdn.com/b/adonet DomusDotNet: http://www.domusdotnet.org Link utili
  • 19.