如何使用实体框架通过标识删除对象

在我看来,我必须检索一个对象,然后才能使用实体框架删除它,如下所示

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


context.DeleteObject(customer);


context.Savechanges();

所以我需要查两次数据库,有更简单的方法吗?

149257 次浏览

如果您不想查询它,只需创建一个实体,然后删除它。

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

与@Nix 相同,但有一个小更改要强类型化:

如果您不想查询它,只需创建一个实体,然后删除它。

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

类似的问题 给你

有了实体框架,就有了 EntityFramework-Plus(扩展库)。
然后你可以写下这样的东西:

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

它对于批量删除也很有用。

我认为原始 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.
}
}

在实体框架6中,删除操作是 Remove

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

我在我的一个项目中使用以下代码:

    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 的项时,只有在发生异常时,它才会查询数据库两次。然后,如果没有找到这个条目,它会返回一条有意义的消息; 否则,它只是将异常抛回(你可以使用不同的 catch 块处理不同的异常类型,使用 if 块添加更多自定义检查等等)。

[我在一个带有实体框架核心的 MVC. Net Core/. Net Core 项目中使用这段代码。]

Dwkd 的回答在实体框架核心中大多对我有用,除了当我看到这个异常时:

InvalidOperationException: 实体类型“ Customer”的实例不能 将被跟踪,因为另一个实例与{‘ Id’}具有相同的键值 附加现有实体时,请确保 只附加一个具有给定键值的实体实例。 可以考虑使用“ DbContextOptionsBuilder.EnableSenstiveDataLogging”来 查看相互冲突的键值。

为了避免异常,我更新了代码:

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

更小的版本(与之前的版本相比) :

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

这个答案实际上来自于 Scott Allen 的课程《 ASP.NET MVC 5基础》。我想我会分享,因为我认为它比这里的任何答案都更简单,更直观。还要注意的是,根据 Scott Allen 和我所做的其他培训,find 方法是从数据库中检索资源的一种优化方法,如果资源已经被检索,它可以使用缓存。在此代码中,集合引用对象的 DBSet。对象可以是任何泛型对象类型。

        var object = context.collection.Find(id);
context.collection.Remove(object);
context.SaveChanges();

来自官方文件(也是迄今为止我发现的最有效的一个) :

Student studentToDelete = new Student() { ID = id };
_context.Entry(studentToDelete).State = EntityState.Deleted;
await _context.SaveChangesAsync();

简单易懂的版本。

var customer = context.Find<Customer>(id);
context.Remove(customer);
context.SaveChanges();

在 EF Core 中,如果你不关心对象是否存在,你只关心它不在数据库中,最简单的方法是:

context.Remove(new Customer(Id: id));  // adds the object in "Deleted" state
context.SaveChanges();                 // commits the removal

你并不真的需要 Attach()-它将对象添加到 Unchanged状态下的变更跟踪器,而 Remove()将对象添加到 Deleted状态下的跟踪器。然而,最重要的是,您只需要对后端执行一次往返操作。