Mi piace scrivere codice e mi piace non essere troppo legato al database, non tanto perchè mi capiti spesso di cambiarlo (sinceramente quasi mai) più che altro per avere controllo completo su tutti gli strati, in particolare quello delle entità che chiaramente è trasversale a tutti gli altri.
In particolare sebbene mi trovo ad avere già il database nel progetto che sto sviluppando (di cui tral'altro non potevo cambiare più di tanto perchè utilizzato da precedenti applicazioni) ho trovato molto utile partire ugualmente dal codice per modellare "più pulito".
Inoltre fino ad oggi ho sempre sofferto il fatto di non riuscire a far ereditare la maggior parte degli oggetti da un OggettoBase come oggetto e basta, senza dover avere situazioni come Table per Hierarchy (TPH), Table per Type (TPT), Table per Concrete class (TPC) legate cmq al database:
più banalmente, volevo dare a tutte una proprietà "Id" (per me non può esistere nessun oggetto privo di un Id...) e dei campi di sistema "ModificaData", "ModificaUtente" (presenti in tutte le tabelle del database) impostati in un unico punto, e non "copiati" su tutte le varie entità.
Con linq2sql o EF < 4.1 non ero ancora in grado di farlo, ora finalmente posso fare in questo modo:
- Definire un OggettoBase con le proprietà (che specifica già il mapping sui campi):
public class OggettoBase
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("ID")]
public int ID { get; set; }
[Column("ModificaData")]
public DateTime? SYSData { get; set; }
[Column("ModificaUtente")]
public string SYSUtente { get; set; }
}
- Definire l'entità che eredita dall'OggettoBase
public class Cliente : OggettoBase
{
public string Nominativo { get; set; }
public string CodiceFiscale { get; set; }
}
- Definire la mappatura della classe che eredita, da notare che non c'è riferimento alla classe OggettoBase, mentre il MapInheritedProperties va messo prima del ToTable(...) di modo che vengano fatte le mappature anche dell'oggetto base:
class ClienteMapping : EntityTypeConfiguration<Cliente>
{
public ClienteMapping()
{
//--- non necessario, vedi update più in basso
//--- Map(x => x.MapInheritedProperties());
//--- imposto la tabella relativa all'oggetto
ToTable("CLIENTI");
//--- questa proprità ha un campo diverso dal nome della proprieta
Property(x => x.CodiceFiscale).HasColumnName("CodFisc");
//--- il resto delle proprietà non serve perchè hanno lo stesso nome
}
}
* UPDATE: Come segnalato da Tony
Pierascenzi la chiamata al metodo "MapInheritedProperties" non è necessaria in questo caso, lo fa direttamente per
noi il runtime di Entity Framework.
- Ed infine il nostro DbContext:
public class ApplicazioneContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//--- mapping
modelBuilder.Configurations.Add(new ClienteMapping());
//--- fine
base.OnModelCreating(modelBuilder);
}
public DbSet<Cliente> Clienti { get; set; }
}
Oltre alla comodità e la pulizia del codice, rimane un obbiettivo raggiunto perchè come è facile intuire, da amante del codice, mi dava proprio fastidio non riuscire a fare una cosa così banale come ereditare da un oggetto base...
In allegato il progetto d'esempio:
http://dotnethell.it/users/files/1622_EF.CodeFirst.zip