DbSet.attach() 进行了下一次查询 return 错误的结果
DbSet.attach() made next query return wrong result
假设此User
数据已记录在数据库中..
User {
Id = 1,
Name = "John",
Job = "Programmer"
};
稍后,我想更新他的名字。所以,我执行这个命令
var entity = new User { Id = 1 };
_context.Users.Attach(entity);
entity.Name = "Jack";
await _context.SaveChangesAsync();
最后在我再次查询看到update
var order = await _context.Users
.FirstOrDefaultAsync(x => x.Id == 1));
但是我得到的数据很奇怪...
User {
Id = 1,
Name = "Jack",
Job = null <----- this should not be null
};
看起来查询结果来自_context
调用attach()
方法后的记录。
任何想法或我应该怎么做才能防止这种奇怪的结果。
您在作业中看到#null 的原因是因为在最终查询中 DbContext returned 您的实体将是您启动并附加到上下文的实例。当您使用实体调用 SaveChanges 时,它的 ID 为 1,名称为 "Jack",作业为 #null。跟踪告诉 EF 只有名称发生了变化,所以这就是更新语句中进入数据库的全部内容。
EF 在幕后做了一些有点可疑的事情,但是当你获取一个实体时,它会 return 在从数据库加载实体之前缓存中的任何内容(如果可用)。令人困惑的是,如果您针对数据库进行分析,您将看到针对数据库引发的 SELECT
,但实体 returned 将反映最后缓存的状态,而不是数据库状态。要刷新实体,您可以:
_context.Entity(user).Reload();
重新加载被跟踪的实体。或者...
_context.Entity(user).EntityState = EntityState.Detached;
user = _context.Users.Single(x => x.Id == 1);
...分离您再次更新的实体以在询问时强制 EF 重新加载或...
user = _context.Users.AsNoTracking().Single(x => x.Id == 1);
...加载新的未跟踪参考。
作为一般规则,在编辑实体时,您应该加载实体、应用更改并保存,而不是 Id + Attach
技巧。 Id + Attach
是删除场景或可能的批量更新的便捷 hack,但仅限于短暂的 DbContexts,以便这些跟踪的 "partial" 实体不会再次被其他查询 returned .
假设此User
数据已记录在数据库中..
User {
Id = 1,
Name = "John",
Job = "Programmer"
};
稍后,我想更新他的名字。所以,我执行这个命令
var entity = new User { Id = 1 };
_context.Users.Attach(entity);
entity.Name = "Jack";
await _context.SaveChangesAsync();
最后在我再次查询看到update
var order = await _context.Users
.FirstOrDefaultAsync(x => x.Id == 1));
但是我得到的数据很奇怪...
User {
Id = 1,
Name = "Jack",
Job = null <----- this should not be null
};
看起来查询结果来自_context
调用attach()
方法后的记录。
任何想法或我应该怎么做才能防止这种奇怪的结果。
您在作业中看到#null 的原因是因为在最终查询中 DbContext returned 您的实体将是您启动并附加到上下文的实例。当您使用实体调用 SaveChanges 时,它的 ID 为 1,名称为 "Jack",作业为 #null。跟踪告诉 EF 只有名称发生了变化,所以这就是更新语句中进入数据库的全部内容。
EF 在幕后做了一些有点可疑的事情,但是当你获取一个实体时,它会 return 在从数据库加载实体之前缓存中的任何内容(如果可用)。令人困惑的是,如果您针对数据库进行分析,您将看到针对数据库引发的 SELECT
,但实体 returned 将反映最后缓存的状态,而不是数据库状态。要刷新实体,您可以:
_context.Entity(user).Reload();
重新加载被跟踪的实体。或者...
_context.Entity(user).EntityState = EntityState.Detached;
user = _context.Users.Single(x => x.Id == 1);
...分离您再次更新的实体以在询问时强制 EF 重新加载或...
user = _context.Users.AsNoTracking().Single(x => x.Id == 1);
...加载新的未跟踪参考。
作为一般规则,在编辑实体时,您应该加载实体、应用更改并保存,而不是 Id + Attach
技巧。 Id + Attach
是删除场景或可能的批量更新的便捷 hack,但仅限于短暂的 DbContexts,以便这些跟踪的 "partial" 实体不会再次被其他查询 returned .