我目前正在改进使用实体框架(并且具有4.0版本)的现有c#项目的性能。 在应用程序中完成了两种类型的批量操作:
目前它们是使用纯SQL语句完成的(“INSERT INTO ...”,“DELETE FROM ...”) (insert语句本身当前没有批量插入语句,而是一个“普通”插入语句)。
由于我对C#很陌生,我的第一步是研究如果我使用实体框架进行更新和删除,性能如何。
我的问题是三折:
(对于数据行,我说的是每个2k-200k的大小)。
由于
答案 0 :(得分:2)
我的问题是三折:
如果我尝试使用实体框架进行批量插入,那是真的吗? 它是否每插入一个数据行使用1个插入? (因此往返 每个插入)。因此,性能低于使用SQL “插入”?
是。如果要使用EF,请将以下属性设置为false以获得更快的性能:
MyContext.Configuration.AutoDetectChangesEnabled = false;
MyContext.Configuration.ValidateOnSaveEnabled = false;
这对删除语句也适用吗?
是。您还可以在数据库在删除级联上定义,然后数据库将删除引用的实体,因此不需要使用EF执行此操作。
这里的最佳做法是什么?要使用SQL语句?或者使用 实体框架,还是完全不同的东西?
您可以使用存储过程,在您的上下文中调用Query
MyContext.ExecuteStoreQuery("your query")
或
MyContext.Database.SqlCommand("your query");
另一种方法是在批处理之后调用SaveChanges()
(100,200个实体标记为已添加或已删除),然后处置上下文,以便实体仍未连接。然后创建一个新的上下文制作批处理并再次调用SaveChanges()
。
<强>更新强>
我没有使用这种方法,但你可以尝试一下。
SqlBulkCopy for Generic List (useful for Entity Framework & NHibernate)
下面的可重复使用的通用版本,它在2.4秒或更短时间内产生了15k插入物 + - 每秒6200行。我把它增加到4个目录,3939个224392行,+ - 5750 rps(在4个文件之间更改)。
答案 1 :(得分:2)
如果您确实想要插入批量数据,则可能需要使用SqlBulkCopy
。您可以在EF上下文使用的同一事务中使用它。
EF不适用于批量操作,您可能会发现其单行每语句DML方法对大型集合来说过于严格。它会强制进行大量的往返,大量的每语句开销,并阻止SQL Server同时优化多行的查询计划,这几乎总是比许多小查询更有效(例如,SQL Server将对所有行进行正确排序,以便索引可以按顺序更新。
通过使用EF来执行批量DML,您基本上强制SQL Server使用每行DML计划。
可以通过将密钥大量插入临时表,然后执行连接到该表的删除语句来处理批量删除。