web-dev-qa-db-ja.com

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

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

私のコードは:

    protected MyEntities sqlEntities;

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

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

protected MyEntities sqlEntities;

public virtual void Delete(TEntity entity)
{
    sqlEntities.Attach(entity);
    sqlEntities.DeleteObject(entity);
    sqlEntities.SaveChanges();
}
154
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();
}

おそらくこれは明白に思えますが、最初にcontextだけでなく、entityを指定する必要があることは明確ではありませんでした。

60
Kjartan

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が示すようにアタッチすることであり、別の解決策は私のソリューションであり、同じコンテキスト内でエンティティをロードすることです。

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

私はこの質問がかなり古いことを知っていますが、複数のクラス/サービスからレジスタを削除し、それぞれが独自のデータベース接続コンテキストをインスタンス化していたため、上記のいずれも機能しませんでした。

私がそれを解決したのは、最初に作成されたコンテキストを、データベースにアクセスする残りのクラス/サービスに送信することでした。

たとえば、私のserviceAはそのレジスターの一部を削除し、serviceBおよびserviceCを呼び出してそれらのレジスターで同じことを行います。

次に、serviceAのレジスタを削除し、serviceAで作成されたコンテキストをパラメーターとしてserviceBおよびserviceCに渡します。

2
Terkhos

このコードを書くことができます:

var x=yourquery.FirstOrDefault(); 

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

上記のいずれも機能しない場合は、次の解決策を試してください。

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

1
Ala' Alnajjar

削除しようとしているリストにオブジェクトが存在することを確認する必要があります。次の条件を設定する必要があります

if(context.entity.contains(your object))

それを除く。

同等の複雑な条件がある場合エンティティクラスのequalメソッドをオーバーライドする必要があります同等の条件を設定して、拡張メソッドの正しい方法を取得する"entity.contains" =

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

sqlEntities.Attach(entity);
sqlEntities.Remove(entity);
sqlEntities.SaveChanges();
0
vahid sabet

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

IdやDateなどのフィールドを使用せずにモデルを渡すことが可能な場合があります。フォームとして投稿する場合は、これらを@ html.Hiddenforに保持します。

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

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

0