为啥 EF 在分离时会删除子实体?

Posted

技术标签:

【中文标题】为啥 EF 在分离时会删除子实体?【英文标题】:Why does EF remove child entities when detaching?为什么 EF 在分离时会删除子实体? 【发布时间】:2016-07-14 15:51:37 【问题描述】:

我需要做一些类似...的事情

    获取数据库上下文 (UtilitiesContext) 查询一些数据(监视目录) 当我拉出 WD(附加数据)时,还要从数据库中拉出孩子 处理上下文 继续使用实体

...

// 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;

【问题讨论】:

如果您要处理上下文,您应该首先将它们映射到 DTO。我相信如果您遵循当前的道路,您将遇到更多问题。在上下文范围之外使用实体对象是自找麻烦。 是的,我已经考虑过了……这些都是非常简单的实体,所以我认为这可能可以节省代码重复 我过去曾尝试做类似的事情,但它最终总是会咬你一口,现在做映射比让它工作到稍后的时间点更容易当你最终崩溃时,你需要重新编写大量代码。 【参考方案1】:

EF 是一个有趣的野兽,这是将实体从上下文中分离出来的终极解决方案......

var jsonSettings = new JsonSerializerSettings  MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore ;
var dirs = JsonConvert.DeserializeObject<List<WatchedDirectory>>(JsonConvert.SerializeObject(db.GetAll<WatchedDirectory>().ToList(), jsonSettings));

这可能有更好的做法,但这种在中国商店的方法解决了我的问题。

【讨论】:

【参考方案2】:

当您从上下文中分离父实体时,您不能再使用延迟加载子实体(在您的情况下,无论如何您都不应该这样做,b/c 性能会受到很大影响)。更高效的方法是使用 include() 预先加载所需的子项。这将为您节省对数据库的额外调用。例如,如果每个父母有 2 个孩子,您将为父母拨打 1 个电话,并为每个孩子另外拨打 2 个电话。效率很低。

为了反序列化某些东西而序列化某些东西的方法是让 DTO 出来的糟糕方法。您应该进行映射(可能使用 Automapper),或者关闭 EF 代理处理和延迟加载,这具有类似的效果。

【讨论】:

以上是关于为啥 EF 在分离时会删除子实体?的主要内容,如果未能解决你的问题,请参考以下文章

EF架构~FluentValidation实体检验与实体分离了

EF DbSet.Find() 返回分离实体

如何更新 EF CF 中的实体对象(分离)?

实体框架分离实体和相关实体消失

JPA 级联持续存在并且对分离实体的引用会引发 PersistentObjectException。为啥?

删除分离实体spring jpa Repository接口