在EntityFramework中更新或删除多个实体的推荐做法是什么?

时间:2012-03-19 19:56:57

标签: c# .net sql entity-framework

在SQL中,有时可能会编写类似

的内容
DELETE FROM table WHERE column IS NULL

UPDATE table SET column1=value WHERE column2 IS NULL

或可能适用于多行的任何其他标准。

据我所知,最好的EntityFramework可以做的就像

foreach (var entity in db.Table.Where(row => row.Column == null))
    db.Table.Remove(entity);   // or entity.Column2 = value;
db.SaveChanges();

但是当然会检索所有实体,然后为每个实体运行单独的DELETE查询。当有许多实体满足标准时,肯定会慢得多。

因此,简而言之,EntityFramework是否支持在单个查询中更新或删除多个实体?

3 个答案:

答案 0 :(得分:13)

EF不支持批量更新或删除,但您可以这样做:

db.Database.ExecuteSqlCommand("DELETE FROM ...", someParameter);

编辑:

真正想坚持LINQ查询的人有时会使用解决方法,他们首先从LINQ查询创建选择SQL查询:

string query = db.Table.Where(row => row.Column == null).ToString();

然后找到FROM的第一个匹配项,并用DELETE替换查询的开头,并使用ExecuteSqlCommand执行结果。这种方法的问题在于它仅适用于基本场景。它不适用于实体拆分或某些继承映射,您需要为每个实体删除两个或多个记录。

答案 1 :(得分:5)

看看Entity Framework Extensions (Multiple entity updates)。该项目允许使用lambda表达式进行集合操作。来自doc的样本:

this.Container.Devices.Delete(o => o.Id == 1);

this.Container.Devices.Update(
     o => new Device() { 
        LastOrderRequest = DateTime.Now, 
        Description = o.Description + "teste"
     }, 
     o => o.Id == 1);

挖掘EFE project source code你可以看到自动化@Ladislav Mrnka的第二种方法也增加了设置操作:

    public override string GetDmlCommand()
    {
        //Recover Table Name

        StringBuilder updateCommand = new StringBuilder();
        updateCommand.Append("UPDATE ");
        updateCommand.Append(MetadataAccessor.GetTableNameByEdmType(
                                  typeof(T).Name));
        updateCommand.Append(" ");
        updateCommand.Append(setParser.ParseExpression());
        updateCommand.Append(whereParser.ParseExpression());

        return updateCommand.ToString();
    }

编辑3年后

看看这个好的答案:https://stackoverflow.com/a/12751429

答案 2 :(得分:2)

实体框架扩展库有助于实现此目的。

删除

//delete all users where FirstName matches
context.Users.Delete(u => u.FirstName == "firstname");

更新

//update all tasks with status of 1 to status of 2
context.Tasks.Update(
    t => t.StatusId == 1, 
    t2 => new Task {StatusId = 2});

//example of using an IQueryable as the filter for the update
var users = context.Users.Where(u => u.FirstName == "firstname");
context.Users.Update(users, u => new User {FirstName = "newfirstname"});

https://github.com/loresoft/EntityFramework.Extended