这实际上不是 EF 的用途。EF 的数据库交互从记录对象开始,并从那里流动。如果实体没有被跟踪(因此被加载),EF 不能生成部分更新(即不覆盖所有内容),同样它不能基于条件而不是键删除记录。
对于条件更新/删除逻辑,没有等效的 EF(不加载所有这些记录),例如
UPDATE People
SET FirstName = 'Bob'
WHERE FirstName = 'Robert'
或者
DELETE FROM People
WHERE FirstName = 'Robert'
使用 EF 方法执行此操作将要求您加载所有这些实体,只是为了将它们(通过更新或删除)发送回数据库,正如您已经发现的那样,这是对带宽和性能的浪费。
我在这里找到的最佳解决方案是绕过 EF 的 LINQ 友好方法,而是自己执行原始 SQL。这仍然可以使用 EF 上下文来完成。
using (var ctx = new MyContext())
{
string updateCommand = "UPDATE People SET FirstName = 'Bob' WHERE FirstName = 'Robert'";
int noOfRowsUpdated = ctx.Database.ExecuteSqlCommand(updateCommand);
string deleteCommand = "DELETE FROM People WHERE FirstName = 'Robert'";
int noOfRowsDeleted = ctx.Database.ExecuteSqlCommand(deleteCommand);
}
更多信息在这里。当然不要忘记在相关的地方防止 SQL 注入。
运行原始 SQL 的特定语法可能因 EF/EF Core 版本而异,但据我所知,所有版本都允许您执行原始 SQL。
我无法具体评论 EF Extensions 或 BulkUpdate 的性能,也不会从他们那里购买。
根据他们的文档,他们似乎没有具有正确签名的方法来允许有条件的更新/删除逻辑。
BulkUpdate
似乎不允许您输入允许您优化它的逻辑条件(UPDATE 命令中的 WHERE)。
BulkDelete
仍然有一个BatchSize
设置,这表明他们仍然一次处理一个记录(好吧,我猜是每批),而不是使用带有条件的单个 DELETE 查询(WHERE 子句)。
根据您在问题中的预期代码,EF Extensions 并没有真正为您提供所需的东西。简单地在数据库上执行原始 SQL 性能更高,成本更低,因为这绕过了 EF 加载其实体的需要。
更新
我可能会更正,对条件更新逻辑有一些支持,如此处所示。但是,我不清楚该示例是否仍将所有内容加载到内存中,如果您已经将所有内容都加载到内存中,那么条件 WHERE 逻辑的目的是什么(为什么不使用内存中的 LINQ?)
但是,即使这在不加载实体的情况下工作,它仍然是:
- 更受限制(与允许任何有效 SQL 的布尔条件的 SQL 相比,只允许相等检查),
- 相对复杂(我不喜欢他们的语法,也许这是主观的)
- 而且成本更高(仍然是付费图书馆)
与滚动您自己的原始 SQL 查询相比。我仍然建议在这里滚动你自己的原始 SQL,但这只是我的意见。