2009-05-15 14 views
74

LINQまたはLINQ-to-Entitiesで特定のクエリに一致するオブジェクトの束を一括削除する方法はありますか?私が見つけることができる唯一の参照は古く、削除するすべてのオブジェクトを繰り返して手動で削除するのは愚かなようです。エンティティへのLINQでのバルク削除

答えて

28

質問は古いものです(EF5の前から)。 EF5を使用している人なら、EntityFramework.Extendedはこれを簡単に実行します。

EF6を使用して、削除する行のSQLクエリを実行したい人のための
+1

私はこれを受け入れられた答えに更新しました。 –

+1

EF 6 'RemoveRange' http://stackoverflow.com/a/21468165/1876572 – Eldho

3

私は、クエリのすべてのレコードを削除する任意のデータコンテキストのDeleteAllOnSubmitメソッドを知っています。多くのオブジェクトが削除されているため、いくつかの最適化が必要です。私は確信していません。

+2

実際には最適化が実行されていません。生成されたSQLは、クエリに一致するすべてのオブジェクトを列挙し、それらを手動で反復して削除します。確かに、反復ではなく、あなたのコードに比べて、DBに起こる、あなたはまだ不その内容を削除するだけで、結果セットを構築している - シンプル「FROMテーブルWHERE DELETE FOO = bar」の、構築さよりははるかに悪いです結果セットはなく、テーブルを1回だけカバーします。 –

2

は、私はそれが可能だろうか効率的わからないんだけど、あなたはこのような何かを試みることができる:

// deletes all "People" with the name "Joe" 
var mypeople = from p in myDataContext.People 
       where p.Name == "Joe"; 
       select p; 
myDataContext.People.DeleteAllOnSubmit(mypeople); 
myDataContext.SubmitChanges(); 
+0

それでも、クエリに一致するすべての要素を反復処理します。あなたのコードではなく、単にDB上で実行します。より効率的ですが、理想的なソリューションからはまだ遠いです。私はそれを行うに考えること –

+2

唯一の他の方法は、その後、myDataContext.ExecuteCommandを行うことであろう(「DELETE ...」);.理想からも遠いですが、うまくいくでしょう。 –

1

は、削除を行うストアドプロシージャを書いて、LINQからそれを呼び出すことができます。セットベースの削除は全体的に高速になる可能性がありますが、レコードに多大な影響を及ぼすとロックの問題を引き起こす可能性があります。また、レコードセットをループするハイブリッドが必要になることもあります(一度に2000個、サイズはデータベース設計によりますが、あなたがセットベースのdelteを見つけるのが始まったら、それはテーブルの他の使用に影響を与えています)削除を行います。

53

しばらくは戻って私は、Entity Frameworkで4一部のブログシリーズ(1つのコマンドで)一括更新をやってカバー(部品1234)を書きました。

そのシリーズの焦点は更新されましたが、間違いなく削除に関連する原則を使用できます。

ですから、このような何かを書くことができる必要があります:

var query = from c in ctx.Customers 
      where c.SalesPerson.Email == "..." 
      select c; 

query.Delete(); 

[削除()拡張メソッドを実装するだけです。

DeleteAllOnSubmitがあるSystem.Data.LinqとのITableの一部であり、私はここで見ている回答は、LINQ to SQLのです

ホープこれは

+0

優れたシリーズ。これに基づいてDelete()拡張メソッドを書くことは簡単です。 –

+15

誰かがそれを持っているなら、ここにこれのためのコードサンプルを持っていいですね! – jocull

+1

拡張メソッド(バッチ削除を含む)の束はここにあります:https://github.com/loresoft/EntityFramework.Extended – Soliah

6

を助け...方法についてのヒントのためのポストシリーズを参照してください。 LinqからSQLへ

これは、Entity Frameworkでは実行できません。

は、私はまだ解決策を持っていないが、私はEntity Frameworkのは、DeleteObjectのメソッドを使用してに依存している介してデータを削除する

38
using (var context = new DatabaseEntities()) 
    { 
     // delete existing records 
     context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId); 
    } 
+3

+1 - EFを使用してSQLコードを実行する方法のコード例をご覧ください。 –

+1

これはおそらくこれを行う唯一の方法であり、ストアドプロシージャを作成するのには不十分ですが、これは不正行為=と感じています。今、私はこれを使っていることを、私は笑EFのquirkinessをcicumventするためにいくつかの他の場所でそれを使用するように誘惑しています - そのような複雑な左結合やグループBYSとして..... :) – Losbear

+0

+ ... DBを使用した場合!あなたが望むツールはドライバーであることがわかります。EFはもう一つのハンマーです。 – gbjbaanb

1

を行うときにポストバックされることのすべてを語りました。このメソッドは、削除するエンティティクラスのEntityCollectionまたは派生したObjectContextで呼び出すことができます。ここに簡単な例があります:

NorthwindEntities db = new NorthwindEntities(); 

IEnumerable<Order_Detail> ods = from o in db.Order_Details 
           where o.OrderID == 12345          
           select o; 

foreach (Order_Detail od in ods) 
    db.Order_Details.DeleteObject(od); 

db.SaveChanges(); 
+0

に**強調表示されません**。おかげさまで – Nuzzolilo

4

:私のような何かをしたい

using (var context = new DatabaseEntities()) 
{ 
    // delete existing records 
    context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter); 
} 
+1

これはEF 5で私にとってはうまくいきましたが、パラメータとして@ p0を使用しなければなりませんでした。良いのは、生成されたSQLで型安全なparamチェックを提供するということです。つまり、EF5では、これはうまくいきます:context.Database.ExecuteSqlCommand( "DELETE FROM YOURTABLE WHERE CustomerID = @ p0"、idParameter); \ @ p1(次のパラメータなど)... –

1

var recordsToDelete = (from c in db.Candidates_T where c.MyField == null select c).ToList<Candidates_T>(); 
if(recordsToDelete.Count > 0) 
{ 
    foreach(var record in recordsToDelete) 
    { 
     db.Candidate_T.DeleteObject(record); 
     db.SaveChanges(); 
    } 
} 

を私はへの道があるとは思いませんEntity Frameworkはエンティティと動作し、ほとんどの場合、オブジェクトのコレクションを意味するので、ループなしで実行します。

+1

このような何かが私のために働いた。 – Demodave

+0

また、あなたがしたことを共有することもできます。ありがとう。 –

+0

@G Jeny Ramirez私のソリューションを追加しました。 – Demodave

1

この例では、削除するレコードを取得し、1つずつ結果セットに添付して削除するように要求します。その後、私は1回の変更を保存します。

using (BillingDB db = new BillingDB()) 
    { 
     var recordsToDelete = (from i in db.sales_order_item 
        where i.sales_order_id == shoppingCartId 
        select i).ToList<sales_order_item>(); 

     if(recordsToDelete.Count > 0) 
     { 
     foreach (var deleteSalesOrderItem in recordsToDelete) 
     {     
      db.sales_order_item.Attach(deleteSalesOrderItem); 
      db.sales_order_item.Remove(deleteSalesOrderItem);     
     } 
     db.SaveChanges(); 
     } 
    } 
1
context.Entity.Where(p => p.col== id) 
       .ToList().ForEach(p => db.Entity.DeleteObject(p)); 

これらはEF

RemoveRangeはEF6で導入されました
0

を使用してDBからレコードを削除する最速の方法であり、それはオブジェクトのリストを削除することができます。超簡単。

var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList(); 
db.PermitOrigins.RemoveRange(origins); 
db.SaveChanges(); 
+1

このコードスニペットは質問を解決するかもしれませんが[http://meta.stackexchange .com/questions/114762/explain-entire-code-based-answers)は本当にあなたの投稿の質を向上させるのに役立ちます。将来読者の質問に答えていることを覚えておいてください。そうした人々はあなたのコード提案の理由を知らないかもしれません。 – DimaSan

関連する問題