• C# 使用SqlBulkCopy类批量复制大数据


    用途说明:

    前些日子,公司要求做一个数据导入程序,要求将Excel数据,大批量的导入到数据库中,尽量少的访问数据库,高性能的对数据库进行存储。于是在网上进行查找,发现了一个比较好的解决方案,就是采用SqlBulkCopy来处理存储数据。SqlBulkCopy存储大批量的数据非常的高效,就像这个方法的名字一样,可以将内存中的数据表直接的一次性的存储到数据库中,而不需要一次一次的向数据库Insert数据。初次实验,百万级别的数据表,也只需几秒时间内就可以完全的存入数据库中,其速度,比传统的Insert方法不止快很多倍


           MSDN摘要:Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同服务器上)。SqlBulkCopy 类允许编写提供类似功能的托管代码解决方案。还有其他将数据加载到 SQL Server 表的方法(例如 INSERT 语句),但相比之下 SqlBulkCopy 提供明显的性能优势。

    使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用IDataReader 实例读取数据。

    复制代码
      /// <summary>
            /// 
            /// </summary>
            /// <param name="connectionString">目标连接字符</param>
            /// <param name="TableName">目标表</param>
            /// <param name="dt">源数据</param>
            private void SqlBulkCopyByDatatable(string connectionString, string TableName, DataTable dt)
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    using (SqlBulkCopy sqlbulkcopy =new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction))
                    {
                        try
                        {
                            sqlbulkcopy.DestinationTableName = TableName;
                            for (int i = 0; i < dt.Columns.Count; i++)
                            {
                                sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
                            }
                            sqlbulkcopy.WriteToServer(dt);
                        }
                        catch (System.Exception ex)
                        {
                            throw ex;
                        }
                    }
                }
            }
    复制代码
    复制代码
     SqlBulkCopy使用使用用于自定义表类型作为存储过程参数,批量写入数据。
     
      如果,大家使用SQL Server 2008,它提供一个新的功能表变量(Table Parameters)可以将整个表数据汇集成一个参数传递给存储过程或SQL语句。它的注意性能开销是将数据汇集成参数(O(数据量))。
     
      现在,我们修改之前的代码,在SQL Server中定义我们的表变量,具体定义如下:
     -- =============================================
    -- Author:        JKhuang
    -- Create date: 08/16/2012
    -- Description:    Declares a user table paramter.
    -- =============================================
    CREATE TYPE jk_users_bulk_insert AS TABLE (
        user_login varchar(60),
        user_pass varchar(64),
        user_nicename varchar(50),
        user_email varchar(100),
        user_url varchar(100),
        user_activation_key varchar(60),
        user_status int,
        display_name varchar(250)
    )
     
      上面,我们定义了一个表参数jk_users_bulk_insert,接着我们定义一个存储过程接受表参数jk_users_bulk_insert,具体定义如下:
     -- =============================================
    -- Author:        JKhuang
    -- Create date: 08/16/2012
    -- Description:    Creates a stored procedure, receive
    -- a jk_users_bulk_insert argument.
    -- =============================================
    CREATE PROCEDURE sp_insert_jk_users 
    @usersTable jk_users_bulk_insert READONLY 
    AS
    INSERT INTO jk_users (user_login, user_pass, user_nicename, user_email, user_url, 
    user_activation_key, user_status, display_name, user_registered) 
    SELECT user_login, user_pass, user_nicename, user_email, user_url, 
    user_activation_key, user_status, display_name, GETDATE() 
    FROM @usersTable 
      接下我们在客户端代码中,调用存储过程并且将表作为参数方式传递给存储过程。
     var sw = Stopwatch.StartNew();
    using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLCONN2"].ToString()))
    {
        conn.Open();
        //// Invokes the stored procedure.
        using (var cmd = new SqlCommand("sp_insert_jk_users", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            //// Adding a "structured" parameter allows you to insert tons of data with low overhead
            var param = new SqlParameter("@userTable", SqlDbType.Structured) { Value = dt };
            cmd.Parameters.Add(param);
            cmd.ExecuteNonQuery();
        }
    }
    sw.Stop(); 
      现在,我们重新执行写入操作发现写入效率与SqlBulkCopy相当。
    复制代码

    ///批量插入实例------------------------------------------------------------个人案例
    using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Impoort { class Program { public static PQMEntities db = new PQMEntities(); static void Main(string[] args) { var users = db.Database.SqlQueryForDataTatable("select * from Right_Users", null); SqlBulkCopyByDatatable(db.Database.Connection.ConnectionString, "Right_UserTemp", users); } private static void SqlBulkCopyByDatatable(string connectionString, string TableName, DataTable dt) { using (SqlConnection conn = new SqlConnection()) { using (SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction)) { try { sqlbulkcopy.DestinationTableName = TableName; for (int i = 0; i < dt.Columns.Count; i++) { sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); } sqlbulkcopy.WriteToServer(dt); } catch (System.Exception ex) { throw ex; } } } } } public static class a { public static DataTable SqlQueryForDataTatable(this Database db, string sql, SqlParameter[] parameters) { SqlConnection conn = new System.Data.SqlClient.SqlConnection(); conn.ConnectionString = db.Connection.ConnectionString; if (conn.State != ConnectionState.Open) { conn.Open(); } SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; cmd.CommandText = sql; if (parameters!=null&&parameters.Length > 0) { foreach (var item in parameters) { cmd.Parameters.Add(item); } } SqlDataAdapter adapter = new SqlDataAdapter(cmd); DataTable table = new DataTable(); adapter.Fill(table); return table; } } }

      

  • 相关阅读:
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    常用Flex 布局scss
    设置npm registry的几种方法
    JavaScript计算平方数的三种方法
    NPM 使用介绍
    x 的 y次幂科学计数法
    Docker 容器使用
    使用dos的tree命令输出文件夹树
    赣州(虔州)历史文化
    vue通过$ref获取不到元素样式?
  • 原文地址:https://www.cnblogs.com/zengpeng/p/5806778.html
Copyright © 2020-2023  润新知