以下のようなエンティティフレームワークでオブジェクトを削除する前にオブジェクトを取得する必要があるように思えます
var customer = context.Customers.First(c => c.Id == 1);
context.DeleteObject(customer);
context.Savechanges();
そのため、データベースに2回アクセスする必要があります。もっと簡単な方法はありますか?
Entity Framework 6では、削除アクションはRemove
です。ここに例があります
Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();
@Nixと同じですが、厳密に型指定されるように少し変更されています。
クエリを行いたくない場合は、エンティティを作成して削除します。
Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.DeleteObject(customer);
context.SaveChanges();
同様の質問 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();
また、一括削除にも役立ちます。
クエリしたくない場合は、エンティティを作成してから削除します。
Customer customer = new Customer() { Id = 1 } ;
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();
私のプロジェクトの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プロジェクトでこのコードを使用しています。]
生の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.
}
}
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();
EF 1.0を使用している場合、それが最も簡潔な方法です。他の方法もあるかもしれませんが、彼らは私見の価値があるよりも厄介です。