我正在使用实体框架从表中删除几个项目。没有外键/父对象,所以我不能用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,在循环中调用DeleteObject是最好的方法。

但是,您可以使用我在这里描述的方法,通过扩展方法执行SQL,并使其完全通用。

尽管答案是3.5。对于4.0,我可能会在底层使用新的ExecuteStoreCommand API,而不是下拉到StoreConnection。

其他回答

对于 EC 4.1,

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

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

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

       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();

你可以使用像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语句,因此性能非常好。

如果你不想直接执行SQL,在循环中调用DeleteObject是最好的方法。

但是,您可以使用我在这里描述的方法,通过扩展方法执行SQL,并使其完全通用。

尽管答案是3.5。对于4.0,我可能会在底层使用新的ExecuteStoreCommand API,而不是下拉到StoreConnection。

EntityFramework 6使用. removerange()使这变得更容易一些。

例子:

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

警告!不要在大型数据集上使用此方法!

EF将所有数据拉入内存,然后删除它。对于较小的数据集,这可能不是一个问题,但通常避免这种类型的删除,除非你能保证你只做非常小的更改。

您可以很容易地将进程运行到内存不足的状态,而EF会很高兴地提取您指定的所有数据来删除它。