【问题标题】:EF4 - Load related entities of detached objectEF4 - 加载分离对象的相关实体
【发布时间】:2012-07-13 05:16:53
【问题描述】:

我有一个 ASP MVC 3 应用程序,它使用 Entity Framework 4 来访问 SQL Server 数据库中的数据。

我有一个使用 EF4 从数据库加载实体的场景。然后我可以正常加载相关实体。第一次加载后,我缓存了实体。这需要它被序列化。在下一个请求中,我加载了相同的实体,但这次是从缓存中加载的。这会导致对象与上下文分离,因为它并非源自那里。然后我无法正常加载相关实体。

很明显,这样做的原因是对象与上下文分离,因此没有被跟踪。我知道,当上下文跟踪对象时,它会跟踪更改并在需要时通过执行实际的 SQL 语句应用它们。但我不确定的是附加状态是否与加载相关实体的能力有关。

好的,这里有一些细节。这是模型结构。请注意,这是简化的,不包括使 EF4 能够使用它所需的一切。这只是简单地展示了结构。

public class Segment
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public SegmentGroup Group { get; set; }
}
public class SegmentGroup 
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Segment> Segments { get; set; }
}

然后我可以从数据库或缓存中获取一个段。这是在 Manager 类中完成的。再次非常简化。

public SegmentManager
{
    public Segment GetSegment(Guid id)
    {
        string cacheKey = ... //generate specific cache key using Guid id
        Segment segment = CacheProvider.Get<Segment>(cacheKey);
        if(segment == null) //does not exist in cache yet - load from db and insert into cache
        {
            segment = repo.Find<Segment>(id); //roughly translates to:
                                              //segment = dbcontext.Segments.SingleOrDefault(a => a.Id == id);
            CacheProvider.Add(cacheKey, segment);
        }
        else //segment was found in cache - attach to context
        {
            repo.Attach<Segment>(segment); //dbcontext.Segments.Attach(segment);
        }
        return segment;
    }  
} 

所以这有效地使我能够像这样使用这个段管理器:

public ActionResult SegmentGroupName(Guid segmentId)
{
    Segment segment = SegmentManager.GetSegment(segmentId); //Loaded from DB of Cache
    return segment.Group.Name; //Group is accesable when segment is loaded from DB, but not from cache
}

所以问题是,当从数据库加载 Segment 时,我可以访问 Segment 上的 SegmentGroup,但从缓存加载时却不行。

所以我的问题是,在从缓存加载分段后,我可以对分段执行什么操作以使我能够访问相关实体。 我需要一个通用的解决方案,我可以以相同的模式将其应用于我的所有模型管理器,因为一切都是高度抽象的。 我试图避免急切加载所有相关实体或事后手动加载它们,因为这实际上比不缓存更昂贵。我只想让事情回到缓存之前的状态。 :)

请注意,代码演示非常简化,您需要做出一些现实的假设。

【问题讨论】:

    标签: c# .net entity-framework


    【解决方案1】:

    听起来像是我遇到的东西,我称之为薛定谔代码...我遇到了一个类似的问题,我将模型传递给我的视图,但是在尝试访问相关实体时,我收到了错误,指的是对象上下文被关闭。通过在将主要实体传递给我的视图之前观察相关实体,我能够在不重新打开对象上下文的情况下解决此问题。

    例如,如果我正在处理您的细分和组,它将是以下内容

    Segment segment = repo.Find<Segment>(segmentId);
    var segmentGroup = segment.Group;
    

    在此之后我不会对 segmentGroup 做任何事情,只是因为我观察到了它,它现在就存在了。如果没有事先观察,系统不确定如何处理此问题,因为尚未对数据库进行额外调用,但由于在本例中已观察到,因此 Group 对象的数据已与 Segment 对象相关联。

    奇怪,我知道……它存在,但它不存在……我们知道它在那里,但我们必须看到它来证明它……因此我将这种情况称为薛定谔密码...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2012-04-04
      相关资源
      最近更新 更多