advanced ef code first 5.0 - ef@work

19
@ EF@Work @ EF@Work EF 5.0 Code First Luca Cestola [email protected] http://it.linkedin.com/pub/luca- cestola/9/652/122

Upload: domusdotnet

Post on 22-May-2015

149 views

Category:

Technology


3 download

DESCRIPTION

Sessione "Advanced ef code first 5.0" tenuta da Luca Cestola all'evento EF@Work di DomusDotNet (http://www.domusdotnet.org/eventi/efatwork.aspx) del 5 Luglio 2013

TRANSCRIPT

Page 1: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

@EF@Work

EF 5.0 Code First

Luca [email protected]

http://it.linkedin.com/pub/luca-cestola/

9/652/122

Page 2: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• Configuration & Mapping• Validazione• Entity, oggetti «transient»• Query Custom• Concorrenza

Agenda

Page 3: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 4: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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; } } }

Page 5: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 7: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• Convezioni• Possiamo cambiarle ? Ovviamente si:• Utilizzando gli attributi del

System.ComponentModel.Annotations• Fluent API

Configuration & Mapping

Page 8: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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; ... }

Page 9: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

•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

Page 10: Advanced ef code first 5.0 - EF@work

@EF@Wor

kConfiguration & 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

Page 11: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 12: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 13: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 14: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• Per ogni proprietà di un’entità:• Current Value (get\set)• Context.Entry(entity).Property(n=>n.name).CurrentValue

• Original Value (get\set)• Context.Entry(entity).Property(n=>name).OriginalValue

• Verificare proprietà modificate:• Context.Entry(entity).Property(n=>n.name).IsModified

(Get\Set)• 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»

Page 15: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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(d

to)

Entity e oggetti «transient»

DEMO

Page 16: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 17: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

• 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

Page 18: Advanced ef code first 5.0 - EF@work

@EF@Wor

k

Entity Framework 5:http://msdn.microsoft.com/it-it/data/efBlog Entity Framework Design:http://blogs.msdn.com/b/efdesign Ado.Net Team Blog:http://blogs.msdn.com/b/adonetDomusDotNet:http://www.domusdotnet.org

Link utili

Page 19: Advanced ef code first 5.0 - EF@work

@EF@Wor

kGrazie agli sponsor