【问题标题】:Caching entities - How to avoid An entity object cannot be referenced by multiple instances of IEntityChangeTracker缓存实体 - 如何避免一个实体对象不能被多个 IEntityChangeTracker 实例引用
【发布时间】:2014-10-23 20:37:28
【问题描述】:

我想缓存我的实体以尽可能避免数据库交互。当我做类似的事情时:

public IList<Website> Get()
{
    //The `_cacheManager.Get` just retrieves the object from an `ObjectCache` instance based on key.
    return _cacheManager.Get(CcCacheWebsiteAll, () => _websiteRepository.Table.ToList());
}

我在从缓存中检索值并将其分配给需要该类型实例的新对象时遇到问题。

例如:

var store = new Store();
store.Name = "something";
store.Website = _websiteService.Get().FirstOrDefault();
_storeService.Insert(store);

//Where _storeService.Insert(store) is:

public void InsertStore(Store store)
{
    _storeRepository.Insert(store); //THIS will raise the error
}

我原以为在 Get() 方法上调用 ToList() 会将实例放入一个新列表并停止问题,但我在测试时没有发现这一点。

有人有什么建议吗?

注意:为了确保我只有一个上下文,我禁用了缓存并且一切都按预期工作。

编辑

商店服务总监:

public StoreService(IRepository<Store> storeRepository)
{
    _storeRepository = storeRepository;
}

网站服务总监:

public WebsiteService(IRepository<Website> websiteRepository)
{
    _websiteRepository= websiteRepository;
}

【问题讨论】:

  • 您的_websiteRepository 与您的_storeRepository 是同一个实例?
  • 不,它们在不同的服务中。基本上,每个都是 IRepository&lt;Website&gt;, 'IRepository` 所以它是 EF 东西的包装器。我假设因为你问过,ToList() 应该解决我的问题?如果我知道应该这样做,我会将精力集中在其他地方。
  • 您可以使用.ToList(),但这不会阻止 dbcontext 跟踪您的实例。您必须将其分离,以便 dbcontext 停止跟踪它,更重要的是,另一个 dbcontext 可以开始跟踪它。我也认为你不应该.Insert(...) 它,而是简单地将实例附加到另一个 dbcontext。
  • 哦!它只是保留对列表中对象的引用而不是实际副本吗?
  • 是的,dbcontext 引用了实例。调用 .ToList() 不会删除该引用。

标签: c# asp.net-mvc entity-framework entity-framework-6


【解决方案1】:

你说过你有两种情况。如果您使用一个上下文(我们称之为上下文 A)来加载您的实体,那么该实体由上下文 A 跟踪。您不能将该实例与另一个上下文(上下文 B)一起使用。所以你必须将你的实体从上下文 A 中分离出来,并将你的实体附加到上下文 B。

在 Entity Framework 的版本中,从上下文中分离/附加实体的方法发生了一些变化,但对于 EF6,我认为 this articlethis SO question 描述得很好。

【讨论】:

    猜你喜欢
    • 2011-11-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多