What’s the best way to bulk database inserts from c#?

前端 未结 10 2109
盖世英雄少女心
盖世英雄少女心 2020-12-02 14:22

How do I/what’s the best way to do bulk database inserts?

In C#, I am iterating over a collection and calling an insert stored procedure for each item in the collect

相关标签:
10条回答
  • 2020-12-02 15:12

    You could update with an Xml document, Sql 2005 works very well with them. One node per row, but just one parameter for Xml.

    0 讨论(0)
  • 2020-12-02 15:15

    Dump your data to a pipe delimited (or something else if your data has pipes in it) text file and use Bulk Insert.

    0 讨论(0)
  • 2020-12-02 15:16

    Re the solution for SqlBulkCopy, I created a class than takes Datatable or a List<T> and a Buffer size (CommitBatchSize). It will convert the list to a data table using an extension (in the second class).

    It works very fast. On my PC, I am able to insert more than 10 million complicated records in less than 10 seconds.

    Here is the class:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DAL
    {
    
    public class BulkUploadToSql<T>
    {
        public IList<T> InternalStore { get; set; }
        public string TableName { get; set; }
        public int CommitBatchSize { get; set; }=1000;
        public string ConnectionString { get; set; }
    
        public void Commit()
        {
            if (InternalStore.Count>0)
            {
                DataTable dt;
                int numberOfPages = (InternalStore.Count / CommitBatchSize)  + (InternalStore.Count % CommitBatchSize == 0 ? 0 : 1);
                for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++)
                    {
                        dt= InternalStore.Skip(pageIndex * CommitBatchSize).Take(CommitBatchSize).ToDataTable();
                    BulkInsert(dt);
                    }
            } 
        }
    
        public void BulkInsert(DataTable dt)
        {
            using (SqlConnection connection = new SqlConnection(ConnectionString))
            {
                // make sure to enable triggers
                // more on triggers in next post
                SqlBulkCopy bulkCopy =
                    new SqlBulkCopy
                    (
                    connection,
                    SqlBulkCopyOptions.TableLock |
                    SqlBulkCopyOptions.FireTriggers |
                    SqlBulkCopyOptions.UseInternalTransaction,
                    null
                    );
    
                // set the destination table name
                bulkCopy.DestinationTableName = TableName;
                connection.Open();
    
                // write the data in the "dataTable"
                bulkCopy.WriteToServer(dt);
                connection.Close();
            }
            // reset
            //this.dataTable.Clear();
        }
    
    }
    
    public static class BulkUploadToSqlHelper
    {
        public static DataTable ToDataTable<T>(this IEnumerable<T> data)
        {
            PropertyDescriptorCollection properties =
                TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }
    }
    

    }

    Here is an example when I want to insert a List of my custom object List<PuckDetection> (ListDetections):

    var objBulk = new BulkUploadToSql<PuckDetection>()
    {
            InternalStore = ListDetections,
            TableName= "PuckDetections",
            CommitBatchSize=1000,
            ConnectionString="ENTER YOU CONNECTION STRING"
    };
    objBulk.Commit();
    
    0 讨论(0)
  • 2020-12-02 15:20

    I construct the list as an xml string and pass it to the stored proc. In SQL 2005, it has enhanced xml functionalities to parse the xml and do a bulk insert.

    check this post: Passing lists to SQL Server 2005 with XML Parameters

    0 讨论(0)
提交回复
热议问题