2012-07-12 46 views
1

我有一个ASP MVC 3应用程序使用实体框架4从SQL Server数据库访问数据。EF4 - 分离对象的负载相关实体

我有一个场景,我使用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 
} 

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

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

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

回答

0

听起来像是我碰到的东西,我称之为薛定谔的代码......我遇到了类似的问题,我将模型传递给了我的视图,但是当试图访问相关实体时,到正在关闭的对象上下文。通过在将主实体传递给我的视图之前观察相关实体,我无需重新打开对象上下文即可解决此问题。

举例来说,如果我正在处理您的细分和组,这将是以下

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

我不打算在此之后做任何事情segmentGroup东西,而仅仅是因为我发现它,它现在存在。如果没有事先的观察,系统不确定如何处理这个问题,因为还没有对数据库进行额外的调用,但是由于在这种情况下已经观察到,所以Group对象的数据已经与Segment对象相关联。我知道它存在,但它不存在......我们知道它存在,但我们必须看到它来证明它......因此,为什么我将这种情况称为薛定谔的代码...

相关问题