我正在使用工作单元模式,在 webapi 请求上执行所有操作后调用 dbcontext.SaveChanges 。在请求的一部分中,我将一个新客户添加到 dbcontext。
dbContext.Customers.Add(new Customer());
稍后在请求中(通常在域事件处理程序内部),我使用相同的 dbcontext 将客户拉出来。
_dbContext.Customers.FirstOrDefault(x => x.Id == id);
public abstract class Customer
{
public Customer()
{
Id = Guid.NewGuid();
}
}
我已经验证 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; }
}
在 EF Core 中,Linq 运算符(例如 FirstOrDefault()、ToList() 等及其异步中的对应部分)会导致针对服务器评估查询。对于查询来说,服务器数据是事实来源。如果返回对象已加载到内存中,它将合并它们,但它会首先与服务器检查。
当您将新的实体对象添加到上下文时,该对象存在于changetracker中,但在您调用之前它不会保存到服务器SaveChanges()
。因此,在添加实体之后和调用之前SaveChanges
对于将针对服务器进行评估的任何查询,将没有有关新添加的实体的信息,并且不会返回与其相关的任何结果。
如果您尝试通过当前上下文实例中的键值查找实体对象(可能已保存或未保存),则使用context.DbSet.Find()
方法(上下文中还定义了其他变体。Find 方法首先检查 ChangeTracker 以查找对象,其中包含内存中加载的所有对象以及添加/修改的对象。如果找不到,则将从服务器加载对象。在你的情况,因为你想找到已添加到上下文但未保存的实体,Find
会给你预期的结果。
Note: DbSet.Local
包含当前上下文正在跟踪的 DbSet 类型的所有实体。因此,添加的实体在那里可用,但不能直接在 DbSet 上使用。 DbSet 是 IQueryable 的,以便允许针对它编写服务器查询。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)