web-dev-qa-db-ja.com

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

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

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

context.DeleteObject(customer);

context.Savechanges();

そのため、データベースに2回アクセスする必要があります。もっと簡単な方法はありますか?

86
Jeff

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

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

@Nixと同じですが、厳密に型指定されるように少し変更されています。

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

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

同様の質問 here

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();

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

24
acarlon

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

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

私のプロジェクトの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プロジェクトでこのコードを使用しています。]

6
demonicdaron

生の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.
   }
}
2
Jonik

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
Jeffrey Rennie

EF 1.0を使用している場合、それが最も簡潔な方法です。他の方法もあるかもしれませんが、彼らは私見の価値があるよりも厄介です。

0
Dave Swersky