Migrare da Entity Framework 6 ad Entity Framework Core 5

di Stefano Mostarda, in Entity Framework Core,

Quando nel 2016 .NET Core con ASP.NET Core ed Entity Framework Core fecero la loro apparizione, fu subito chiaro che la migrazione di un'applicazione da Framework a Core sarebbe stata un'impresa difficilissima. L'assenza di molte API in .NET Core unito a un cambio di paradigma di sviluppo rendeva quasi impossibile il passaggio. Grazie a .NET Standard 2.0, alla maturazione di .NET Core e soprattutto all'adozione da parte della community, molte librerie sono state adattate per funzionare sia su Framework che Core. Questo ha reso la migrazione di un'applicazione da Framework a Core molto meno complicato. In molti casi, al netto di qualche modifica a tappeto per ASP.NET Core, si può dire che il passaggio fosse quasi indolore.

La situazione tuttavia cambiava radicalmente quando l'applicazione da migrare utilizzava Entity Framework 6. Infatti, Entity Framework 6 conteneva un numero elevato di funzionalità che non erano presenti in Entity Framework Core. Inoltre, alcune funzionalità esistenti in entrambi, erano comunque implementate in modo diverso tra i framework. Per questi motivi, al fine di semplificare la migrazione, si è scelto di modificare Entity Framework 6 per fare in modo che, con piccolissime modifiche al codice dell'applicazione, potesse girare su .NET Core a partire dalla versione 3. Sebbene questo passaggio abbia notevolmente agevolato la migrazione, rimane il problema che Entity Framework 6 è un framework oramai non più evoluto, ma solo manutenuto per bug fix, e che quindi diventerà ben presto inferiore a Entity Framework Core che invece continuerà a crescere con aggiornamenti continui.

Avere un'applicazione dipendente da un prodotto che non verrà evoluto significa condannarsi ad avere un'applicazione che non potrà mai evolvere pienamente e fruire delle ultime novità tecnologiche. Se l'applicazione ha una durata ancora lunga e necessita di essere evoluta, conviene investire nella migrazione a Entity Framework Core. Laddove invece l'applicazione è stabile e non necessità di aggiornamenti o evoluzione, il porting a .NET con l'uso di Entity Framework 6 può essere una valida alternativa. Tuttavia, In questo articolo ci occuperemo della migrazione da Entity Framework 6 a Entity Framework Core 5.

Differenze tra Entity Framework 6 ed Entity Framework Core

Da un punto di vista delle API, Entity Framework 6 ed Entity Framework Core condividono molte API. Se guardiamo al codice necessario per scrivere ed aggiornare le entity, potrebbero non esserci addirittura differenze. Tuttavia, al suo interno i framework sono profondamente differenti e in alcuni casi diametralmente opposti.

La principale differenza salta all'occhio già in fase di setup dell'applicazione. Entity Framework 6 può essere importato in un'applicazione in due modi: utilizzando il designer o utilizzando solamente il codice. Entity Framework Core prevede invece il solo utilizzo del codice.

Un'altra differenza tra i due framework è la modalità di recupero della stringa di connessione. Questa differenza è data in parte dalle differenze tra .NET Framework e .NET, ma in parte anche dalle differenze di implementazione della classe DbContext.

Anche le modalità di mapping sono cambiate. Infatti, nel caso si fosse usato il mapping via codice anche con Entity Framework 6, le API di mapping sono leggermente cambiate in Entity Framework Core.

Un'altra differenza tra come i due framework è nel modo in cui trattano le relazioni molti a molti. Entity Framework 6 in alcune situazioni costringe a fare dei giri complicati mentre Entity Framework Core permette di ottenere la stessa funzionalità con codice più pulito.

L'ultima importante differenza consiste nel provider LINQ. In Entity Framework Core 5, non si ha ancora una feature parity completa con Entity Framework 6. Tuttavia, la maggior parte delle query viene tradotta al netto di alcuni casi che spesso si riescono a scoprire solo a run time.

Analizziamo nel dettaglio queste differenze e vediamo come possiamo appianarle durante una migrazione.

Entity e classe di contesto

La migrazione delle entity e della classe di contesto è probabilmente la parte più complicata dell'intero processo. Esistono due percorsi da intraprendere a seconda che si usi il file edmx in associazione col designer o che si usi solamente il codice.

Quando dobbiamo migrare codice generato dal designer tramite il file edmx, il primo step consiste nel copiare nel progetto .NET 5 i file delle entity. Al netto di un eventuale cambio di namespace, questi file possono essere portati così come sono senza alcuna modifica. Anche il file di contesto può essere portato, ma necessità di due modifiche: la rimozione del costruttore e l'implementazione del metodo OnModelCreating con il codice di mapping (di cui parleremo nella prossima sezione).

Quando dobbiamo migrare entity e classe di contesto scritti a mano, il compito è più agevole in quanto possiamo semplicemente copiare nel nuovo progetto le entity e la classe di contesto facendo attenzione a eliminare da quest'ultima eventuali costruttori e ad allineare eventualmente i namespace.

Ovviamente, questi passi rappresentano solo il primo passo del processo. Il secondo è rappresentato dalla scrittura del codice di mapping.

Codice di mapping

Ora che nel nostro nuovo progetto abbiamo sia entity che classe di contesto, dobbiamo passare alla scrittura del codice di mapping all'interno del metodo OnModelCreating. Nel caso in cui la classe di contesto è stata originariamente generata dal file edmx, questo metodo è contiene una sola riga di codice che lancia un'eccezione che va cancellata e va riempito a mano con tutte le informazioni di mapping necessarie. Nel caso in cui la classe di contesto è stata scritta a mano da noi, questo metodo è già popolato, ma vanno fatte diverse modifiche nel codice in quanto molti metodi di mapping sono diversi in Entity Framework Core. Nella seguente tabella proviamo a mappare tra loro i metodi più comuni.

Entity Framework 6 Entity Framework Core
HasRequired HasOne(lambda).IsRequired()
HasOptional HasOne(lambda)
WithOptional WithOne(lambda)
WithRequired WithOne(lambda).IsRequired()
IsOptional IsRequired(false)
WillCascadeOnDelete OnDelete
Map (relazioni) Nessun equivalente: usera metodi Has* and With*
MapToStoredProcedures Non supportato
HasDatabaseGeneratedOption ValueGenerated*
Map (ereditarietà) HasDiscriminator (TPH)

Gli altri metodi presenti in Entity Framework 6 e non menzionati in questa lista sono stati riportati in Entity Framework Core con lo stesso nome. Entity Framework Core inoltre aggiunge molti altri metodi di mapping che rispecchiano le nuove funzionalità.

Una menzione speciale la merita il modo in cui i due framework calcolano di default il nome della tabella su cui una entity mappa. Entity Framework 6 usa un servizio di pluralizzazione basato sul nome della entity mentre Entity Framework Core usa il nome del DbSet che espone la entity o il nome dell'entity stessa se questa non è esposta da un DbSet. Questa differenza può portare a errori di run time in quanto i due framework potrebbero usare nomi diversi per le tabelle. In questi casi possiamo ricorrere al metodo ToTable per assegnare il nome corretto quando mappiamo l'entity.

3 pagine in totale: 1 2 3
Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

Top Ten Articoli

Articoli via e-mail

Iscriviti alla nostra newsletter nuoviarticoli per ricevere via e-mail le notifiche!

In primo piano

I più letti di oggi

In evidenza

Misc