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


当前回答

如果您正在使用通用存储库:

在泛型存储库中,下面可能是新方法。

       public void RemoveMultiple(Expression<Func<T, bool>> predicate)
        {
             IQueryable<T> query = _context.Set<T>().Where(predicate);
             _context.Set<T>().RemoveRange(query.AsNoTracking());
            
        }

用法:

_unitOfWork.YOUR_ENTITY.RemoveMultiple(x => x.AccountId == accountId);
 _unitOfWork.Complete();

其他回答

从服务器上拉回任何东西来删除它看起来仍然很疯狂,但至少只返回id比拉下完整的实体要精简得多:

var ids = from w in context.Widgets where w.WidgetId == widgetId select w.Id;
context.Widgets.RemoveRange(from id in ids.AsEnumerable() select new Widget { Id = id });

可以通过以下方式直接执行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(); 
}

我想出了一个很棒的库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方法。(它们只是同步方法的包装)在高负载环境中使用这个库可能会遇到很多意想不到的问题。

Best: EF6 => . removerang ()

例子:

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

你可以使用像EntityFramework这样的扩展库。Extended或Z.EntityFramework.Plus。EF6,有EF 5, 6或核心可用。当你必须删除或更新时,这些库具有出色的性能,并且它们使用LINQ。删除(source +)的示例:

ctx.Users。Where(x => x. lastlogindate < DateTime.Now.AddYears(-2)) delete ();

或(来源扩展)

context.Users。Where(u => u.FirstName == "firstname") delete ();

它们使用本地SQL语句,因此性能非常好。