实体框架6在一个事务中批量更新/删除的位置

时间:2015-02-18 13:13:11

标签: c# entity-framework-6

在EF6中,我想在一个查询中更新/删除批量数据。 我的代码是

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

            }

但是在Sql Profiler中,有三个脚本

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子句获取脚本?

3 个答案:

答案 0 :(得分:10)

不幸的是,实体框架中不支持此功能。但是,您可以使用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表达式。此处未引用的任何属性将保留其原始值。

答案 1 :(得分:0)

您无法使用EF在一个SQL调用中更新多个行。

您可以做的是编写一个能够有效地为您完成工作的存储过程。或者使用提供EF扩展的第三方库来执行此操作。

当然,如果要更新的行数非常小,则没有意义。

答案 2 :(得分:0)

基于 @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 });
}