2016-12-08 14 views
1

RemoveRange()を1問合せアプローチで実行する方法を探します。 Remove()方法で、それは次のように動作します。1問合せアプローチのEntity Framework 6でRemoveRangeを使用する方法

public void Delete() 
{ 
    Record record = new Record() { 
     id = 1, 
     value = 5 
    }; 
    using(SomeContext ctx = new SomeContext()) { 
     ctx.Records.Entry(record).State = EntityState.Deleted; 
     ctx.SaveChanges(); 
    } 
} 

しかし、同じアプローチがRemoveRange()のために動作しません。 EFのドキュメントによると、このメソッドは各エンティティをEntityState.Deletedに設定します。それは私がそれを理解するようになる場合 - これは動作します:

public void DeleteAll() 
{ 
    List<Record> records = new List<Record>() { 
     new Record() { id = 1, value = 5 }, 
     new Record() { id = 2, value = 10 } 
    }; 
    using(SomeContext ctx = new SomeContext()) { 
     ctx.Records.RemoveRange(records); 
     ctx.SaveChanges(); 
    } 
} 

これが動作するため:

public void DeleteAll() 
{ 
    List<Record> records = new List<Record>() { 
     new Record() { id = 1, value = 5 }, 
     new Record() { id = 2, value = 10 } 
    }; 
    using(SomeContext ctx = new SomeContext()) { 
     foreach(var item in records) 
     { 
      ctx.Entry(item).State = EntityState.Deleted; 
     } 
     ctx.SaveChanges(); 
    } 
} 

しかし、それは

The object cannot be deleted because it was not found in the ObjectStateManager. 

をせず、例外をスローすることができます私の別のクエリを介してデータベースからすべてを取得せずにこのメソッドを使用しますか?

答えて

2

ctx.Entry(item)を使用すると、この項目がコンテキストトラッキングに追加され、編集することができます。 RemoveRangeでは、最初に暗黙的にデータコンテキストに追加されるわけではないため、例外が発生します。それを行うには

代替方法: AttachRange

RemoveRange前に編集を使用してみてください。これはちょっと、 RemoveRangeが裏でそれをする方法です。最初に AutoDetectChangesを無効にし、必要なものを削除してから DetectChangesを呼び出します。これを拡張メソッドでラップして、もう一度それを1つのライナーにすることができます。

public void DeleteAll() 
{ 
    List<Record> records = new List<Record>() { 
     new Record() { id = 1, value = 5 }, 
     new Record() { id = 2, value = 10 } 
    }; 
    using(SomeContext ctx = new SomeContext()) { 
     ctx.Configuration.AutoDetectChangesEnabled = false; 
     foreach(var item in records) 
     { 
      ctx.Entry(item).State = EntityState.Deleted; 
     } 
     ctx.ChangeTracker.DetectChanges(); 
     ctx.SaveChanges(); 
    } 
} 
+0

から取ら

//Find all records in database with an id that is in your record collection var recordsToBeDeleted = ctx.Records.Where(dbr => records.Any(r => r.id == dbr.id)); ctx.Records.RemoveRange(recordsToBeDeleted); context.SaveChanges(); 

ソリューションは、EFのドキュメント内方法を見つけることができません。カスタムメソッドを意味しますか?それは十分に速いでしょうか? –

+0

EFコアのみの方法かもしれませんが、EF6にない可能性があります。申し訳ありません – Mats391

+0

さて、編集は私が求めていたものです、それは食べ物の練習ですか? 'ctx.Records.Where(dbr => records.Any(r => r.id == dbr.id));'を使ってデータベースからコレクションを取り出すよりも速くなるでしょうか?または状態を変更することは同じですか?データベースからすべてのレコードを取得するためにクエリを実行しますか? –

0

私のエンティティコレクションはデタッチされているため(そこに作成すると)、objectContextはそれを追跡しません。それを添付する必要があるかもしれません。あなたは以下のようにこれを行うことができます:this thread

+0

ありがとうございますが、削除する前にデータベースへのクエリを実行する必要があります。私はこれらのオブジェクトがデータベースに存在することを正確に知っていますので、レコードを最初に検索せずにレコードを削除したいと思います。 –

関連する問題