2012-12-03 2 views
2

아래 코드에서 알 수 있듯이 AsNoTracking을 사용하여 개체를 가져옵니다. 그때에도 무슨 일이 일어나고 있는지 볼 수 ObjectSateManager를 사용하고 난 아무 것도 리터 * 컬렉션에서 추적되고 있지 볼 수 있습니다 아직 난 여전히AsNoTracking 및 ObjectStateManager의 엔터티 프레임 워크 오류

는 "같은 키를 가진 개체가 이미 ObjectStateManager에 존재 얻을. ObjectStateManager는 할 수 없습니다 같은 키로 여러 객체를 추적 "하십시오.

아이디어가 있으십니까?

=========================
바구니 보관함 repo = 새로운 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; 

    } 
+0

질문 : 'dbContext'의 수명은 얼마입니까? 객체의 상태를 변경하면 항상 새로운 것입니까? –

답변

0

실제로 나빴습니다. 의 아이디어에 익숙해 지려면 개념적으로 조금 어려울 수 있습니다. EF로 상황을 연결하고 추적하는 방법입니다. 그 비밀은 그래프의 객체가 상태 X와 연결될 때마다 그래프 (다른 객체와 관계가있는 객체)가있는 경우 그 상태에서 그래프의 다른 모든 객체도 연결되어있는 것처럼 보입니다 .

내 시나리오에서 나는 매우 어리 석었다. var bpro = new BasketProduct (ba, ba.BasketProducts.First(). Product, 3); 을 사용하여 데이터베이스에 실제로 존재하는 테스트 제품을 만들고 바구니 및 해당 제품이 포함 된 그래프 개체의 일부였습니다. 이 "새"바스켓을 붙이려고했을 때 EF는 첨부 된 그래프에 이미 동일한 키가있는 객체가 이미 있다고 불평했습니다!

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; 

는 희망이 도움이!