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


当前回答

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

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

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

其他回答

请看答案“最喜欢的代码”

下面是我如何使用它:

     // 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<WebLog> DeleteAllWebLogEntries()
    {
        IEnumerable<WebLog> myEntities = context.WebLog.Where(e => e.WebLog_ID > 0);
        context.WebLog.RemoveRange(myEntities);
        context.SaveChanges();

        return myEntities;
    }

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

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

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

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

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

对于 EC 4.1,

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

我知道已经很晚了,但如果有人需要一个简单的解决方案,最酷的事情是你还可以添加where子句:

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

注意:刚刚用MSSQL2008测试过。

更新:

上面的解决方案不会工作时,EF生成sql语句的参数,所以这里是EF5的更新:

public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
    var query = db.Set<T>().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);
}

这需要一点反思,但效果很好。

EF 6.=>

var assignmentAddedContent = dbHazirBot.tbl_AssignmentAddedContent.Where(a =>
a.HazirBot_CategoryAssignmentID == categoryAssignment.HazirBot_CategoryAssignmentID);
dbHazirBot.tbl_AssignmentAddedContent.RemoveRange(assignmentAddedContent);
dbHazirBot.SaveChanges();