我正在使用实体框架从表中删除几个项目。没有外键/父对象,所以我不能用OnDeleteCascade处理这个。

现在我正在做这个:

var widgets = context.Widgets
    .Where(w => w.WidgetId == widgetId);

foreach (Widget widget in widgets)
{
    context.Widgets.DeleteObject(widget);
}
context.SaveChanges();

它工作,但foreach困扰我。我使用EF4,但我不想执行SQL。我只是想确保我没有错过任何东西-这是最好的,对吧?我可以用扩展方法或helper来抽象它,但在某些地方我们还是要用foreach,对吧?


当前回答

在EF 7中,您可以使用批量删除

    var ids = widgets.Select(x => x.Id).ToList();
    await _mrVodDbContext.Widgets.Where(x => ids.Contains(x.Id)).ExecuteDeleteAsync();

EF磁芯发生器

  DELETE FROM [i]
  FROM [Widgets] AS [i]
  WHERE [i].[Id] IN (4,3,2,1)

更多关于在发行说明中删除或更新的信息。https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#basic-executedelete-examples

其他回答

在EF 6.2中,这可以很好地将删除直接发送到数据库,而无需首先加载实体:

context.Widgets.Where(predicate).Delete();

对于固定谓词,它非常简单:

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();

如果你需要一个动态谓词,看看LINQKit (Nuget包可用),这样的东西在我的情况下工作得很好:

Expression<Func<Widget, bool>> predicate = PredicateBuilder.New<Widget>(x => x.UserID == userID);
if (somePropertyValue != null)
{
    predicate = predicate.And(w => w.SomeProperty == somePropertyValue);
}
context.Widgets.Where(predicate).Delete();

如果需要删除表中的所有行,可以使用sql命令

using (var context = new DataDb())
{
     context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}

TRUNCATE TABLE (Transact-SQL)从表中删除所有行,而不记录单个行删除。TRUNCATE TABLE类似于没有WHERE子句的DELETE语句;然而,TRUNCATE TABLE更快,使用更少的系统和事务日志资源。

你也可以使用DeleteAllOnSubmit()方法,通过将你的结果传递在一个通用列表中,而不是在var中。这样你的foreach减少到一行代码:

List<Widgets> widgetList = context.Widgets
              .Where(w => w.WidgetId == widgetId).ToList<Widgets>();

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

它可能仍然在内部使用循环。

Best: EF6 => . removerang ()

例子:

db.Table.RemoveRange(db.Table.Where(x => Field == "Something"));

我想出了一个很棒的库Zack.EFCore.Batch。它将您的表达式转换为简单的DELETE FROM ....在哪里查询。(就像一些建议的答案)https://github.com/yangzhongke/Zack.EFCore.Batch

使用示例:

等待ctx。DeleteRangeAsync<Book>(b => b. price > n);

Zack.EFCore.Batch库比Z.EntityFramework.Extended https://entityframework-extensions.net/有很多好处,后者没有真正的Async方法。(它们只是同步方法的包装)在高负载环境中使用这个库可能会遇到很多意想不到的问题。