【问题标题】:SqlBulkCopy and Entity FrameworkSqlBulkCopy 和实体框架
【发布时间】:2011-02-02 22:58:07
【问题描述】:

我当前的项目包含 3 个标准层:数据、业务和演示。我想使用数据实体来满足我所有的数据访问需求。该应用程序的部分功能是需要将平面文件中的所有数据复制到数据库中。该文件不是那么大,所以我可以使用 SqlBulkCopy。我找到了几篇关于 .NET 中使用 SqlBulkCopy 类的文章。但是,所有文章都使用 DataTables 来回移动数据。

有没有办法将数据实体与 SqlBulkCopy 一起使用,还是我必须使用 DataTables?

【问题讨论】:

    标签: c# .net entity-framework sqlbulkcopy


    【解决方案1】:

    您需要将实体转换为 IDataReader 或 DataTable。

    有一个小助手类旨在帮助: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389

    编辑:msdn 链接已损坏,可在此处找到替代副本: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

    然后你可以像这样使用 SqlBulkCopy:

    var sbCopy= new SqlBulkCopy(connectionString);
    sbCopy.DestinationTableName = "TableName";
    sbCopy.WriteToServer(entitiesList.AsDataReader()); 
    

    【讨论】:

    • @JonBarker - 这是 GitHub 链接:github.com/matthewschrager/Repository/blob/master/…
    • @DaveHogan 我喜欢你在这里的想法。我们正在播种 200K 多个项目,至少可以说它很痛苦。我试图将其拉入我们的 repo EF 播种,但是在创建具有子对象的 Office 项目时,它不会创建子项目或关系船。这种事情是可能的还是超出了链接的代码范围?谢谢
    • @Jon - 如果不为每个子项手动显式设置 SqlBulkCopy 到表中(并手动管理关系约束),我认为您无法轻松地执行子项
    • 我是 ObjectDataReader 的原作者,并将其添加到新的 GitHub 主页:github.com/dbrownems/ObjectDataReader
    【解决方案2】:

    我们在使用 EF 进行批量插入时尝试并测试了几种方法,最终使用表值参数在一系列行大小下获得最佳性能。我手头没有数字,但我知道 Performance of bcp/BULK INSERT vs. Table-Valued Parameters 是一个指导因素。

    我们最初使用SqlBulkCopy 加上一个适配器,该适配器采用IEnumerable<T> 并创建了一个IDataReader。它还为 SqlBulkCopy 生成了相关的元数据。这里的优点是导入只是代码。 @davehogan 发布的代码被用作此的基础。

    表值参数需要在数据库中定义的存储过程和表类型。如果您使用代码优先,您可以执行 SQL 来创建这些作为创建脚本的一部分。虽然这是更多的工作,但我们发现我们在数据库中获得了更加一致和更快的行吞吐量。

    另外,值得考虑批量插入到您的主表中。我们使用临时堆表并在导入数据后为其添加聚集索引。然后我们在临时表和主表之间执行MERGE。这样做的好处是在插入时不锁定主表的索引并提高了并发性。使用这种方法插入的每个 CPU,我们倾向于获得超过 2500 行/秒的数据。

    如果您想了解更多信息,请告诉我。

    【讨论】:

      【解决方案3】:

      您可以使用Bulk package 库。 Bulk Insert 1.0.0 版本用于具有 Entity framework >=6.0.0 的项目。 更多描述可以在下面的链接中找到 - Bulkoperation source code

      【讨论】:

        【解决方案4】:

        对于 EFCore,这里有 BulkExtensions(插入、InsertOrUpdate 更新、删除):
        链接:https://github.com/borisdj/EFCore.BulkExtensions
        也可以通过Nuget安装

        【讨论】:

          【解决方案5】:

          SqlBulkCopy 在调用 WriteToServer 方法时使用 IDataReader,因此您应该能够基于 IEnumerable 集合实现 IDataReader。这将允许您接收一个实体集并使用您的 IDataReader 实现调用 SqlBulkCopy。

          【讨论】:

            【解决方案6】:

            您可以将数据集视为数据实体的序列化。但是一般来说,我认为 SqlBulkCopy 是一个表到表的东西,因此是数据表的原因。

            【讨论】:

              【解决方案7】:

              SqlBulkCopy 是一种直接的、几乎类似于字节数组的行数据从客户端到 SQL Server 的传输。这是将数据导入 SQL Server 的最有效方式。

              然而,它的性能在于真正的“批量”操作。数百或数千行不一定高到足以证明使用的合理性。数万到数百万行都是 SqlBulkCopy 的性能才会真正大放异彩。最后,我们真正谈论的只是将数据发送到服务器

              将一组行放入生产数据库的表中还有其他重大挑战。重新索引、重新排序(如果有聚集索引)、外键验证,所有这些类型的事情都会增加插入时间,并且可能会锁定表和索引。

              此外,TVP 数据被写入磁盘(作为临时表数据),然后可以访问以放入您的表中。 SqlBulkCopy 能够直接进入您的餐桌...在这种情况下性能明显更快,但是,必须平衡并发速度。

              我认为总体规则是,如果您有少量行要处理,请考虑 TVP,如果您有数千行,请考虑通过 SqlBulkCopy 尽快将其传输到 SQL Server。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-02-10
                • 2011-10-11
                • 2020-08-12
                • 2011-08-20
                • 2011-10-25
                • 2013-04-13
                • 2016-07-21
                • 1970-01-01
                相关资源
                最近更新 更多