【发布时间】: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