我正在使用实体框架从表中删除几个项目。没有外键/父对象,所以我不能用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,对吧?


当前回答

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

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

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

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

其他回答

 context.Widgets.RemoveRange(context.Widgets.Where(w => w.WidgetId == widgetId).ToList());
                db.SaveChanges();

在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

最后,实体框架核心7通过ExecuteDelete命令引入了这个功能:

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

这里需要注意的是,ExecuteDelete不需要SaveChanges,根据它的文档:

该操作立即对数据库执行,而不是延迟到DbContext.SaveChanges()被调用。它也不以任何方式与EF更改跟踪器交互:当调用此操作时恰好被跟踪的实体实例不会被考虑,也不会被更新以反映更改。

我知道问题是EF4,但如果升级可以是一个选择!

可以通过以下方式直接执行sql查询:

    private int DeleteData()
{
    using (var ctx = new MyEntities(this.ConnectionString))
    {
        if (ctx != null)
        {

            //Delete command
            return ctx.ExecuteStoreCommand("DELETE FROM ALARM WHERE AlarmID > 100");

        }
    }
    return 0;
}

对于选择,我们可以使用

using (var context = new MyContext()) 
{ 
    var blogs = context.MyTable.SqlQuery("SELECT * FROM dbo.MyTable").ToList(); 
}

Best: EF6 => . removerang ()

例子:

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