EF4 - 加载分离对象的相关实体

时间:2012-07-12 20:35:30

标签: c# .net entity-framework

我有一个使用Entity Framework 4的ASP MVC 3应用程序来访问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,但是当它从缓存加载时不能访问。

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

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

1 个答案:

答案 0 :(得分:0)

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

例如,如果我正在处理您的细分和群组,则会出现以下内容

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

在此之后我不会对segmentGroup做任何事情,但仅仅因为我观察它,它现在存在。如果没有先前的观察,系统不确定如何处理这个问题,因为没有对数据库进行额外的调用,但是因为在这个实例中已经观察到,所以Group对象的数据已经与Segment对象相关联。 / p>

很奇怪,我知道......它存在,但它不存在......我们知道它存在,但我们必须看到它来证明它...因此我为什么把这个场景称为薛定谔的代码...