Dall'archivio articoli > LINQ
Le novità di Entity Framework Core 2.0
Per poter utilizzare questa funzionalità, devi fare il login o iscriverti.
Entity Framework Core 2.0 è la seconda versione dell'O/RM prodotto da Microsoft per girare su tutte le piattaforme .NET. Questa piattaforma introduce diverse novità che semplificano notevolmente lo sviluppo in alcuni scenari. Tra queste novità ci sono gli Owned Types che sono un'evoluzione dei Complex Type di Entity Framework, Il Table Splitting che permette di ottimizzare le performance, i Model Level Filters che permettono di impostare in fase di mapping i filtri su una tabella, la complilazione esplicita delle query LINQ, l'attach di grafi di oggetti e altre piccole funzionalità. In questo articolo ci occuperemo di queste funzionalità così da avere un'idea chiara su cosa offre la nuova versioen di Entity Framework Core (EF Core d'ora in poi).
EF Core ora implementa .NET Standard 2.0. Questo significa che può essere usato su tutte le versioni di .NET Che implementano questa versione di .NET Standard: .NET Core, .NET Framework 4.6.1, Xamarin. Per maggiori informazioni su .NET Standard 2.0 potete leggere questo articolo.
Gli owned types sono l'equivalente dei value types in gergo DDD. Si tratta di tipi che non hanno un collegamento con una tabella del db, ma contengono comunque dati. Un tipico esempio di value type è l'indirizzo di una persona. Un indirizzo è formato da via, numero, cap, comune, provincia. All'interno di un progetto un indirizzo può essere di una persona, di un'azienda, può essere la location di un asset o qualunque altra cosa. Ripetere ogni volta tutti i campi per ogni entity è ripetitivo e soprattutto non permette di creare funzioni ad-hoc per l'indirizzo. In questi casi possiamo creare un owned type di tipo GenericAddress e mapparlo all'interno delle entity.
Per prima cosa creiamo l'owned type.
public class GenericAddress { public string Address { get; set; } public string City { get; set; } public string Region { get; set; } public string PostalCode { get; set; } public string Country { get; set; } }
Successivamente dobbiamo modificare l'entity per utilizzare il tipo GenericAddress invece dei singoli campi.
public partial class Customer { ... public GenericAddress Address { get; set; } }
Infine dobbiamo scrivere il codice di mapping dell'entity per utilizzare l'owned type.
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Customer>().OwnsOne(e => e.Address).Property(e => e.Address).HasColumnName("address"); modelBuilder.Entity<Customer>().OwnsOne(e => e.Address).Property(e => e.City).HasColumnName("City"); modelBuilder.Entity<Customer>().OwnsOne(e => e.Address).Property(e => e.Country).HasColumnName("Country"); modelBuilder.Entity<Customer>().OwnsOne(e => e.Address).Property(e => e.PostalCode).HasColumnName("PostalCode"); modelBuilder.Entity<Customer>().OwnsOne(e => e.Address).Property(e => e.Region).HasColumnName("Region"); }
Il metodo OwnsOne specifica che stiamo mappando un owned type mentre gli altri metodi (Property e HasColumnName) sono gli stessi che si usano anche per le entity. Per default, EF Core utilizza il nome del tipo e il nome della proprietà come nome della colonna mappata nel database. Questo significa che se non utilizziamo il metodo HasColumnName, EF Core cerca nella tabella una colonna col nome GenericAddress_Address, GenericAddress_City e così via.
Una volta completatà la creazione delle classi e del loro mapping, EF Core è in grado di leggere e scrivere sulla tabella senza problemi.
//Query var customers = ctx.Customers.Where(c => c.Address.City == "Rome"); //Scrittura var c = new Customer() { Address = new GenericAddress { City = "Milan", ... } ... } ctx.Add(c); ctx.SaveChanges();
Gli owned type sono una evoluzione dei complex type di EF in quanto permettono anche di contenere riferimenti a una entity. La proprietà City di GenericAddress è una stringa, ma se avessimo una entity City, allora potremmo modificare GenericAddress per fare in modo che la proprietà City sia di tipo City e non di tipo string. Questa funzionalità non è disponibile in Entity Framework ore e rappresenta una grossa limitazioni in alcuni scenari.
Quando abbiamo un modello con molte entity, il metodo OnModelCreating della classe di contesto può diventare molto grande e dispersivo rendendo le modifiche molto complicate. Con la nuova versione, EF Core permette di creare una classe contenente il codice di mapping di una entity e di aggiungere questa classe al mapping. In questo modo possiamo creare una classe di mapping per ogni entity rendendo il codice di mapping molto più semplice da manutenere e il metodo OnModelCreating molto più piccolo.
Un classe di mapping deve implementare l'interfaccia IEntityTypeConfiguration<T> dove T è il tipo dell'entity che la classe mappa. L'interfaccia espone il metodo Configure che accetta in input un oggetto EntityTypeBuilder tramite il quale possiamo costruire il codice di mapping. Nel prossimo esempio possiamo vedere il codice del metodo.
class CustomerConfiguration : IEntityTypeConfiguration<Customers> { public void Configure(EntityTypeBuilder<Customer> builder) { builder.HasKey(e => e.CustomerId); builder.HasIndex(e => e.CompanyName) .HasName("CompanyName"); builder.Property(e => e.CustomerId) .HasColumnName("CustomerID") .HasColumnType("nchar(5)") .ValueGeneratedNever(); //altro codice di mapping } }
Nel metodo OnModelCreating della classe di contesto dobbiamo aggiungere la classe di mapping al mapping del contesto sfruttando il metodo ApplyConfiguration del modelbuilder come mostrato nel seguente codice.
modelBuilder.ApplyConfiguration(new CustomerConfiguration());
Questa funzionalità era già presente in Entity Framework, ma non era stata portata in EF Core 1.0 suscitando reazioni negative da parte degli sviluppatori che l'hanno richiesta a gran voce proprio per la sua utilità quando si lavora con modelli che hanno tante entity.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.