【问题标题】:Entity framework error with AsNoTracking and ObjectStateManagerAsNoTracking 和 ObjectStateManager 的实体框架错误
【发布时间】:2012-12-03 23:38:39
【问题描述】:

从下面的代码中可以看出,我使用 AsNoTracking 来获取我的对象。 然后我什至使用 ObjectSateManager 来查看发生了什么,我可以看到 l* 集合中没有任何内容被跟踪,但我仍然得到

“ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象”。

有什么想法吗?

============================================
BasketRepository repo = new BasketRepository();

            var ba = repo.GetById(8);

            var bpro = new BasketProduct(ba, ba.BasketProducts.First().Product, 3);

            repo.AddToBasket(bpro);
           repo.Save();

===================================

    public Basket GetById(int basketId)
    {
        // eager-load product info
        var basket = dbContext.Baskets.Include("BasketProducts")
                                      .Include("BasketProducts.Product.Brand").AsNoTracking().SingleOrDefault(b => b.BasketId == basketId);;
        return basket;
    }

=======================================

  public void AddToBasket(BasketProduct product)
    {
        var ctx = ((IObjectContextAdapter)dbContext).ObjectContext;
        ObjectStateManager objectStateManager = ctx.ObjectStateManager;
        var l1 = objectStateManager.GetObjectStateEntries(EntityState.Added);
        var l2 = objectStateManager.GetObjectStateEntries(EntityState.Modified);
        var l3 = objectStateManager.GetObjectStateEntries(EntityState.Deleted);
        //var l4 = objectStateManager.GetObjectStateEntries(EntityState.Detached);
        var l5 = objectStateManager.GetObjectStateEntries(EntityState.Unchanged);

        var existingProductInBasket = dbContext.BasketProducts.AsNoTracking().SingleOrDefault(b => b.BasketId == product.BasketId && b.ProductId == product.ProductId);
        var l6 = objectStateManager.GetObjectStateEntries(EntityState.Added);
        var l7 = objectStateManager.GetObjectStateEntries(EntityState.Modified);
        var l8 = objectStateManager.GetObjectStateEntries(EntityState.Deleted);
        //var l4 = objectStateManager.GetObjectStateEntries(EntityState.Detached);
        var l9 = objectStateManager.GetObjectStateEntries(EntityState.Unchanged);

        //objectStateManager.
        dbContext.Entry<BasketProduct>(product).State = existingProductInBasket == null ? EntityState.Added : EntityState.Modified;

    }

【问题讨论】:

  • 问题是:dbContext的寿命是多少?当你改变对象的状态时,它总是新的吗?

标签: entity-framework


【解决方案1】:

当您使用 asNoTracking() 时,您会得到一个无法使用 EntityState.Modified 正常更新的未连接实体。然后,一个技巧是用非缓存的实体值替换缓存的实体值。

这是我在需要 asNoTracking 的特殊情况下使用的源代码。可以是

private T ReplaceEntity(T cachedEntity, T nonCachedEntity) {

     dbContext.Entry(cachedEntity).CurrentValues.SetValues(nonCachedEntity);

     return cachedEntity;
}

常见的用法可以是:

public virtual T FindFirstBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate, bool asNoTracking = false)
{
     if (asNoTracking)
     {
          T cachedEntity = dbContext.Set<T>().FirstOrDefault(predicate);
          T nonCachedEntity = dbContext.Set<T>().AsNoTracking().FirstOrDefault(predicate);

          return ReplaceEntity(cachedEntity, nonCachedEntity);
     }
     return dbContext.Set<T>().FirstOrDefault(predicate);
}

根据你的情况:

var cachedEntity = dbContext.BasketProducts.SingleOrDefault(b => b.BasketId == product.BasketId && b.ProductId == product.ProductId);
var nonCachedEntity = dbContext.BasketProducts.AsNoTracking().SingleOrDefault(b => b.BasketId == product.BasketId && b.ProductId == product.ProductId);

var product= ReplaceEntity(cachedEntity, nonCachedEntity);
dbContext.Entry<BasketProduct>(product).State = EntityState.Modified;

希望对你有帮助!!

【讨论】:

    【解决方案2】:

    这实际上很糟糕。从概念上讲,要习惯于 EF如何附加和跟踪事物。秘诀是记住,如果你有一个对象 图形(与其他对象有关系的对象)只要图形的一个对象附加了状态 X,那么图形中的所有其他对象似乎也处于该状态。

    在我的场景中,我非常愚蠢地使用 var bpro = new BasketProduct(ba, ba.BasketProducts.First().Product, 3); 创建一个实际已经存在于数据库中并且是对象的一部分的测试产品 包含篮子及其产品的图表。当我尝试附加这个“新”篮子时,EF 正确地抱怨附加图中已经存在具有相同键的对象!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多