Condividi tramite


Nuove funzionalità di EF Core 2.1

Oltre a numerose correzioni di bug e piccoli miglioramenti funzionali e delle prestazioni, EF Core 2.1 include alcune nuove funzionalità interessanti:

Caricamento pigro

EF Core ora contiene i blocchi predefiniti necessari per chiunque possa creare classi di entità in grado di caricare le proprietà di navigazione su richiesta. È stato anche creato un nuovo pacchetto, Microsoft.EntityFrameworkCore.Proxies, che sfrutta tali componenti fondamentali per produrre classi proxy di caricamento lazy basate su classi di entità modificate al minimo, ad esempio classi con proprietà di navigazione virtuali.

Per ulteriori informazioni su questo argomento, vedere la sezione sul caricamento differito.

Parametri nei costruttori di entità

Come uno degli elementi costitutivi necessari per il caricamento differito, abbiamo abilitato la creazione di entità che accettano parametri nei loro costruttori. È possibile usare i parametri per inserire i valori delle proprietà, i delegati di caricamento differito e i servizi.

Per altre informazioni su questo argomento, vedere la sezione sul costruttore di entità con i parametri.

Conversioni di valori

Fino ad ora EF Core poteva mappare solo le proprietà dei tipi supportati in modo nativo dal provider di database sottostante. I valori sono stati copiati tra colonne e proprietà senza alcuna trasformazione. A partire da EF Core 2.1, le conversioni di valori possono essere applicate per trasformare i valori ottenuti dalle colonne prima che vengano applicati alle proprietà e viceversa. Sono disponibili numerose conversioni che possono essere applicate per convenzione in base alle esigenze, nonché un'API di configurazione esplicita che consente di registrare conversioni personalizzate tra colonne e proprietà. Alcune delle applicazioni di questa funzionalità sono:

  • Archiviazione di enumerazioni come stringhe
  • Mappatura di interi senza segno con SQL Server
  • Crittografia automatica e decrittografia dei valori delle proprietà

Per altre informazioni su questo argomento, vedere la sezione sulle conversioni di valori.

Traduzione LINQ GroupBy

Prima della versione 2.1, in EF Core l'operatore LINQ GroupBy verrebbe sempre valutato in memoria. È ora supportata la conversione nella clausola SQL GROUP BY nei casi più comuni.

Questo esempio mostra una query con GroupBy usata per calcolare varie funzioni di aggregazione:

var query = context.Orders
    .GroupBy(o => new { o.CustomerId, o.EmployeeId })
    .Select(g => new
        {
          g.Key.CustomerId,
          g.Key.EmployeeId,
          Sum = g.Sum(o => o.Amount),
          Min = g.Min(o => o.Amount),
          Max = g.Max(o => o.Amount),
          Avg = g.Average(o => o.Amount)
        });

La traduzione SQL corrispondente è simile alla seguente:

SELECT [o].[CustomerId], [o].[EmployeeId],
    SUM([o].[Amount]), MIN([o].[Amount]), MAX([o].[Amount]), AVG([o].[Amount])
FROM [Orders] AS [o]
GROUP BY [o].[CustomerId], [o].[EmployeeId];

Seeding dei dati

Con la nuova versione sarà possibile fornire i dati iniziali per popolare un database. A differenza di EF6, i dati di seeding sono associati a un tipo di entità come parte della configurazione del modello. Le migrazioni di EF Core possono quindi calcolare automaticamente le operazioni di inserimento, aggiornamento o eliminazione da applicare durante l'aggiornamento del database a una nuova versione del modello.

Ad esempio, è possibile utilizzare questo per configurare i dati iniziali per un Post in OnModelCreating:

modelBuilder.Entity<Post>().HasData(new Post{ Id = 1, Text = "Hello World!" });

Per altre informazioni su questo argomento, vedere la sezione sul seeding dei dati.

Tipi di query

Un modello EF Core può ora includere tipi di query. A differenza dei tipi di entità, i tipi di query non dispongono di chiavi definite e non possono essere inserite, eliminate o aggiornate (ovvero sono di sola lettura), ma possono essere restituite direttamente dalle query. Alcuni degli scenari di utilizzo per i tipi di query sono:

  • Mapping di viste senza chiavi primarie
  • Mapping di tabelle senza chiavi primarie
  • Mapping alle query definite nel modello
  • Serve come tipo restituito per le query FromSql()

Per ulteriori informazioni su questo argomento, leggere la sezione sui tipi di query.

Includi per i tipi derivati

Sarà ora possibile specificare le proprietà di navigazione definite solo sui tipi derivati durante la scrittura di espressioni per il metodo Include. Per la versione fortemente tipizzata di Include, supportiamo l'uso sia di un cast esplicito sia dell'operatore as. Sono ora supportati anche i riferimenti ai nomi delle proprietà di navigazione definite sui tipi derivati nella versione stringa di Include.

var option1 = context.People.Include(p => ((Student)p).School);
var option2 = context.People.Include(p => (p as Student).School);
var option3 = context.People.Include("School");

Per ulteriori informazioni su questo argomento, leggere la sezione su Include con tipi derivati.

Supporto di System.Transactions

È stata aggiunta la possibilità di usare le funzionalità System.Transactions, ad esempio TransactionScope. Questo funzionerà sia su .NET Framework che su .NET Core quando si usano provider di database che lo supportano.

Per altre informazioni su questo argomento, vedere la sezione su System.Transactions.

Miglioramento dell'ordinamento delle colonne nella migrazione iniziale

In base al feedback dei clienti, le migrazioni sono state aggiornate per generare inizialmente colonne per le tabelle nello stesso ordine in cui le proprietà vengono dichiarate nelle classi. Si noti che EF Core non può modificare l'ordine quando vengono aggiunti nuovi membri dopo la creazione iniziale della tabella.

Ottimizzazione delle sottoquery correlate

Abbiamo migliorato la traduzione delle query per evitare di eseguire query SQL "N + 1" in molti scenari comuni in cui l'utilizzo di una proprietà di navigazione nella proiezione comporta l'unione di dati dalla query principale con i dati di una sottoquery correlata. L'ottimizzazione richiede il buffering dei risultati dalla sottoquery ed è necessario modificare la query per acconsentire esplicitamente al nuovo comportamento.

Ad esempio, la query seguente viene normalmente convertita in una query per Clienti, più N (dove "N" è il numero di clienti restituiti) query separate per gli ordini:

var query = context.Customers.Select(
    c => c.Orders.Where(o => o.Amount  > 100).Select(o => o.Amount));

Includendo ToListAsync() nella posizione corretta, si indica che il buffering è appropriato per gli Ordini, il che consente l'ottimizzazione.

var query = context.Customers.Select(
    c => c.Orders.Where(o => o.Amount  > 100).Select(o => o.Amount).ToList());

Si noti che questa query verrà convertita in solo due query SQL: una per i clienti e quella successiva per Orders.

Attributo [di proprietà]

È ora possibile configurare tipi di entità di proprietà semplicemente annotando il tipo con [Owned] e quindi assicurandosi che l'entità proprietaria venga aggiunta al modello.

[Owned]
public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

Strumento da riga di comando dotnet-ef incluso in .NET Core SDK

I comandi dotnet-ef fanno ora parte di .NET Core SDK, pertanto non sarà più necessario usare DotNetCliToolReference nel progetto per poter usare le migrazioni o per eseguire lo scaffolding di un DbContext da un database esistente.

Per altre informazioni su come abilitare gli strumenti per versioni diverse di .NET Core SDK e EF Core, vedere la sezione relativa all'installazione degli strumenti da riga di comando l'installazione degli strumenti.

Pacchetto Microsoft.EntityFrameworkCore.Abstractions

Il nuovo pacchetto contiene attributi e interfacce che è possibile usare nei progetti per accendere le funzionalità di EF Core senza assumere una dipendenza da EF Core nel suo complesso. Ad esempio, l'attributo [Owned] e l'interfaccia ILazyLoader si trovano qui.

Eventi di modifica dello stato

È possibile usare nuovi eventi di Tracked e StateChanged in ChangeTracker per scrivere la logica che reagisce alle entità che entrano in DbContext o modificarne lo stato.

Analizzatore di parametri SQL non elaborati

Un nuovo analizzatore del codice è incluso in EF Core che rileva utilizzi potenzialmente non sicuri delle API SQL non elaborate, ad esempio FromSql o ExecuteSqlCommand. Ad esempio, per la query seguente verrà visualizzato un avviso perché minAge non è parametrizzato:

var sql = $"SELECT * FROM People WHERE Age > {minAge}";
var query = context.People.FromSql(sql);

Compatibilità del provider di database

È consigliabile usare EF Core 2.1 con provider che sono stati aggiornati o almeno testati per funzionare con EF Core 2.1.

Suggerimento

Se si riscontrano incompatibilità impreviste o problemi nelle nuove funzionalità o se si hanno commenti e suggerimenti al riguardo, segnalalo usando il tracker dei problemi.