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

Jef*_*eff 90 entity entity-framework

在我看来,我必须在使用下面的实体框架删除它之前检索一个对象

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

context.DeleteObject(customer);

context.Savechanges();
Run Code Online (Sandbox Code Playgroud)

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

dwk*_*wkd 77

在Entity Framework 6中,删除操作是Remove.这是一个例子

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

  • 人们可能会混淆 Entity Framework Core 和 Entity Framework 之间删除的用法。确实,对于实体框架,需要在“Attach”方法之后调用“Remove”方法,正如@Pierre-Luc提到的那样。但是,对于 [EFCore](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.remove),“Remove”方法将开始跟踪已删除的实体。 (22认同)
  • 为什么`附加'?为什么不只是'删除'和`SaveChanges`? (10认同)
  • 您必须将实体附加到上下文中,因为如果不这样做,则在删除时会收到错误消息。EF只能在这种情况下删除实体 (2认同)
  • 根据该手册,实体必须在上下文中存在@runeks,然后才能执行Remove操作。参见此处https://docs.microsoft.com/zh-cn/dotnet/api/system.data.entity.dbset.remove?view=entity-framework-6.2.0 (2认同)
  • 我没有使用attach,效果很好 (2认同)

Saw*_*wan 52

与@Nix相同,只需要进行一些小改动即可进行强类型化:

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

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

  • 不完美,因为如果对象丢失则抛出异常:"DbUpdateConcurrencyException:存储更新,插入或删除语句影响了意外的行数(0)." 我想要忽略它,就像DELETE语句一样. (6认同)

aca*_*lon 25

类似的问题在这里.

使用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();
Run Code Online (Sandbox Code Playgroud)

它对批量删除也很有用.

  • 它无视现在这不是核心EF库的一部分. (28认同)
  • 此方法已过时使用: context.Users.Where(user=&gt; user.Id == id).Delete(); (3认同)
  • 是否需要 context.SaveChanges() ? (3认同)
  • @FerretallicA - 同意。 (2认同)

Nix*_*Nix 22

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

Customer customer  = new Customer() {  Id = 1   } ; 
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();
Run Code Online (Sandbox Code Playgroud)


Sha*_*ami 19

从 Entity Framework Core 7 开始,您可以使用以下命令:

await context.Customers.Where(c => c.Id == 1).ExecuteDeleteAsync();
Run Code Online (Sandbox Code Playgroud)


Val*_*alo 8

在 EF Core 中,如果您不关心对象是否存在,而只关心它不会在数据库中,那么最简单的是:

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

您实际上并不需要Attach()- 它将对象添加到状态中的更改跟踪器Unchanged并将Remove()对象添加到状态中的跟踪器Deleted。然而,最重要的是,您只需要与后端进行一次往返。


dem*_*ron 6

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

    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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

这样,只有在尝试删除具有指定ID的项时发生异常时,它才会查询数据库两次.然后,如果找不到该项,则返回有意义的消息; 否则,它只会抛出异常(您可以使用不同的异常类型的不同catch块以更适合您的情况的方式处理它,使用if块添加更多自定义检查等).

[我在具有Entity Framework Core的MVC .Net Core/.Net Core项目中使用此代码.]


and*_*der 5

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

        var object = context.collection.Find(id);  
        context.collection.Remove(object);
        context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

  • 虽然这在语法上是最简单的,但OP特别要求一种无需两次访问数据库即可删除的方法。这是可行的,但它会在数据库上执行 SELECT(查找),然后执行 DELETE(删除/保存更改)...正如 @demonicdaron 已经提到的,如果查找返回 null,则会失败。 (3认同)
  • 对象可以为空。如果为空,则 .Remove(object); 会抛出异常。 (2认同)