ObjectStateManager에서 찾을 수 없기 때문에 개체를 삭제할 수 없습니다.


114

"ObjectStateManager에서 찾을 수 없기 때문에 개체를 삭제할 수 없습니다."라는 오류 메시지가 나타납니다.

내 코드는 다음과 같습니다.

    protected MyEntities sqlEntities;

    public virtual void Delete(TEntity entity)
    {
        System.Type t = typeof(TEntity);
        sqlEntities.DeleteObject(entity);
        sqlEntities.SaveChanges();
    }

5
레코드를 가져오고 삭제하는 데 다른 데이터 컨텍스트 개체가 사용되었다는 코드에 문제가 발생했습니다.
Sami

다음과 같은 버그가있었습니다. var entity = new TEntity() { PK_ID = 23 }; sqlEntities.DeleteObject(entity);Entity Framework가 PK를 기반으로 DeleteObject를 호출하기를 바라면서 PK가 올바르게 설정된 모의 엔티티를 만들려고했습니다
.

답변:


156

이는 엔티티가 연결되지 않았 음을 의미합니다 (동일한 컨텍스트 인스턴스에 의해로드되지 않음). 이 시도:

protected MyEntities sqlEntities;

public virtual void Delete(TEntity entity)
{
    sqlEntities.Attach(entity);
    sqlEntities.DeleteObject(entity);
    sqlEntities.SaveChanges();
}

1
감사합니다 Ladislav. 이는 TransactionScope 외부의 다른 컨텍스트에서 호출 된 부모에서 자식 데이터를 삭제할 때 두 가지 컨텍스트가 진행될 때 도움이되었습니다. 범위와 동일한 컨텍스트 내에서 부모 호출을 이동하고 문제가 해결되었습니다.
dan richardson 2013

1
@Ladislav : .Attach를 사용하면 "엔티티 개체를 IEntityChangeTracker의 여러 인스턴스에서 참조 할 수 없습니다."라는 다른 오류가 발생합니다. 삭제를 방해하는 다른 개체 인스턴스가 이미 존재한다는 의미입니까?
매트

2
@Matt : 아니요, 개체가 이미 다른 컨텍스트에 연결되어 있음을 의미합니다. 동시에 두 개에 연결할 수 없습니다. 엔터티를 삭제하려면 원래 컨텍스트를 사용해야합니다.
Ladislav Mrnka 2013 년

@Ladislav : 감사합니다. 더 많은 것을 찾는 데 도움이되었습니다. 문제를 해결하는 방법에 대한 대답 인이 질문을 찾았습니다. 개체가 이미 Entity Framework의 데이터 컨텍스트에 연결되어 있는지 확인할 수 있습니까? . 당신 말이 맞습니다. 제 경우에는 이것이 문제인 것 같습니다. 빠른 답변에 감사드립니다!
Matt

알림을 보내 주셔서 감사합니다. 레코드를 업데이트 할 때 첨부했지만 레코드를 삭제할 때는 첨부하지 않았습니다.
pinmonkeyiii

60

Ladislav Mrnka의 답변에 대한 작은 설명입니다 (수용된 답변이어야 함).

저와 같은 경우 다음과 같은 형식의 코드가 있습니다.

using (var context = new MyDataContext())
{
    context.MyTableEntity.Remove(EntytyToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

.. 그런 다음 원하는 작업 :

using (var context = new MyDataContext())
{
    // Note: Attatch to the entity:
    context.MyTableEntity.Attach(EntityToRemove);

    context.MyTableEntity.Remove(EntityToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

아마도 이것은 명백해 보이지만 처음에는 컨텍스트 뿐만 아니라 연결할 엔티티 를 지정해야한다는 것이 분명 하지 않았습니다 .


1
이 접근 방식을 사용하고 예외를받습니다. "Store update, insert 또는 delete 문이 예기치 않은 행 수 (0)에 영향을 미쳤습니다. 엔티티가로드 된 이후 엔티티가 수정되거나 삭제되었을 수 있습니다. ObjectStateManager 항목을 새로 고칩니다."
kat1330 2014 년

11

Kjartans 설명을 적절하게 설명하기 위해 :

나는 :

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = GetProject(id);
            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }

문제는 엔티티를 가져 오기 위해 내 자신의 메서드 (GetProject ())를 사용했다는 것입니다 (따라서 다른 컨텍스트를 사용하여 엔티티를로드 함).

public Project GetProject(int id)
    {
        using (var context = new Context())
        {
            var project = context.Projects
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Profession)))
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Room)))
                .SingleOrDefault(x => x.Id == id);
            return project;      
        }
    }

한 가지 해결책은 Kjartan이 말한대로로드 된 엔티티를 첨부하는 것이고, 다른 하나는 동일한 컨텍스트 내에서 엔티티를로드하기위한 광산 솔루션 일 수 있습니다.

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = context.Projects.SingleOrDefault(x => x.Id == id);
            if (p == null)
                return p;

            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }

2

나는이 질문이 꽤 오래되었다는 것을 알고 있지만 하나 이상의 클래스 / 서비스에서 레지스터를 삭제하고 각각이 자체 데이터베이스 연결 컨텍스트를 인스턴스화했기 때문에 위의 어느 것도 나를 위해 일하지 않았습니다.

내가 그것을 해결하기 위해 한 일은 데이터베이스에 액세스 할 나머지 클래스 / 서비스에 처음으로 생성 된 컨텍스트를 보내는 것이 었습니다.

예를 들어, serviceA레지스터 중 일부를 삭제하고 호출 serviceB하고 serviceC레지스터로 동일한 작업을 수행하려고했습니다.

나는 다음에 내 레지스터를 삭제할 것입니다 serviceA및 매개 변수로에서 생성 된 컨텍스트 패스 serviceA에를 serviceB하고 serviceC.


2

이 코드를 작성할 수 있습니다.

var x=yourquery.FirstOrDefault(); 

sqlEntities.DeleteObject(x);
sqlEntities.SaveChanges();

1

위의 방법 중 어느 것도 효과가없는 경우 다음 해결 방법을 시도해 볼 수 있습니다.

context.Entry(yourObject).State = System.Data.Entity.EntityState.Deleted; context.SaveChanges();


0

제거하려는 목록에 개체가 있는지 확인해야합니다. 다음 조건을 입력해야합니다.

if (context.entity.contains (객체))

그것을 제거하십시오.

동등성에 대한 복잡한 조건이있는 경우 확장 메소드 "entity.contains"에 대한 올바른 방법을 얻으려면 동등성에 대한 조건을두기 위해 엔티티 클래스의 동등 메소드를 재정의해야합니다.


0

Remove (Entity)로 전달되는 모델이 데이터베이스 레코드와 정확히 동일한 지 확인하십시오.

때때로 Id 또는 Date와 같은 일부 필드없이 모델을 전달할 수 있습니다. 양식으로 게시하는 경우 @ html.Hiddenfor에 보관하십시오.

가장 좋은 방법은 ID를 전달하고 Find (Id) 메서드를 사용하여 엔티티를 가져와 Remove (Entity)에 전달하는 것입니다.

이것이 누군가를 돕기를 바랍니다.


0

나는이 문제를 가지고 그것을 해결한다. 아래 코드를 복사하십시오.

sqlEntities.Attach(entity);
sqlEntities.Remove(entity);
sqlEntities.SaveChanges();

0

제 경우에는 컨텍스트가 하나 있었지만 'AsNoTracking'옵션이있는 엔티티가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.