엔티티 프레임 워크 코드 - 첫 번째 : "ObjectStateManager는 동일한 키로 여러 개체를 추적 할 수 없습니다."

StackOverflow https://stackoverflow.com//questions/9611003

문제

MVC3에서 먼저 엔티티 프레임 워크 코드로 문제가 발생합니다. 이 예외가 적합합니다 :

동일한 키가있는 객체가 ObjectStateManager에 이미 있습니다. ObjectStateManager는 동일한 여러 개체를 추적 할 수 없습니다 키.

이것은 여러 번 해결되지만, 제안 된 솔루션을 내 상황에서 활용하는 데 어려움을 겪고 있습니다.

여기에는 코드 샘플이 있습니다.

FestORM.SaleMethod method = new FestORM.SaleMethod
{
    Id = 2,
    Name = "Test Sale Method"
};
FestContext context = new FestContext();

//everything works without this line:
string thisQueryWillMessThingsUp = 
    context.SaleMethods.Where(m => m.Id == 2).Single().Name;

context.Entry(method).State = System.Data.EntityState.Modified;
 context.SaveChanges();
.

명확히하기 위해 편집 : 데이터베이스에 이미 존재하는 객체를 업데이트하려고 시도하고 있습니다.

모든 것이 코드에 언급되지 않은 상태에서 잘 작동합니다. 내 응용 프로그램에서 컨트롤러가 컨텍스트에서 사용되는 여러 개의 저장소로 전달됩니다. 초기 쿼리 작업에 대해 다른 컨텍스트를 사용하기 만하면됩니다. objectStateManager에서 엔티티를 제거하려고 노력했지만 그 중 하나를 가지고있는 것처럼 보일 수는 없습니다. 나는 두 가지 조건에서 일할 솔루션을 알아 내려고 노력하고 있습니다. 때로는 ObjectStateManager가 추적하는 객체를 업데이트하고 때로는 아직 추적되지 않은 경우가 있습니다.

fwiw, 나의 실제 저장소 함수는 위의 코드와 마찬가지로 다음과 같습니다.

public void Update(T entity)
{
    //works ONLY when entity is not tracked by ObjectStateManager
    _context.Entry(entity).State = System.Data.EntityState.Modified; 
}

public void SaveChanges()
{
    _context.SaveChanges();
}
.

아이디어가 있습니까? 나는 이것을 너무 오랫동안 싸우고있었습니다 ...

도움이 되었습니까?

해결책

이 문제는이 쿼리

string thisQueryWillMessThingsUp =  
    context.SaleMethods.Where(m => m.Id == 2).Single().Name; 
.

Salemethod 엔티티의 한 인스턴스를 컨텍스트에 가져온 다음이 코드 을 가져옵니다.

context.Entry(method).State = System.Data.EntityState.Modified;
.

다른 인스턴스 을 컨텍스트에 부착합니다. 두 인스턴스 모두 동일한 기본 키를 가질 수 있으므로 EF는 컨텍스트와 동일한 키로 두 개의 다른 엔터티를 첨부하려고 노력하고 있다고 생각합니다. 둘 다 동일한 엔티티가되어야한다는 것을 알지 못합니다.

어떤 이유로 이름을 쿼리해야하지만 실제로 전체 엔티티를 컨텍스트에 가져 오지 않으려면 다음을 수행 할 수 있습니다.

string thisQueryWillMessThingsUp =           
    context.SaleMethods.Where(m => m.Id == 2).AsNoTracking().Single().Name; 
.

수행 할 작업이 기존 엔티티를 업데이트하고 해당 엔티티의 모든 매핑 된 속성에 대해 값이있는 경우 쿼리를 실행하지 않아도됩니다.

context.Entry(method).State = System.Data.EntityState.Modified;
.

모든 속성을 업데이트하지 않으려면 모든 속성에 값이 없으므로 SaveChanges를 호출하기 전에 엔티티 및 속성 설정을 쿼리하기 때문에 사용할 수 있습니다. 정확한 요구 사항에 따라이 작업을 수행하는 방법에는 여러 가지가 있습니다. 한 가지 방법은 속성 메소드를 사용하는 것입니다.

var salesMethod = context.SaleMethods.Find(2); // Basically equivalent to your query
context.Entry(salesMethod).Property(e => e.Name).CurrentValue = newName;
context.Entry(salesMethod).Property(e => e.SomeOtherProp).CurrentValue = newOtherValue;
context.SaveChanges();
.

이 블로그 게시물에는 도움이 될 수있는 추가 정보가 포함되어 있습니다.

http://blogs.msdn.com/b/adonet/archive/2011/01/29/using-dbcontext-in-ef-feature-ctp5-part-4-add-attach. - entity-states.aspx

http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property. -values.aspx

다른 팁

명백한 대답은 전화하기 전에 실제로 메소드 오브젝트를 데이터베이스에 저장하지 않아야합니다.

//everything works without this line:
string thisQueryWillMessThingsUp = context.SaleMethods.Where(m => m.Id == 2).Single().Name;
.

그러나, 아마도 이것은 단지 비트 당신이 그만 둔 코드 일 것입니다. 엔티티가 추상 클래스에서 상속되면 IE.

public abstract class BaseClass
{
     public int Id { get; set; }
}
. 그런 다음 저장소를 로 업데이트하십시오.
public class Repository<T> where T : BaseClass
{
 .....
    public void Update(T entity)
    {        
        _context.Entry(entity).State = entity.Id == 0 ? System.Data.EntityState.Added : System.Data.EntityState.Modified; 
    }
}
.

또한 Salemethod의 ID를 설정하지 않고 데이터베이스에 의해 생성 할 수 있습니다.데이터베이스의 Salemethod 객체가 ID가 2 인 경우 ID 2가있는 다른 Salemethod 객체를 추가하려고 시도하기 때문에 문제가 발생할 수도 있습니다. ObjectStateManager에 ID가 2 개의 ID가있는 다른 Salemethod 객체를 추가하려고하는 오류가 나타납니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top