【问题标题】:Entity Framework - Detach and keep related object graph实体框架 - 分离并保留相关的对象图
【发布时间】:2009-07-21 10:40:46
【问题描述】:

我刚刚开始使用实体框架而不是我的普通 NHiberante 来了解 EF 的工作原理,到目前为止我遇到了很多问题,但特别是分离一个对象并保留相关的子对象。
我买了 O'Reilly Entity Framework 书,它告诉您“是的,默认情况下,实体框架在您分离时不会保留对象图”,但它没有说明如何保留该图!谢谢 O'Reilly 那真的很有用。

无论如何,如果有人可以提供帮助,那就太好了,下面的代码:

        using (var creativeWorkshopEntities = new CreativeWorkshopEntities())
        {
            var q = from c in creativeWorkshopEntities.Job.Include("Files")
                    where c.Id == jobId
                    select c;

            var job = q.First();

            creativeWorkshopEntities.Detach(job);

            return job;
        }

谢谢!

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    尝试改用 NoTracking 查询。这样,对象就永远不会被附加,因此您不需要“分离”,即图形被切碎:

    using (var creativeWorkshopEntities = new CreativeWorkshopEntities())        
    {            
        creativeWorkshopEntities.Job.MergeOption = MergeOption.NoTracking;
        var q = from c in creativeWorkshopEntities.Job.Include("Files")
                where c.Id == jobId                    
                select c;            
        var job = q.First();            
        return job;
    } 
    

    希望对你有帮助

    亚历克斯

    (项目经理实体框架团队)

    【讨论】:

    • 非常感谢 Alex MergeOption 解决了这个问题,但问题是没有分离我的更新方法不起作用,无论如何?使用 (var creativeWorkshopEntities = new CreativeWorkshopEntities()) { if (job.Id > 0) creativeWorkshopEntities.AttachUpdated(job); //自定义扩展方法 else creativeWorkshopEntities.AddToJob(job); creativeWorkshopEntities.SaveChanges(); }
    • 您需要使用 ApplyPropertyChanges(...) 传入更新的实体。 ApplyPropertyChanges(updated) 将值从“更新”实体复制到原始实体。为此,“原始”实体必须在上下文中,因为您持有副本并附加它(推荐),或者因为您执行了查询以从数据库中重新加载它。
    • 有什么办法可以防止实体图被切碎吗?为什么要以这种方式实现分离?
    • 如果我需要让上下文保持活动状态怎么办?我为每个 http 请求使用 1 个上下文,即使我设置了 MergeOption.NoTracking 实体仍保持连接
    【解决方案2】:

    在 EF5 中,MergeOption 不再处于 DbSet 级别。所以根据这个:http://msdn.microsoft.com/en-us/data/hh949853.aspx

    如果您想进行不跟踪查询,您需要执行以下操作:

      var q = from c in creativeWorkshopEntities.Job.AsNoTracking().Include("Files")
                            where c.Id == jobId
                            select c;
    

    【讨论】:

      【解决方案3】:

      查看http://www.codeproject.com/KB/architecture/attachobjectgraph.aspx

      这是一个很棒的解决方案,可能会对您有所帮助 - 请注意,作者在他自己的博客上也有更新版本 - http://www.codetuning.net/blog/post/Entity-Framework-reattaching-entity-graphs-(3).aspx

      保罗

      【讨论】:

      • 这看起来是一个非常棒的解决方案!
      【解决方案4】:

      使用以下代码将相关对象保存在内存中。

        using (var creativeWorkshopEntities = new CreativeWorkshopEntities())
        {
                      var q = from c in creativeWorkshopEntities.Job.Include("Files")
                              where c.Id == jobId
                              select c;
      
                      var job = q.First();
      
                      return (Job)Detach(job);
         }
      
        private Object Detach(Object object)
        {
                  using (var stream = new MemoryStream())
                   {
                      var formatter = new BinaryFormatter();
                      formatter.Serialize(stream, dbo);
                      stream.Position = 0;
                     return formatter.Deserialize(stream);
                   }
         }
      

      【讨论】:

      • 这只会分离单个对象 - 而不是整个图形。
      • @DannyVarod 你为什么会这样想?我刚刚尝试过,它按预期工作,所有实体都在那里。
      • @veljkoz EF4 的内置分离仅分离了一个对象,此实现克隆了该对象。我不记得我为什么写这个了——那是一年多以前的事了,我看不到任何修改。
      • 这实际上并没有分离任何东西。它只是克隆图形。原始图仍在上下文的本地缓存中。如果减少内存占用是您想要分离实体图的原因的一部分,那么这根本没有帮助 - 实际上它会使情况变得更糟。您还必须标记所有[Serializable],这是另一个贬低者。
      • -1 虽然在 MSDN 论坛 (social.msdn.microsoft.com/Forums/en-US/…) 上建议这样做,但正如 @sliderhouserules 指出的那样,这不会分离任何东西,它会克隆 一切(整个上下文,可通过对象跟踪器引用访问)。如果上下文中有很多(10k's)对象(我整周都在追查的错误),这可能会导致极端性能问题。我强烈建议避免使用这种方法。
      猜你喜欢
      • 1970-01-01
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 2016-12-19
      • 1970-01-01
      相关资源
      最近更新 更多