为什么 EF 在分离时删除子实体?
Why does EF remove child entities when detaching?
我需要做类似...
- 获取数据库上下文 (UtilitiesContext)
- 查询一些数据(监视目录)
- 当我拉出 WD 的 (AdditionalData) 时,也从数据库中拉出子节点
- 处理上下文
- 继续使用实体
...
// step 1
using (var db = new UtilitiesContext(false))
{
var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
// step 2
var dirs = db.GetAll<WatchedDirectory>();
// step 3 (lazy load and serialize the WD and its additional data)
log.Debug(JsonConvert.SerializeObject(dirs, jsonSettings));
foreach (var d in dirs)
{
try
{
log.Debug(" Initialising monitoring for path " + d.UNCPath);
// detach the object and its data items from the db
db.Detach(d);
d.AdditionalData.ForEach(i => db.Detach(i));
// here the AdditionalData property serialises an empty array
log.Debug(JsonConvert.SerializeObject(d, jsonSettings));
// step 4 happens down here
我的问题是我在第一个日志输出中得到了我想要的所有数据(标记为第 3 步的行)
然后当我重复说子集合已经消失时,我所做的只是从上下文中分离实体。
我的分离方法如下所示...
public void Detach(object entity)
{
Entry(entity).State = EntityState.Detached;
}
EF 是一只有趣的野兽,这是将实体从上下文中分离出来的终极良方...
var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
var dirs = JsonConvert.DeserializeObject<List<WatchedDirectory>>(JsonConvert.SerializeObject(db.GetAll<WatchedDirectory>().ToList(), jsonSettings));
这方面可能有更好的做法,但这种 bull in china shop 方法解决了我的问题。
当您从上下文中分离 parent 实体时,您不能再使用 child 实体的延迟加载(在您的情况下,无论如何您都不应该这样做,b/c性能将受到很大影响)。性能更高的方法是使用 includes() 预先加载所需的 children。这将为您节省对数据库的额外调用。例如,如果每个 parent 有 2 个 children,您将对 parent 进行 1 次调用,并对每个 child 进行额外的 2 次调用。效率很低。
你序列化某些东西以反序列化某些东西的方法是一种糟糕的获取 DTO 的方法。您应该进行映射(可能使用 Automapper),或者关闭 EF 代理处理和延迟加载,这具有类似的效果。
我需要做类似...
- 获取数据库上下文 (UtilitiesContext)
- 查询一些数据(监视目录)
- 当我拉出 WD 的 (AdditionalData) 时,也从数据库中拉出子节点
- 处理上下文
- 继续使用实体
...
// step 1
using (var db = new UtilitiesContext(false))
{
var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
// step 2
var dirs = db.GetAll<WatchedDirectory>();
// step 3 (lazy load and serialize the WD and its additional data)
log.Debug(JsonConvert.SerializeObject(dirs, jsonSettings));
foreach (var d in dirs)
{
try
{
log.Debug(" Initialising monitoring for path " + d.UNCPath);
// detach the object and its data items from the db
db.Detach(d);
d.AdditionalData.ForEach(i => db.Detach(i));
// here the AdditionalData property serialises an empty array
log.Debug(JsonConvert.SerializeObject(d, jsonSettings));
// step 4 happens down here
我的问题是我在第一个日志输出中得到了我想要的所有数据(标记为第 3 步的行) 然后当我重复说子集合已经消失时,我所做的只是从上下文中分离实体。
我的分离方法如下所示...
public void Detach(object entity)
{
Entry(entity).State = EntityState.Detached;
}
EF 是一只有趣的野兽,这是将实体从上下文中分离出来的终极良方...
var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
var dirs = JsonConvert.DeserializeObject<List<WatchedDirectory>>(JsonConvert.SerializeObject(db.GetAll<WatchedDirectory>().ToList(), jsonSettings));
这方面可能有更好的做法,但这种 bull in china shop 方法解决了我的问题。
当您从上下文中分离 parent 实体时,您不能再使用 child 实体的延迟加载(在您的情况下,无论如何您都不应该这样做,b/c性能将受到很大影响)。性能更高的方法是使用 includes() 预先加载所需的 children。这将为您节省对数据库的额外调用。例如,如果每个 parent 有 2 个 children,您将对 parent 进行 1 次调用,并对每个 child 进行额外的 2 次调用。效率很低。
你序列化某些东西以反序列化某些东西的方法是一种糟糕的获取 DTO 的方法。您应该进行映射(可能使用 Automapper),或者关闭 EF 代理处理和延迟加载,这具有类似的效果。