如何在实体框架中删除多行(无foreach)

本文翻译自:How do I delete multiple rows in Entity Framework (without foreach)

I'm deleting several items from a table using Entity Framework. 我正在使用实体框架从表中删除多个项目。 There isn't a foreign key / parent object so I can't handle this with OnDeleteCascade. 没有外键/父对象,因此我无法使用OnDeleteCascade处理它。

Right now I'm doing this: 现在我正在这样做:

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

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

It works but the foreach bugs me. 它有效,但是foreach使我感到烦恼。 I'm using EF4 but I don't want to execute SQL. 我正在使用EF4,但我不想执行SQL。 I just want to make sure I'm not missing anything - this is as good as it gets, right? 我只想确保我没有遗漏任何东西-这是一样好,对吗? I can abstract it with an extension method or helper, but somewhere we're still going to be doing a foreach, right? 我可以使用扩展方法或辅助程序对其进行抽象,但是在某个地方我们仍将进行foreach,对吗?


#1楼

参考:https://stackoom.com/question/azx0/如何在实体框架中删除多行-无foreach


#2楼

For EF 4.1, 对于EF 4.1,

var objectContext = (myEntities as IObjectContextAdapter).ObjectContext;
objectContext.ExecuteStoreCommand("delete from [myTable];");

#3楼

I know it's quite late but in case someone needs a simple solution, the cool thing is you can also add the where clause with it: 我知道已经很晚了,但是如果有人需要一个简单的解决方案,很酷的事情是您还可以在其中添加where子句:

public static void DeleteWhere(this DbContext db, Expression> filter) where T : class
{
    string selectSql = db.Set().Where(filter).ToString();
    string fromWhere = selectSql.Substring(selectSql.IndexOf("FROM"));
    string deleteSql = "DELETE [Extent1] " + fromWhere;
    db.Database.ExecuteSqlCommand(deleteSql);
}

Note: just tested with MSSQL2008. 注意:刚刚使用MSSQL2008进行了测试。

Update: 更新:

The solution above won't work when EF generates sql statement with parameters , so here's the update for EF5 : 当EF生成带有参数的 sql语句时,上述解决方案将不起作用,因此这是EF5的更新:

public static void DeleteWhere(this DbContext db, Expression> filter) where T : class
{
    var query = db.Set().Where(filter);

    string selectSql = query.ToString();
    string deleteSql = "DELETE [Extent1] " + selectSql.Substring(selectSql.IndexOf("FROM"));

    var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_internalQuery").Select(field => field.GetValue(query)).First();
    var objectQuery = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_objectQuery").Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
    var parameters = objectQuery.Parameters.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();

    db.Database.ExecuteSqlCommand(deleteSql, parameters);
}

It requires a little bit of reflection but works well. 它需要一点反射,但是效果很好。


#4楼

对于使用EF5的任何人,都可以使用以下扩展库: https : //github.com/loresoft/EntityFramework.Extended

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

#5楼

EntityFramework 6 has made this a bit easier with .RemoveRange() . EntityFramework 6使用.RemoveRange()使此操作变得容易.RemoveRange()

Example: 例:

db.People.RemoveRange(db.People.Where(x => x.State == "CA"));
db.SaveChanges();

#6楼

See the answer 'favorite bit of code' that works 查看有效的答案“最喜欢的代码”

Here is how I used it: 这是我的用法:

     // Delete all rows from the WebLog table via the EF database context object
    // using a where clause that returns an IEnumerable typed list WebLog class 
    public IEnumerable DeleteAllWebLogEntries()
    {
        IEnumerable myEntities = context.WebLog.Where(e => e.WebLog_ID > 0);
        context.WebLog.RemoveRange(myEntities);
        context.SaveChanges();

        return myEntities;
    }

你可能感兴趣的:(如何在实体框架中删除多行(无foreach))