Dato questo tipo di contesto:
public class FooContext : DbContext
{
public FooContext(DbContextOptions<FooContext> opts) : base(opts)
{ }
public DbSet<Bar> Bars { get; set; }
}
Posso andare in un Bar
in due modi:
fooContext.Bars.Add(new Bar()); // Approach 1
o
fooContext.Set<Bar>().Add(new Bar()); // Approach 2
Qual è la differenza tra i due approcci?
Ho provato a rispondere alla mia domanda:
Set<T>()
crea anche un DbSet<T>
) DbSet<T>
specificamente sugli URL dei documenti, ma qui non sembrano DbSet<T>
risultati pertinenti DbSet<T>
che suggerisce semplicemente che puoi ottenere un set attraverso uno dei due metodi (non se c'è o non c'è differenza) Set<T>()
che non hanno informazioni rilevanti Ma non sono riuscito a trovare una buona spiegazione su quale dei due sia utilizzato per quale scopo. Qual è la differenza? O forse ancora più importante: dove e come dovrei essere in grado di trovarlo nei documenti?
Fanno esattamente la stessa cosa. La vera domanda è quando userete l'uno rispetto all'altro.
Usi DbSet quando conosci il tipo di entità con cui vuoi giocare. Devi semplicemente scrivere il nome DbContext, quindi il nome del tipo di entità e puoi creare, leggere, aggiornare o eliminare le voci per questa entità con i metodi di entità disponibili. Sai cosa vuoi e sai dove farlo.
Usa Set quando non conosci il tipo di entità con cui vuoi giocare. Diciamo, volevi costruire una classe che funzioni nel tuo repository per creare, leggere, aggiornare ed eliminare voci per un'entità. Volete che questa classe sia riutilizzabile in modo da poter semplicemente passare un DbContext su di essa e utilizzerà gli stessi metodi di creazione, lettura, aggiornamento ed eliminazione. Non sai con certezza su quale DbContext verrà utilizzato o su quale DbSet avrà DbContext. Ecco quando usi generici in modo che la tua classe possa essere utilizzata da qualsiasi DbContext per qualsiasi DbSet.
Ecco un esempio di una classe che puoi usare per creare qualsiasi entità su qualsiasi DbSet in qualsiasi DbContext
public class Repository<TDbContext> where TDbContext : DbContext
{
private TDbContext _context { get; }
public Repository(TDbContext context)
{
_context = context;
}
public TEntity Create<TEntity>(TEntity entity) where TEntity : class
{
if(entity != null)
{
var dataSet = _context.Set<TEntity>();
if(entity is IEnumerable)
{
dataSet.AddRange(entity);
}
else
{
dataSet.Add(entity);
}
_context.SaveChanges();
}
return entity;
}
}
E questo è come usarlo.
var dbContext01 = new DbContext01();
var dbContext02 = new DbContext02();
var repository01 = new Repository<DbContext01>(dbContext01);
var repository02 = new Repository<DbContext02>(dbContext02);
repository01.Create(new EntityOnDbContext01 {
Property01A = "String",
Property01B = "String"
});
repository02.Create(new EntityOnDbContext02 {
Property02A = 12345,
Property02B = 12345
});
Ecco un link se vuoi saperne di più sui farmaci generici. È fantastico.
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
Sfortunatamente al momento non troverete spiegazioni nella documentazione ufficiale, principalmente perché tutte queste sono funzionalmente equivalenti.
In primo luogo, i metodi generici di DbConext
come Add<TEntity>
, Remove<TEntity>
, Attach<TEntity>
ecc. Sono completamente equivalenti ai corrispondenti DbSet<TEntity>
(attualmente attualmente sono l'implementazione del successivo, ovvero i metodi DbSet
semplicemente chiamare il metodo generico DbContext
corrispondente). Quello che usi è solo una questione di gusti.
Secondo, la proprietà DbSet<TEntity>
e Set<TEntity>
sono funzionalmente equivalenti, ma presentano alcune differenze non funzionali.
Le proprietà DbSet
vengono popolate una volta durante la creazione del contesto, mentre il metodo Set
esegue sempre una ricerca, pertanto l'accesso alla proprietà DbSet
deve essere più veloce del metodo Set
(anche se non significativo).
La differenza importante è in realtà la convenzione di tipo EF Core Include and Excluding Types :
Per convenzione, i tipi esposti in proprietà
DbSet
nel proprio contesto sono inclusi nel modello. Inoltre, sono inclusi anche i tipi menzionati nel metodoOnModelCreating
.
Quindi, mentre puoi mantenere il tuo DbContext
senza le proprietà DbSet
esposte e lavorare solo con il metodo Set
, se lo fai devi dire esplicitamente EF Core quali sono i tuoi tipi di entità aggiungendo OnModelCreating
una chiamata a modelBuilder.Entity<TEntity>();
per ogni tipo di entità (questo è ciò che la documentazione intende per tipi menzionati nel metodo OnModelCreating
).