加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

数据批量插入

发布时间:2020-12-12 14:28:27 所属栏目:MsSql教程 来源:网络整理
导读:在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。? IProvider里有一个用于实现批量插入的插件服务接口IBatcherProvider。 /// summary /// 提

在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。? IProvider里有一个用于实现批量插入的插件服务接口IBatcherProvider。

复制代码

    /// <summary>
    /// 提供数据批量处理的方法。
    </summary>
    public interface IBatcherProvider : IProviderService
    {
        <summary>
        <see cref="DataTable"/> 的数据批量插入到数据库中。
        </summary>
        <param name="dataTable">要批量插入的 </param>
        <param name="batchSize">每批次写入的数据量。</param>
        void Insert(DataTable dataTable,int batchSize = 10000);
    }

复制代码

一、SqlServer数据批量插入

??? SqlServer的批量插入很简单,使用SqlBulkCopy就可以,以下是该类的实现:

为 System.Data.SqlClient 提供的用于批量操作的方法。 sealed class MsSqlBatcher : IBatcherProvider { 获取或设置提供者服务的上下文。 </summary> public ServiceContext ServiceContext { get; set; } ) { Checker.ArgumentNull(dataTable,"dataTable"); if (dataTable.Rows.Count == 0) { return; } using (var connection = (SqlConnection)ServiceContext.Database.CreateConnection()) { try { connection.TryOpen(); //给表名加上前后导符 var tableName = DbUtility.FormatByQuote(ServiceContext.Database.Provider.GetService<ISyntaxProvider>(),dataTable.TableName); var bulk = new SqlBulkCopy(connection,SqlBulkCopyOptions.KeepIdentity,255)">null) { DestinationTableName = tableName,BatchSize = batchSize }) { 循环所有列,为bulk添加映射 dataTable.EachColumn(c => bulk.ColumnMappings.Add(c.ColumnName,c.ColumnName),c => !c.AutoIncrement); bulk.WriteToServer(dataTable); bulk.Close(); } } catch (Exception exp) { throw new BatcherException(exp); } finally { connection.TryClose(); } } } } SqlBulkCopy的ColumnMappings中列的名称受大小写敏感限制,因此在构造DataTable的时候应请注意列名要与表一致。

???? 以上没有使用事务,使用事务在性能上会有一定的影响,如果要使用事务,可以设置SqlBulkCopyOptions.UseInternalTransaction。

二、Oracle数据批量插入

???? System.Data.OracleClient不支持批量插入,因此只能使用Oracle.DataAccess组件来作为提供者。

Oracle.Data.Access 组件提供的用于批量操作的方法。
OracleAccessBatcher : IBatcherProvider { ServiceContext.Database.CreateConnection()) { var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand()) { if (command == ) { new BatcherException(new ArgumentException(command)); } command.Connection = connection; command.CommandText = GenerateInserSql(ServiceContext.Database,command,dataTable); command.ExecuteNonQuery(); } } { connection.TryClose(); } } } 生成插入数据的sql语句。 <param name="database"></param> <param name="command"></param> <param name="table"></param> <returns></returns> private string GenerateInserSql(IDatabase database,DbCommand command,DataTable table) { var names = StringBuilder(); var values = 将一个DataTable的数据转换为数组的数组 var data = table.ToArray(); 设置ArrayBindCount属性 command.GetType().GetProperty(ArrayBindCount").SetValue(command,table.Rows.Count,0)">); var syntax = database.Provider.GetService<ISyntaxProvider>(); for (var i = 0; i < table.Columns.Count; i++var column = table.Columns[i]; var parameter = database.Provider.DbProviderFactory.CreateParameter(); if (parameter == ) { continue; } parameter.ParameterName = column.ColumnName; parameter.Direction = ParameterDirection.Input; parameter.DbType = column.DataType.GetDbType(); parameter.Value = data[i]; if (names.Length > ) { names.Append(,0)">); values.Append(); } names.AppendFormat({0}{0}{1}return string.Format(INSERT INTO {0}({1}) VALUES ({2}) 以上最重要的一步,就是将DataTable转为数组的数组表示,即object[][],前数组的上标是列的个数,后数组是行的个数,因此循环 Columns将后数组作为Parameter的值,也就是说,参数的值是一个数组。而insert语句与一般的插入语句没有什么不一样。

?

???? 三、SQLite数据批量插入

???? SQLite的批量插入只需开启事务就可以了,这个具体的原理不得而知。

复制代码

     SQLiteBatcher : IBatcherProvider
    {
         ServiceContext.Database.CreateConnection())
            {
                DbTransaction transcation = ;
                
                {
                    connection.TryOpen();
                    transcation = connection.BeginTransaction();
                     connection;

                        command.CommandText =if (command.CommandText == .Empty)
                        {
                            ;
                        }

                        var flag =  AssertFlag();
                        dataTable.EachRow(row =>
                            {
                                var first = flag.AssertTrue();
                                ProcessCommandParameters(dataTable,row,first);
                                command.ExecuteNonQuery();
                            });
                    }
                    transcation.Commit();
                }
                if (transcation != )
                    {
                        transcation.Rollback();
                    }
                    
                {
                    connection.TryClose();
                }
            }
        }

        void ProcessCommandParameters(DataTable dataTable,DataRow row,255)">bool first)
        {
            var c = 0; c < dataTable.Columns.Count; c++)
            {
                DbParameter parameter;
                首次创建参数,是为了使用缓存
                if (first)
                {
                    parameter = ServiceContext.Database.Provider.DbProviderFactory.CreateParameter();
                    parameter.ParameterName = dataTable.Columns[c].ColumnName;
                    command.Parameters.Add(parameter);
                }
                else
                {
                    parameter = command.Parameters[c];
                }
                parameter.Value = row[c];
            }
        }

         AssertFlag();
            table.EachColumn(column =>
                {
                    if (!flag.AssertTrue())
                    {
                        names.Append();
                        values.Append();
                    }
                    names.Append(DbUtility.FormatByQuote(syntax,column.ColumnName));
                    values.AppendFormat(

复制代码

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读