SqlBulkCopy是.NET的一个类常用于批量插入数据,这种方式比Insert方式性能要高许多。

需要注意的是,DataTable中的列需要与即将插入的表的列兼容,名称和数据库的顺序完全一致。楼主往日期类型插入空值时就遇到了一个问题,那就是不能给这一列的设置Null值,而是要通过不给其赋值的方式。DataTable的表名要与数据库的表名一致。

插入数据时,有个SqlBulkCopyOptions可以设置,它可以更改SqlBulkCopy的行为,它是枚举类型,它的值如下所示:

字段

解释

Default

使用所有选项的默认值

KeepIdentity

保留源标识值。 未指定标识值时,该值由目标指派。这个很好理解,比如将A表中的数据批量导入到B表中,B表的标识列id依旧套用A表的id时就需要这个。

CheckConstraints

插入数据时检查约束。 默认情况下,不检查约束。当数据是从外部导入时就需要检查约束

TableLock

获取批量复制操作持续时间的批量更新锁定。 如果未指定,则使用行锁定。

KeepNulls

在目标表中保留 null 值,而不考虑默认值的设置。 如果未指定,由默认值替换 null 值(适用时)。假如A表中的Salary为Null,B表中的Salary的默认值为0,那么A表导入B表后Salary的值会变成0。

FireTriggers

如果指定,则使服务器激发插入触发器,从而使行插入数据库。

UseInternalTransaction

如果指定,批量复制操作的每一批都将在事务内发生。如果指示该选项,并且还向构造函数提供 SqlTransaction 对象,则发生 ArgumentException

示例代码如下:

/// <summary>
    /// 批量导入
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static bool ExecuteNonQuery(DataTable dt)
    {
        SqlConnection connection = null;
        SqlTransaction tran = null;
        SqlBulkCopy sqlbulkcopy = null;
        try
        {
            connection = new SqlConnection(connStr);
            connection.Open();
            tran = connection.BeginTransaction();//开启事务
            sqlbulkcopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.CheckConstraints, tran);
            sqlbulkcopy.BulkCopyTimeout = 100;  //超时之前操作完成所允许的秒数
            sqlbulkcopy.BatchSize = dt.Rows.Count;  //每一批次中的行数
            sqlbulkcopy.DestinationTableName = dt.TableName;  //服务器上目标表的名称
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                sqlbulkcopy.ColumnMappings.Add(i, i);  //映射定义数据源中的列和目标表中的列之间的关系
            }
            sqlbulkcopy.WriteToServer(dt);  // 将DataTable数据上传到数据表中
            tran.Commit();
            return true;
        }
        catch (Exception e)
        {
            if (connection != null)
            {
                connection.Close();
            }
            tran.Rollback();
            return false;
        }
        finally
        {
            if (connection != null)
            {
                connection.Close();
            }
            if(sqlbulkcopy != null)
            {
                sqlbulkcopy.Close();
            }
        }
    }