3. Configuration & MappingL’origine di tutto: la classe DbContextI passi minimi nell’approccio Code First:Costruire le classi che definiscono l’object Model asData Model (Importante: Code First NON è DDD )Costruire una classe derivata da DbContext(gateway per l’accesso all’entità e dati) ed esporre proprietà System.Data.Entity.DataSet<> per ognuna delle classi dell’Object ModelSe ci basiamo solo sulle convezioni nient’altro.
4. Configuration & MappingQuali convezioni?Nome database e stringa di connessioneDi default: «LocalhostQLEXPRESS», Full QualifiedTypeName del DbContextderivatoOverride: aggiungere App.Config o Web.Config con una stringa di connessione Custom il cui nome è uguale al DbContext derivato
5. Configuration & MappingQuali convezioni ? Per il mapping delle colonne abbiamo convezioni per:Chiave primarieNomi delle tabelleNomi delle colonneNomi delle relazioniForeignKeyTipiEcc…Possiamo cambiarle ? Ovviamente si:Utilizzando gli attributi del System.ComponentModel.AnnotationsFluent APIElenco delle convenzioni Code Firsthttp://msdn.microsoft.com/en-us/library/hh161541%28VS.103%29.aspx
6. Configuration & MappingAttributi MaxLenghtKeyDataType…L’utilizzo degli attributi può rendere «difficile» la lettura del codice della definizione del nostro modello dati. Configuration & MappingFluent ApiStesse funzionalità di mapping degli attributiNecessarie per scenari di mapping più complessi (nel 99,99 % dei casi reali )EntitySplitting (1 entità «spalmata» su N tabelle)Gerarchie di EreditarietàTable per ClassTable per Class HierarchyTable per Concrete ClassTableSplitting (1 tabella «spalmata» su N entità)Configurazione & mappingconcentrato in un solo punto:OverrideOnModelCreatingdella classe DbContext
7. Configuration & MappingDurante la fase di «mapping» possiamo utilizzare la collezione Configurations per:Aggiungere nuove configurazioni a quelle già presentiClassi derivate da EntityTypeConfiguration<> o ComplexTypeConfiguration<> secondo dei casiRimuovere configurazioni esistentiPossiamo utilizzare la collezione Conventions per rimuovere le convenzioni esistenti:modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()PluggableConventions non supportate (in questa versione) Per ogni istanza della classe derivata da DbContext, tramite la proprietà Configuration possiamo impostare (abilitate per default):AutoDetectChangesEnabled LazyLoadingEnabledProxyCreationEnabledValidateOnSaveEnabled
8. Configuration & MappingInizializzazione del databaseCancella e crea in ogni casoDatabase.SetInitializer<Db>(new DropCreateDatabaseAlways<Db>());Crea se non esisteDatabase.SetInitializer<Db>(new CreateDatabaseIfNotExists<Db>());Cancella e crea se il modello cambia (Attenzione!)Database.SetInitializer<Db>(new DropCreateDatabaseIfModelChanges<Db>());Strategia CustomDatabase.SetInitializer<Db>(new DbCustomDatabaseStrategy()); DEMO
9. ValidazionePerché ‘Validare ?’Dati corretti Risparmiare round trip sul server (SQL Azure)In EF 4.1Abilitata per defaultUtilizza attributi (DataAnnotations.ValidationAttribute)Validazione automatica dei ComplextTypeSupporta l’interfaccia IValidatableObjectAttributi su NavigationProperties e Collection (validità della proprietà e non degli elementi)
10. ValidazioneQuando viene eseguita ?Prima della persistenza dei datiOn-demand per singola entitàOn-demand per singola proprietàSe la validazione non ha successo:DbEntityValidationException (EntityValidationErrors)DbEntityValidationResult (ValidationErrors)ValidationErrorPerché non System.ComponentModel.DataAnnotations.Validator?Non esegue la validazione automatica dei ComplexTypeDEMO
11. ProprietàPer ogni proprietà di un’entità:Current Value (getet)Context.Entry(entity).Property(n=>n.name).CurrentValueOriginal Value (getet)Context.Entry(entity).Property(n=>name).OriginalValueVerificare proprietà modificate:Context.Entry(entity).Property(n=>n.name).IsModified (Getet)Forzare l’Updatedurante il SaveChanges() anche se Original Value e Current Value coincidonoCurrent, Original e Database Values:Context.Entry(entity).CurrentValues()Context.Entry(entity).OriginalValues()Context.Entry(entity).GetDatabaseValues()
12. ProprietàOriginal e CurrentValues da un altro oggetto: Consideriamo un DTO del tipo:new Book {Title=‘Pippo’ , ISBN=‘Franco’};Il DTO viene utilizzato da Services Layerper la comunicazione tra stratiValorizzare la entity da modificareContext.Entry(entity).CurrentValues.SetValues(dto)DEMO
13. Persistenza e QueryAbbiamo visto nella sessione di Alessandro l’utilizzo di LINQ per l’interrogazione dei dati.
14. Persistenza e QueryStored ProcedureNon c’è un supporto diretto al mapping di Stored Procedure come ad esempio in Model First.
20. ConcorrenzaConcorrenza (ottimistica):Specifichiamo le proprietà interessate Attributo [ConcurrencyCheck]Due possibili strategie:StoreWinsUtilizziamo il metodo Reload() per sovrascrivere i dati dell’entity con quelli presenti nel databaseClient WinsSostituiamo i valori originali dell’entity con quelli del database GetDatabaseValues() (eliminazione delle incogruenze)DEMO
21. Futuro (Entity Framework 4.2)Rilasciata la CTP a Giugno 2011 e la Beta 1 ad Agosto 2011EnumSpatialTypeTable-ValuedfunctionsStored Procedure con result sets multipliOttimizzazione delle query nei modelli Table-per-Type (TPT)Query Linq automaticamente compilate e «cached»Entity Data Model con diagrammi multipliStored Procedure mappate automaticamente a ComplexTypeMiglioramenti e aggiunge di funzionalità all’Entity Data DesignerCode First Sql MigrationEvoluzione del database in sincronia con l’evoluzione del modello Code First