EF6 + SQL 14:将大量行上传到表中的最有效方法
Posted
技术标签:
【中文标题】EF6 + SQL 14:将大量行上传到表中的最有效方法【英文标题】:EF6 + SQL 14: The most effective way to upload large number of rows into a table 【发布时间】:2016-07-25 15:30:46 【问题描述】:使用 Entity Framework 6 和 SQL Server 2014:
我需要将 XML 文件中的大约 200,000 行上传到 SQL Server 表中。每行有 5 个字段。一行的数据不大,但是我的行数很多。
在你的 C# 应用程序中,我可以解析 XML 文件并在内存中读取它的数据没有问题。但我担心每行向 SQL Server 发送一个 TSQL 存储过程调用效率不高。在 EF6 中实现此要求的最有效方法是什么?
如果Entity Framework不适合这个,我可以直接使用ADO.NET。
【问题讨论】:
如果您需要做的事情包括大量的清理和转换,请考虑在 SSIS 中进行。 @HLGEM,将 SSIS 许可成本和部署添加到一个文件的体系结构会有点过度设计。 【参考方案1】:您可以将多行打包到一个 DataTable 中,并作为表值参数 (tvp) 传递给您的存储过程。您的存储过程可以使用 tvp 作为源执行 MERGE 语句,或者连接到 tvp 的 INSERT 语句。
这在使用直接 ADO.NET 时效果很好。从一个快速的谷歌来看,它看起来也应该通过实体框架工作。例如:http://www.c-sharpcorner.com/UploadFile/78607b/using-table-valued-parameters-in-entity-framework
一些tvps相关的链接:
http://www.sommarskog.se/arrays-in-sql-2008.html
http://www.sommarskog.se/arrays-in-sql-perftest-2009.html
【讨论】:
这太棒了。非常感谢!是否有任何指导方针可以有多大的 TVP?我正在考虑将数据分成块,但我需要知道 TVP 的最佳大小是多少? 我对 TVP 的大小没有任何限制,但我想如果它们太大,您最终可能会遇到操作系统强加的内存限制。将其分成块是一个好主意 - 它还可能有助于减少 MERGE 或 INSERT 期间 SQL Server 锁定的数量。我通常使块大小可配置,以便在代码实现和试用后轻松调整。如果 tvp 只有一个 guid 主键,我会将块大小默认为 5000 或类似的值,但显然涉及很多因素。【参考方案2】:尝试使用OPENROWSET
直接解析:
DECLARE @xml XML
SELECT @xml = BulkColumn
FROM OPENROWSET(BULK 'D:\sample.xml', SINGLE_BLOB) x
SELECT t.c.value('.', 'NVARCHAR(100)')
FROM @xml.nodes('root/row') t(c)
GO
【讨论】:
SQL Server 机器无权访问 \\UNC\Share\File.xml。 OPENROWSER 能否在 SqlClinet 机器上打开文件并发送到 SQL 服务器?【参考方案3】:您可以通过在添加实体并在调用 SaveChanges 之前再次打开它时设置 context.AutoDetectChangesEnabled = false 来显着提高实体框架的性能。小批量添加实体并每次处理上下文也会有所帮助。
或者有一些第三方库做得更好:
EntityFramework.BulkInsert
Entity Framework Extensions
Entity Framework Plus
后两者是商业的,我相信 Entity Framework Plus 是 Entity Framework Extensions 的演变。
【讨论】:
以上是关于EF6 + SQL 14:将大量行上传到表中的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章