Sto usando il pattern Unità di lavoro che chiama dbcontext.SaveChanges dopo che tutto è stato eseguito su una richiesta webapi. In parte della richiesta, aggiungo un nuovo cliente a dbcontext.
dbContext.Customers.Add(new Customer());
Più tardi nella richiesta (solitamente all'interno di un gestore di eventi di dominio), sto utilizzando lo stesso dbcontext per estrarre il cliente.
_dbContext.Customers.FirstOrDefault(x => x.Id == id);
public abstract class Customer
{
public Customer()
{
Id = Guid.NewGuid();
}
}
Ho verificato che dbContext.Customers.Local ha l'oggetto che mi aspetto, ma non sembra che stia recuperando l'oggetto locale. Ciò potrebbe essere causato dal fatto che il Cliente è una classe astratta, implementata da DirectCustomer e InDirectCustomer?
Perché? Posso cambiare questo comportamento attraverso la configurazione? Forse devo unire i risultati locali e del database (un po 'hacky).
Aggiornare:
class Program
{
static void Main(string[] args)
{
MyDbContext context = new MyDbContext();
Guid customerGuid = Guid.NewGuid();
context.Customers.Add(new DirectCustomer()
{
Id = customerGuid
});
// This does not work, customerFromLocal1 is null
var customerFromLocal1 = context.Customers.FirstOrDefault(x => x.Id == customerGuid);
// This does work, customerFromLocal2 is NOT null
var customerFromLocal2 = context.Customers.Find(customerGuid);
}
}
public class MyDbContext : Microsoft.EntityFrameworkCore.DbContext
{
public DbSet<Customer> Customers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.\\sqlexpress;integrated security=true;database=EFCoreDeepDive2");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<DirectCustomer>();
builder.Entity<IndirectCustomer>();
}
}
public abstract class Customer
{
public Guid Id { get; set; }
}
public class DirectCustomer : Customer
{
}
public class IndirectCustomer : Customer
{
public Guid ParentCustomerId { get; set; }
}
In EF Core, gli operatori Linq (come FirstOrDefault (), ToList () ecc. E le loro contro-parti in async) fanno in modo che la query venga valutata rispetto al server. Per la query, i dati del server sono fonte di verità. Combinerebbe oggetti di ritorno se sono già stati caricati in memoria ma prima verrebbe controllato dal server.
Quando aggiungi un nuovo oggetto entità al contesto, l'oggetto esiste nel programma di trasformazione ma non verrà salvato sul server finché non chiami SaveChanges()
. Pertanto, dopo aver aggiunto l'entità e prima di chiamare SaveChanges
per qualsiasi query che verrà valutata rispetto al server, non saranno disponibili informazioni sull'entità appena aggiunta e non verranno restituiti risultati correlati.
Se stai cercando di trovare un oggetto entità con i suoi valori chiave nell'istanza di contesto corrente, che può essere o non essere stato salvato, usa il metodo context.DbSet.Find()
(ci sono anche altre variazioni definite sul contesto. controlla il ChangeTracker per trovare l'oggetto, che contiene tutti gli oggetti caricati in memoria e gli oggetti aggiunti / modificati. Se non trova, carica l'oggetto dal server. Nel tuo caso dal momento che vuoi trovare un'entità che è stata aggiunta al contesto ma non salvato, Find
ti darà il risultato previsto.
Nota: DbSet.Local
contiene tutte le entità del tipo di DbSet tracciate dal contesto corrente. Pertanto l'entità aggiunta è disponibile lì ma non direttamente su DbSet. DbSet è IQueryable per consentire di scrivere query del server su di esso.