2014-03-03 54 views
20

我想从表中删除多行。使用RemoveRange()批量删除行

在常规的SQL Server中,这将是简单的:

DELETE FROM Table 
WHERE 
    Table.Column = 'SomeRandomValue' 
    AND Table.Column2 = 'AnotherRandomValue' 

在实体框架6,他们已经推出了RemoveRange()方法。
但是,当我使用它时,Entity Framework不是使用我提供的where子句删除行,而是查询数据库以获取与where子句匹配的所有行,并使用它们的主键逐个删除它们。

这是EntityFramework的当前局限性吗? 还是我使用RemoveRange()错?

以下是我如何使用RemoveRange()

db.Tables.RemoveRange(
    db.Tables 
     .Where(_ => _.Column == 'SomeRandomValue' 
      && _.Column2 == 'AnotherRandomValue') 
); 
+0

表是您的存储库的名称? –

+3

[EntityFramework.Extended](https://github.com/loresoft/EntityFramework.Extended)具有[批量删除](https://github.com/loresoft/EntityFramework.Extended/wiki/Batch-Update-and-删除) – paqogomez

+1

看看这个:http://stackoverflow.com/questions/2519866/how-do-i-delete-multiple-rows-in-entity-framework-without-foreach –

回答

2

我想我们在这里达到了EF的限制。 有时您只需使用ExecuteSqlCommand即可保持高性能。

1

这是一个有点坏了,尝试

db.Tables.RemoveRange(
    db.Tables 
     .Where(_ => _.Column == 'SomeRandomValue' 
      && _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList() 
); 
db.SaveChanges(); 
+0

对不起,我仍然得到与此代码相同的结果。实体框架执行内部查询,然后遍历每一行并删除它们。 –

0

你为什么不只是有一个适配器连接到数据库,并只发送适当的删除像你的例子中的命令?

+3

我可以。但这意味着我必须自己编写基本的DELETE语句。这完全破坏了拥有ORM的点。另外,如果我想要一个复杂的WHERE子句呢?当我有一个超级通用的适配器可以处理一堆不同的WHERE子句时,我基本上已经自己构建了ORM。 –

1
var db1 = db.Tables 
     .Where(_ => _.Column == 'SomeRandomValue' 
      && _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList(); 
db.Tables.RemoveRange(db1); 
db.SaveChanges(); 

使用一个变量来存储可移动列表并将其传递给RemoveRange()。

我通常这样做,这就是工作。 希望这也适用于你的情况。

+1

对不起,我仍然得到与此代码相同的结果。实体框架执行内部查询,然后遍历每一行并删除它们。 –

+0

如果你的表有外键,使用[Foreign]属性在模型中指定并使用虚拟 – AKASH

0

退一步思考。你真的想从数据库中下载记录以删除它们吗?只是因为你不能把它变成一个好主意。

也许你可以考虑用存储过程从数据库中删除项目? EF也允许这样做......

+1

我同意存储过程在这种情况下是更好的解决方案。不过,我也相信这是EF的一个未来。删除符合特定条件的行是基本的CRUD。存储过程更好地实现这一点的事实违背了使用ORM的要点。 –

+0

也有一些是被称为“ORM阻抗失配”,它概括地说指出的是,数据库设计为 - 速度或CRUD操作 - 磁盘 高效的大小 - 参照完整性 并不仅仅是为了保持数据可用性重新启动后或跨系统边界共享数据。 –

3

您正在寻找的是一个批量删除库,它可以从LINQ查询中删除数据库中的多个记录,而无需加载实体。

存在支持此功能的多个库。

您可以在这里找到名单:Entity Framework Batch Delete Library

免责声明:我是这个项目的所有者Entity Framework Plus

// using Z.EntityFramework.Plus; // Don't forget to include this. 

// DELETE directly in SQL (without loading entities) 
db.Tables.Where(_ => _.Column == 'SomeRandomValue' 
        && _.Column2 == 'AnotherRandomValue') 
     .Delete(); 

// DELETE using a BatchSize  
db.Tables.Where(_ => _.Column == 'SomeRandomValue' 
        && _.Column2 == 'AnotherRandomValue') 
     .Delete(x => x.BatchSize = 1000); 

百科:EF+ Batch Delete

0

我处理这个自己,并同意阿迪 - 只是使用SQL。

我在日志表清理旧行和EF RemoveRange用了3分钟,这样做确实在3秒内同样的事情:

DELETE FROM LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < -6 

日期是列包含日期名称。为了使它正确,当然,使用这样的参数:

context.Database.ExecuteSqlCommand 
     ("DELETE FROM LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < @DaysOld", new System.Data.SqlClient.SqlParameter(
         "DaysOld", - Settings.DaysToKeepDBLogEntries)); 

请注意,有很多行涉及我的情况。当我开始项目并且没有很多数据时,RemoveRange运行良好。