有没有比使用DataTable更快的方式来使用SqlBulkCopy?

时间:2017-11-09 16:51:29

标签: c# sql-server sqlbulkcopy

我将大量记录加载到我的应用程序中(100万+)并对它们进行大量处理。处理要求它们都在内存中。

之后,我想将所有(现在已修改的)记录转储到空表中。

加载记录仅需几秒钟,我最终得到了大量MyRecord个项目。

使用SqlBulkCopy保存也需要几秒钟。

但是SqlBulkCopy要求(我相信)DataTable - 将我的记录加载到DataTable的速度很慢 - 每分钟大约7500条记录

dataTable.Rows.Add(myRecord.Name, myRecord.Age, ....)

有更快的方法来执行这个中间步骤吗?

2 个答案:

答案 0 :(得分:6)

导致延迟的原因是您必须先将所有内容缓冲到DataTable中,然后再将其发送到服务器。为了获得更好的性能,您应该立即将记录发送到SqlBulkCopy,并让该类使用自己的缓冲和批处理。

SqlBulkCopy可以与IDataReader一起使用。所有ADO.NET数据读取器都实现了此接口,因此您可以将从任何数据读取器读取的数据推送到SqlBulkCopy。

在其他情况下,假设您有一个IEnumerable对象,您可以使用来自FastMember包的Marc Gravel的ObjectReader在IEnumerable之上创建一个IDataReader。此数据读取器一次加载所有内容,因此在SqlBulkCopy请求之前不会缓存任何数据:

复制Marc Gravel的例子:

IEnumerable<SomeType> data = ... 

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
  bcp.DestinationTableName = "SomeTable"; 
  bcp.WriteToServer(reader); 
}

答案 1 :(得分:0)

我不知道问题是什么。下面的程序运行不到一秒钟。我怀疑速度慢是由于读取数据而不是写入DataTable。

       static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Col A", typeof(int));
            dt.Columns.Add("Col B", typeof(string));
            dt.Columns.Add("Col C", typeof(int));
            dt.Columns.Add("Col D", typeof(string));
            dt.Columns.Add("Col E", typeof(int));
            dt.Columns.Add("Col F", typeof(string));
            dt.Columns.Add("Col G", typeof(int));
            dt.Columns.Add("Col H", typeof(string));
            dt.Columns.Add("Col I", typeof(int));
            dt.Columns.Add("Col J", typeof(string));

            DateTime begin = DateTime.Now;

            for (int i = 0; i < 7500; i++)
            {
                dt.Rows.Add(new object[] {
                    i + 10000, "b", i + 20000, "d", i + 30000, "f", i + 40000, "h", i + 50000, "i"
                });
            }

            DateTime end = DateTime.Now;

            Console.WriteLine((end - begin).ToString());

            Console.ReadLine();
        }