.NET,实体框架:对象删除-哪个更快/更好?
有时我不得不一次删除许多行。它需要花费大量时间,例如,删除3000个元素+21000个相关元素大约需要4分钟 我的做法是:.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
// 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为单位的级联怎么样?它也能加速吗?