Entity Framework 6 批量 Update/Delete 在一笔交易中
Entity Framework 6 Where in Bulk Update/Delete in one transaction
在 EF6 中,我想 update/delete 在一个查询中批量处理数据。
我的代码是
using (var context = _dataContextFactory.GetContext())
{
var result1 = from b in context.MyTables
where new List<int> {592, 593, 594}.Contains(b.Id)
select b;
foreach (var item in result1 )
{
item.StatusId = 3;
}
context.SaveChanges();
}
但是在SqlProfiler中,有3个脚本
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=592
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=593
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=594
是否可以在一个查询中获取带有 Where In 子句的脚本?
您无法在使用 EF 的一次 SQL 调用中更新多行。
您可以改为编写一个存储过程来高效地完成这项工作。或者使用提供 EF 扩展的第三方库来执行此操作。
当然,如果要更新的行数非常少,就没有意义了。
不幸的是,开箱即用的 Entity Framework 不支持此功能。但是,您可以使用 EntityFramework.Extended
库中的批量更新功能:
https://github.com/loresoft/EntityFramework.Extended
还有一个 nuget 包可用。
例如:
using EntityFramework.Extensions;
...
int[] myIds = { 592, 593, 594 };
using (var context = _dataContextFactory.GetContext())
{
// Define a filter expression to retrieve matching items
var filter = context.MyTables.Where(item => myIds.Contains(item.Id));
// Update the StatusId of matched items
context.MyTables.Update(filter, i => new Item { StatusId = 3 });
// NB: no context.SaveChanges() required
}
注意:可能有更有效的写法,但我仍在使用库。但是,它确实编译成单个 SQL 语句,并且该库还包括批处理的 DELETE。
最后,不用担心 new
表达式。此处未引用的任何属性将保留其原始值。
基于 @Dave R. 答案的最新 Z.EntityFramework.Plus (v5.1.16) 示例代码。此外,.Where
和 .Update
可以放在一个语句中:
using Z.EntityFramework.Plus;
...
int[] myIds = { 592, 593, 594 };
using (var context = _dataContextFactory.GetContext())
{
context.MyTables
.Where(item => myIds.Contains(item.Id))
.Update(i => new Item { StatusId = 3 });
}
在 EF6 中,我想 update/delete 在一个查询中批量处理数据。 我的代码是
using (var context = _dataContextFactory.GetContext())
{
var result1 = from b in context.MyTables
where new List<int> {592, 593, 594}.Contains(b.Id)
select b;
foreach (var item in result1 )
{
item.StatusId = 3;
}
context.SaveChanges();
}
但是在SqlProfiler中,有3个脚本
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=592
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=593
exec sp_executesql N'UPDATE [dbo].[MyTable] SET [StatusId] = @0 WHERE ([Id] = @1) ',N'@0 int,@1 int',@0=1,@1=594
是否可以在一个查询中获取带有 Where In 子句的脚本?
您无法在使用 EF 的一次 SQL 调用中更新多行。
您可以改为编写一个存储过程来高效地完成这项工作。或者使用提供 EF 扩展的第三方库来执行此操作。
当然,如果要更新的行数非常少,就没有意义了。
不幸的是,开箱即用的 Entity Framework 不支持此功能。但是,您可以使用 EntityFramework.Extended
库中的批量更新功能:
https://github.com/loresoft/EntityFramework.Extended
还有一个 nuget 包可用。
例如:
using EntityFramework.Extensions;
...
int[] myIds = { 592, 593, 594 };
using (var context = _dataContextFactory.GetContext())
{
// Define a filter expression to retrieve matching items
var filter = context.MyTables.Where(item => myIds.Contains(item.Id));
// Update the StatusId of matched items
context.MyTables.Update(filter, i => new Item { StatusId = 3 });
// NB: no context.SaveChanges() required
}
注意:可能有更有效的写法,但我仍在使用库。但是,它确实编译成单个 SQL 语句,并且该库还包括批处理的 DELETE。
最后,不用担心 new
表达式。此处未引用的任何属性将保留其原始值。
基于 @Dave R. 答案的最新 Z.EntityFramework.Plus (v5.1.16) 示例代码。此外,.Where
和 .Update
可以放在一个语句中:
using Z.EntityFramework.Plus;
...
int[] myIds = { 592, 593, 594 };
using (var context = _dataContextFactory.GetContext())
{
context.MyTables
.Where(item => myIds.Contains(item.Id))
.Update(i => new Item { StatusId = 3 });
}