.NET,实体框架:对象删除-哪个更快/更好?

.NET,实体框架:对象删除-哪个更快/更好?,.net,entity-framework,model-view-controller,compare,.net,Entity Framework,Model View Controller,Compare,有时我不得不一次删除许多行。它需要花费大量时间,例如,删除3000个元素+21000个相关元素大约需要4分钟 我的做法是: // removes settlement elements var settlementElements = context.SettlementElements.Where(x => x.SettlementElementSettlementId == id); context.SettlementElements.Remo

有时我不得不一次删除许多行。它需要花费大量时间,例如,删除3000个元素+21000个相关元素大约需要4分钟

我的做法是:

// removes settlement elements
var settlementElements = context.SettlementElements.Where(x => x.SettlementElementSettlementId == id);                     context.SettlementElements.RemoveRange(settlementElements);
我想知道,如果只获取这些元素的ID,用这些ID创建空对象,附加它们并删除,是否会比上面使用的删除范围更快?我的意思是这样的:

var settlementElementsIds = context.SettlementElements.Where(x => x.SettlementElementSettlementId == id).Select(x => x.SettlementElementId);
foreach (var seID in settlementElementsIds)
{
    var obj = new SettlementElements() { SettlementElementId = seID };
    context.SettlementElements.Attach(obj);
    context.SettlementElements.Remove(obj);
}

您在优化元素删除方面有经验吗?

每当我必须执行任何形式的批量处理时,我都会发现通过在存储过程中执行该操作可以提高速度。您可以通过创建删除和比较来运行快速测试,如果您可以选择存储过程,我可以提供帮助

如果在ef6版本中可用,也可以尝试使用RemoveRange而不是存储过程

db.SettleElements.RemoveRange(itemstodelete);
db.SaveChanges();
文档称Removate的性能可能比多次调用Remove要好得多


Source

每当我不得不进行任何形式的大容量处理时,我都会通过在存储过程中进行处理来提高速度。您可以通过创建删除和比较来运行快速测试,如果您可以选择存储过程,我可以提供帮助

如果在ef6版本中可用,也可以尝试使用RemoveRange而不是存储过程

db.SettleElements.RemoveRange(itemstodelete);
db.SaveChanges();
文档称Removate的性能可能比多次调用Remove要好得多

来源

TL;博士

如果您想要适当的批量删除功能,请使用EFPlus软件包:

细节

正如@tomlawrence所写,使用RemoveRange可以提高内存中循环的性能。然而,上面的代码将导致将记录检索到内存中,然后EF将为每个被删除的记录生成单独的DELETE语句,如下例所示:

context.Database.Log=Console.Write; var-id=111; var settlementElements=context.settlementElements 其中x=>x.SettlementElementSettlementId==id; context.SettlementElements.RemoveRangesettlementElements; 上下文变化; 将生成此输出,假设有3条记录要从结算ID=111中删除:

2017年10月25日下午2:08:33+03:00打开连接 选择 [Extent1]。[SettlementTelementId]作为[SettlementTelementId], [Extent1][SettlementSettlementId]作为[SettlementElementSettlementId], [Extent1].[Description]作为[Description] 来自[dbo]。[SettlementElements]作为[Extent1] 其中[Extent1]。[SettlementSettlementTid]=@p_ulinq_u0 -p__linq__0:'111'类型=Int32,IsNullable=false -于2017年10月25日下午2:08:33+03:00执行 -在5毫秒内完成,结果为:SqlDataReader 2017年10月25日下午2:08:33+03:00关闭连接 2017年10月25日下午2:08:33+03:00打开连接 于2017年10月25日下午2:08:33+03:00开始交易 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1111'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在1毫秒内完成,结果:1 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1112'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在0毫秒内完成,结果:1 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1113'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在0毫秒内完成,结果:1 2017年10月25日下午2:08:33+03:00承诺交易 2017年10月25日下午2:08:33+03:00关闭连接 如果我们有数百万条记录要删除,这绝对不是一个选项

使用EFPlus时,将显示以下代码:

使用Z.EntityFramework.Plus; // ... context.Database.Log=Console.Write; var-id=111; var settlementElements=context.settlementElements 其中x=>x.SettlementElementSettlementId==id; 结算。删除;//0 开始 删除前4000名 从 来自[dbo]。[SettlementElements]作为 内部联接选择 [Extent1][SettlementTelementId]作为[SettlementTelementId] 来自[dbo]。[SettlementElements]作为[Extent1] 其中[Extent1]。[SettlementSettlementTid]=@p_ulinq_u0 作为A[SettlementTelementId]=B[SettlementTelementId]上的B 设置@RowInfected=@@ROWCOUNT 设置@TotalRowInfected=@TotalRowInfected+@RowInfected 终止 选择@TotalRowInfected -p__linq__0:'111'类型=Int32,IsNullable=false -2017年10月25日下午2:20:29+03:00执行 -在2毫秒内完成,结果:3 2017年10月25日下午2:20:29+03:00关闭连接 我们可以看到:

SELECT语句消失了;内存中没有回迁 只有一条DELETE语句,而不是每条记录一条 TL;博士

如果您想要适当的批量删除功能,请使用EFPlus软件包:

细节

正如@tomlawrence所写,使用RemoveRange可以提高内存中循环的性能。然而,上面的代码将导致将记录检索到内存中,然后EF将生成单独的 删除每个被删除记录的DELETE语句,如下例所示:

context.Database.Log=Console.Write; var-id=111; var settlementElements=context.settlementElements 其中x=>x.SettlementElementSettlementId==id; context.SettlementElements.RemoveRangesettlementElements; 上下文变化; 将生成此输出,假设有3条记录要从结算ID=111中删除:

2017年10月25日下午2:08:33+03:00打开连接 选择 [Extent1]。[SettlementTelementId]作为[SettlementTelementId], [Extent1][SettlementSettlementId]作为[SettlementElementSettlementId], [Extent1].[Description]作为[Description] 来自[dbo]。[SettlementElements]作为[Extent1] 其中[Extent1]。[SettlementSettlementTid]=@p_ulinq_u0 -p__linq__0:'111'类型=Int32,IsNullable=false -于2017年10月25日下午2:08:33+03:00执行 -在5毫秒内完成,结果为:SqlDataReader 2017年10月25日下午2:08:33+03:00关闭连接 2017年10月25日下午2:08:33+03:00打开连接 于2017年10月25日下午2:08:33+03:00开始交易 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1111'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在1毫秒内完成,结果:1 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1112'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在0毫秒内完成,结果:1 删除[dbo].[SettlementElements] 其中[SettlementTelementId]=@0 -@0:'1113'类型=Int32 -于2017年10月25日下午2:08:33+03:00执行 -在0毫秒内完成,结果:1 2017年10月25日下午2:08:33+03:00承诺交易 2017年10月25日下午2:08:33+03:00关闭连接 如果我们有数百万条记录要删除,这绝对不是一个选项

使用EFPlus时,将显示以下代码:

使用Z.EntityFramework.Plus; // ... context.Database.Log=Console.Write; var-id=111; var settlementElements=context.settlementElements 其中x=>x.SettlementElementSettlementId==id; 结算。删除;//0 开始 删除前4000名 从 来自[dbo]。[SettlementElements]作为 内部联接选择 [Extent1][SettlementTelementId]作为[SettlementTelementId] 来自[dbo]。[SettlementElements]作为[Extent1] 其中[Extent1]。[SettlementSettlementTid]=@p_ulinq_u0 作为A[SettlementTelementId]=B[SettlementTelementId]上的B 设置@RowInfected=@@ROWCOUNT 设置@TotalRowInfected=@TotalRowInfected+@RowInfected 终止 选择@TotalRowInfected -p__linq__0:'111'类型=Int32,IsNullable=false -2017年10月25日下午2:20:29+03:00执行 -在2毫秒内完成,结果:3 2017年10月25日下午2:20:29+03:00关闭连接 我们可以看到:

SELECT语句消失了;内存中没有回迁 只有一条DELETE语句,而不是每条记录一条 正如@felix-b所回答的

如果你能使用它,最快的方法就是使用我的免费库+BatchDelete

另一种技术是,如果您已经拥有了所有要删除的实体,则使用BulkDelete

免责声明:我是项目的所有者

此库不是免费的,但允许您执行应用程序所需的所有批量操作,包括BulkDelete:

批量保存更改 隔板 批量更新 批量删除 大合并 批量同步 例如:

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);

// Customize Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});
正如@felix-b所回答的

如果你能使用它,最快的方法就是使用我的免费库+BatchDelete

另一种技术是,如果您已经拥有了所有要删除的实体,则使用BulkDelete

免责声明:我是项目的所有者

此库不是免费的,但允许您执行应用程序所需的所有批量操作,包括BulkDelete:

批量保存更改 隔板 批量更新 批量删除 大合并 批量同步 例如:

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);

// Customize Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});

以DB为单位的级联怎么样?它也能加速吗?以DB为单位的级联怎么样?它也能加速吗?