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

时间:2016-07-14 15:51:37

标签: c# entity-framework detach

我需要做点像......

  1. 获取数据库上下文(UtilitiesContext)
  2. 查询一些数据(监视目录)
  3. 当我拉动WD(AdditionalData)
  4. 时,也从数据库中拉出孩子
  5. 处理上下文
  6. 继续使用实体
  7. ...

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

2 个答案:

答案 0 :(得分:0)

EF是一个有趣的野兽,这是将一个实体从背景中分离的最终方法......

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

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

答案 1 :(得分:0)

当您从上下文中分离父实体时,您不能再使用延迟加载子实体(在您的情况下,您绝不应该这样做,b / c性能会受到很大影响)。性能更高的方法是使用includes()预先加载所需的子项。这将节省您对数据库的额外调用。例如,如果每个父母有2个孩子,那么您将为父母进行1次呼叫,并为每个孩子进行另外2次呼叫。非常低效。

将序列化某些东西以便反序列化的方法是让DTO失败的一种不好的方法。您应该进行映射(可能使用Automapper),或者关闭EF代理处理和延迟加载,这会产生类似的效果。