我相信这既是缓存内容的问题,也是如何缓存的问题。在处理 EF 时,当您尝试跨不同上下文持久化 EF 对象并尝试分离/附加这些对象时,您可能会很快遇到问题。如果您将自己的 POCO 对象与自定义 t4 模板一起使用,那么这不是问题,但如果您使用的是 vanilla EF,那么您将需要为缓存创建 POCO 对象。
对于大多数简单的查找项(即数字主键和字符串文本描述),您可以使用 Dictionary。如果您有多个字段需要通过 UI 传递和返回,那么您可以构建更完整的对象模型。由于这些将是 POCO 对象,因此它们几乎可以在任何地方以您喜欢的任何方式持久化。我建议在 MVC 应用程序之外使用缓存逻辑,以便您可以轻松地模拟缓存活动以进行测试。如果您有多个列表需要缓存,您可以将它们全部放在一个容器类中,如下所示:
public class MyCacheContainer
{
public Dictionary<int, string> GeoLocations { get; set; }
public List<Category> Categories { get; set; }
}
下一个问题是您的实体模型中是否真的需要这些对象。您真正需要的只是主键(即,您使用字典中的键和值创建一个下拉列表,然后发布 ID)。因此,您可能会在构建视图模型时处理对文本描述的所有查找。这可能看起来像这样:
MyEntityObject item = Context.MyEntityObjects.FirstOrDefault(i => i.Id == id);
MyCacheContainer cache = CacheFactory.GetCache();
MyViewModel model = new MyViewModel { Item = item, GeoLocationDescription = GeoLocations[item.GeoLocationId] };
如果您绝对必须在您的上下文中拥有这些对象(即,如果存在将 2 个或更多其他表联系在一起的引用实体),您可以将该缓存容器传递到您的数据访问层,以便它可以进行正确的查找。
至于分配“有效”实体,在 .Net 4 中,您只需设置外键属性,而不必实际附加对象(技术上您可以在 3.5 中执行此操作,但它需要使用魔术字符串来设置键)。如果您使用的是 3.5,则可以尝试以下操作:
myItem.Category = Context.Categories.FirstOrDefault(c => c.id == id);
虽然这不是最优雅的解决方案,并且确实需要额外往返数据库才能获得您并不真正需要的类别,但它确实有效。基于主键进行单条记录查找不应该真的有那么大的影响,特别是如果表像您正在谈论的查找数据类型一样小。
如果您坚持使用 3.5 并且不想进行额外的往返,并且您想要使用魔术字符串路线,只需确保您为魔术字符串使用某种类型的静态资源和/或代码生成器,这样你不胖手指他们。这里有很多例子展示了如何在不进入数据库的情况下将新的 EntityKey 分配给引用,所以我不会在这个问题上讨论这个问题。