ObjectStateManagerで見つからなかったため、オブジェクトを削除できません


114

「ObjectStateManagerに見つからなかったため、オブジェクトを削除できません」というエラーが発生します。

私のコードは:

    protected MyEntities sqlEntities;

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

5
申し訳ありませんが、レコードのフェッチと削除に異なるデータコンテキストオブジェクトが使用されているというコードの問題がありました。
2011年

私はこのようなバグがありました:var entity = new TEntity() { PK_ID = 23 }; sqlEntities.DeleteObject(entity);私は、Entity Frameworkのは、PKに基づいてDeleteObjectのを呼ぶだろうと期待して、正しくそのPKが設定されたモックエンティティを作成しようとしていた
C. Tewalt

回答:


156

これは、エンティティがアタッチされていないことを意味します(同じコンテキストインスタンスによって読み込まれなかった)。これを試して:

protected MyEntities sqlEntities;

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

1
ラディスラフに感謝します。これは、親から子データを削除するときに2つのコンテキストが実行されていたときに役立ちました。これは、TransactionScopeの外部の別のコンテキストから呼び出されました。親呼び出しをスコープと同じコンテキスト内に移動し、私の問題は解決しました。
dan richardson、2013

1
@Ladislav:.Attachを使用すると、「エンティティオブジェクトはIEntityChangeTrackerの複数のインスタンスから参照できません。」という別のエラーが発生します。削除を妨げている他のオブジェクトインスタンスがすでに存在しているということですか?
Matt

2
@マット:いいえ、オブジェクトがすでに別のコンテキストにアタッチされていることを意味します。2個同時に装着することはできません。エンティティを削除するには、元のコンテキストを使用する必要があります。
Ladislav Mrnka 2013

@Ladislav:ありがとう、それはさらに調査するのに役立ちました-私それを解決する方法に答えるように思えるこの質問を見つけました:オブジェクトがEntity Frameworkのデータコンテキストにすでにアタッチされているかどうかを確認することは可能ですか?。あなたの言う通り、私の場合はこれが問題のようです。迅速な回答ありがとうございます!
Matt

リマインダーのおかげで、レコードを更新するときは添付しましたが、レコードを削除するときは添付しませんでした。
pinmonkeyiii 2014年

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
この方法を使用して、「ストアの更新、挿入、または削除ステートメントが予期しない行数(0)に影響しました。エンティティが読み込まれた後にエンティティが変更または削除された可能性があります。ObjectStateManagerエントリを更新してください。」という例外を受け取ります。
kat1330

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;      
        }
    }

1つの解決策は、読み込まれたエンティティをKjartanの状態としてアタッチすることであり、もう1つの解決策は、同じコンテキスト内でエンティティを読み込むための鉱山ソリューションである可能性があります。

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はそのレジスタの一部を削除して呼び出しserviceBserviceCそれらのレジスタで同じことを行いました。

次に、レジスタを削除serviceAし、serviceAto 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(your object))

それを除く。

等価性に関する複雑な条件がある場合、拡張機能メソッド「entity.contains」の正しい方法を得るには、エンティティークラスの等価メソッドをオーバーライドして、等価性の条件を設定する必要があります


0

Remove(Entity)に渡されるモデルがデータベースレコードと正確に同じであることを確認してください。

IdやDateなどの一部のフィールドなしでモデルを渡すことが可能な場合もあります。フォームとして投稿する場合は、@ html.Hiddenforに入れてください。

最良の方法は、IDを渡して、Find(Id)メソッドを使用してエンティティを取得し、それをRemove(Entity)に渡すことです。

これが誰かを助けることを願っています。


0

私はこの問題を解決しました。以下のコードをコピーしてください:

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

0

私の場合、1つのコンテキストがありましたが、「AsNoTracking」オプションを使用してエンティティを取得しました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.