エンティティフレームワークを使用してIDでオブジェクトを削除する方法


105

以下のようなエンティティフレームワークでオブジェクトを削除する前に、オブジェクトを取得する必要があるようです

var customer = context.Customers.First(c => c.Id == 1);

context.DeleteObject(customer);

context.Savechanges();

したがって、データベースを2回ヒットする必要があります。もっと簡単な方法はありますか?


j.mp/f0x0Bhが答えです。これはすばらしい一般的な方法です
BritishDeveloper '28

回答:


93

Entity Framework 6では、削除アクションはRemoveです。ここに例があります

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();

16
なんでAttach?なぜRemoveそしてただではないのSaveChangesですか?
runeks 2018

3
エンティティをコンテキストにアタッチする必要があります。そうしないと、削除中にエラーが発生します。EFはこのコンテキストでのみエンティティを削除できます
Pierre-Luc

3
マニュアルによると、@ runeksエンティティは、削除操作を実行する前にコンテキスト内に存在している必要があります。ここdocs.microsoft.com/en-us/dotnet/api/…を
dwkd

1
アタッチを使用しなかったので問題ありませんでした
ILIAS M. DOLAPO

58

@Nixと同じですが、強く型付けされるように少し変更されています。

クエリを実行したくない場合は、エンティティを作成してから削除します。

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();

7
オブジェクトが欠落している場合は例外をスローするため、完璧ではありません。「DbUpdateConcurrencyException:ストアの更新、挿入、または削除ステートメントが予期しない行数(0)に影響しました。」DELETEステートメントと同様に、これを無視してください。
2015年

申し訳ありませんが、これにより検証が必要になりますが、常に必要ではなく、常に期待されています!
Hamed Zakery Miab 2017

32

ここで同様の質問。

Entity Frameworkには、EntityFramework-Plus(拡張ライブラリ)があります。
NuGetで利用できます。それからあなたは次のようなものを書くことができます:

// DELETE all users which has been inactive for 2 years
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2))
     .Delete();

また、一括削除にも役立ちます。


36
これが今ではコアEFライブラリの一部ではないという理由に反しています。
nathanchere 2013

1
@FerretallicA-同意。
acarlon 2013

2
このメソッドは廃止されました。context.Users.Where(user => user.Id == id).Delete();
マヌエル

エラー「A FROM句は現在DELETEステートメントではサポートされていません。」のため、Azure SQL DataWarehouseでは機能しません。しかし、Jonikの答えのような生のSQLは機能します。
Michael Freidgeim 2016

1
context.SaveChanges()は必要ですか?
Tomas Kubes

23

クエリしたくない場合は、エンティティを作成してから削除します。

Customer customer  = new Customer() {  Id = 1   } ; 
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();

6

私のプロジェクトの1つで次のコードを使用しています。

    using (var _context = new DBContext(new DbContextOptions<DBContext>()))
    {
        try
        {
            _context.MyItems.Remove(new MyItem() { MyItemId = id });
            await _context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            if (!_context.MyItems.Any(i => i.MyItemId == id))
            {
                return NotFound();
            }
            else
            {
                throw ex;
            }
        }
    }

このようにして、指定されたIDのアイテムを削除しようとしたときに例外が発生した場合にのみ、データベースを2回クエリします。次に、アイテムが見つからない場合は、意味のあるメッセージを返します。それ以外の場合は、例外をスローするだけです(さまざまな例外タイプのさまざまなcatchブロックを使用して、より適切な方法でこれを処理したり、ifブロックを使用してカスタムチェックを追加したりできます)。

[Entity Framework Coreを使用したMVC .Net Core / .Net Coreプロジェクトでこのコードを使用しています。]


2

生のSQLクエリは私が思う最も速い方法です

public void DeleteCustomer(int id)
{
   using (var context = new Context())
   {
      const string query = "DELETE FROM [dbo].[Customers] WHERE [id]={0}";
      var rows = context.Database.ExecuteSqlCommand(query,id);
      // rows >= 1 - count of deleted rows,
      // rows = 0 - nothing to delete.
   }
}

19
これは、EFで強く型付けされたオブジェクトの機能を使用する目的を無効にします。
LawMan、2015年

4
これは、EF IDキャッシュを危険にさらします。この後も、EFは削除されたエンティティを返します。
epox

1
他のソリューションでは機能しないのに、Azure SQL DataWarehouseで機能します。
Michael Freidgeim 16

1
これを行う場合は、ORMを使用しないこともできます。これはEFキャッシュを危険にさらすと思います。
Storm Muller

このスタイルは、SQLインジェクション攻撃に対して脆弱です。この特定の例では、変数が整数であるため保護されていますが、文字列変数でこのパターンを使用することはありません。
セレム

2

dwkdの答えは、この例外を見た場合を除いて、Entity Frameworkコアで主に機能しました。

InvalidOperationException:{'Id'}の同じキー値を持つ別のインスタンスが既に追跡されているため、エンティティタイプ 'Customer'のインスタンスは追跡できません。既存のエンティティをアタッチするときは、特定のキー値を持つエンティティインスタンスが1つだけアタッチされるようにしてください。'DbContextOptionsBuilder.EnableSensitiveDataLogging'を使用して、競合するキー値を確認することを検討してください。

例外を回避するために、コードを更新しました。

Customer customer = context.Customers.Local.First(c => c.Id == id);
if (customer == null) {
    customer = new Customer () { Id = id };
    context.Customers.Attach(customer);
}
context.Customers.Remove(customer);
context.SaveChanges();

1

小さいバージョン(以前のものと比較した場合):

var customer = context.Find(id);
context.Delete(customer);
context.SaveChanges();

このコードスニペットのコンテキストと、過去10年間に残された他の回答よりも優れている点について説明してください。
miken32

1

この回答は、ASP.NET MVC 5 Fundamentalsという名前のScott Allenのコースから実際に出されたものです。すでにここにあるどの回答よりも少しシンプルで直感的だと思うので、共有したいと思いました。また、Scott Allenおよび私が行った他のトレーニングによれば、findメソッドはデータベースからリソースを取得するための最適化された方法であり、既に取得されている場合はキャッシュを使用できます。このコードでは、コレクションはオブジェクトのDBSetを指します。オブジェクトは、任意の汎用オブジェクトタイプにすることができます。

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