DbContext 不返回本地对象

Dar*_*g8r 2 c# entity-framework-core

我正在使用工作单元模式,该模式在 webapi 请求上执行完所有内容后调用 dbcontext.SaveChanges。在请求的一部分中,我向 dbcontext 添加了一个新客户。

dbContext.Customers.Add(new Customer());
Run Code Online (Sandbox Code Playgroud)

稍后在请求中(通常在域事件处理程序中),我使用相同的 dbcontext 将客户拉回来。

_dbContext.Customers.FirstOrDefault(x => x.Id == id);


public abstract class Customer
{
    public Customer()
    {
        Id = Guid.NewGuid();
    }

}
Run Code Online (Sandbox Code Playgroud)

我已经验证 dbContext.Customers.Local 有我期望的对象,但它似乎没有提取本地对象。这可能是因为 Customer 是一个抽象类,由 DirectCustomer 和 InDirectCustomer 实现吗?

为什么?我可以通过配置更改此行为吗?也许我必须合并本地和数据库结果(有点 hacky )。

更新:

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; }
}
Run Code Online (Sandbox Code Playgroud)

Smi*_*mit 5

在 EF Core 中,Linq 运算符(如 FirstOrDefault()、ToList() 等及其异步中的对应部分)导致针对服务器评估查询。对于查询,服务器数据是真实来源。如果返回对象已经加载到内存中,它将合并返回对象,但它会首先检查服务器。

当您将新实体对象添加到上下文时,该对象存在于 changetracker 中,但在您调用SaveChanges(). 因此,在添加实体之后,在调用SaveChanges将针对服务器进行评估的任何查询之前,将没有关于新添加实体的信息,也不会返回与之相关的任何结果。

如果您试图通过当前上下文实例中的键值查找实体对象,该对象可能已保存或未保存,则使用context.DbSet.Find()方法(上下文中还定义了其他变体。Find 方法首先检查 ChangeTracker 以查找对象,其中包含加载到内存中的所有对象和添加/修改的对象。如果没有找到,那么它将从服务器加载对象。在您的情况下,因为您想找到已添加到上下文但未保存的实体,Find会给您预期的结果。

注意:DbSet.Local包含当前上下文正在跟踪的 DbSet 类型的所有实体。因此,添加的实体在那里可用,但不能直接在 DbSet 上使用。DbSet 是 IQueryable 以允许针对它编写服务器查询。