我有一个 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
}
所以问题是当从数据库加载段时,我可以访问段上的段组,但从缓存加载时不能。
所以我的问题是,在从缓存加载段后,我可以对段做些什么以使我能够访问相关实体。我需要一个通用的解决方案,我可以以相同的模式将其应用于我的所有模型管理器,因为一切都是高度抽象的。我试图避免急切加载所有相关实体或事后手动加载它们,因为这实际上比不缓存更昂贵。我只想让事情回到缓存之前的状态。:)
请注意,代码演示非常简化,您需要做出一些现实的假设。