国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#:幾種數據庫的大數據批量插入

2019-11-17 02:30:56
字體:
來源:轉載
供稿:網友
C#:幾種數據庫的大數據批量插入

在之前只知道SqlServer支持數據批量插入,殊不知道Oracle、SQLite和MySQL也是支持的,不過Oracle需要使用Orace.Dataaccess驅動,今天就貼出幾種數據庫的批量插入解決方法。

首先說一下,iprovider里有一個用于實現批量插入的插件服務接口IBatcherPRovider,此接口在前一篇文章中已經提到過了。

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

一、SqlServer數據批量插入

SqlServer的批量插入很簡單,使用SqlBulkCopy就可以,以下是該類的實現:

/// <summary>/// 為 System.Data.SqlClient 提供的用于批量操作的方法。/// </summary>public sealed class MsSqlBatcher : IBatcherProvider{/// <summary>/// 獲取或設置提供者服務的上下文。/// </summary>public ServiceContext ServiceContext { get; set; }/// <summary>/// 將 <see cref="DataTable"/> 的數據批量插入到數據庫中。/// </summary>/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>/// <param name="batchSize">每批次寫入的數據量。</param>public void Insert(DataTable dataTable, int batchSize = 10000){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);using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, 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組件來作為提供者。

/// <summary>/// Oracle.Data.Access 組件提供的用于批量操作的方法。/// </summary>public sealed class OracleAccessBatcher : IBatcherProvider{/// <summary>/// 獲取或設置提供者服務的上下文。/// </summary>public ServiceContext ServiceContext { get; set; }/// <summary>/// 將 <see cref="DataTable"/> 的數據批量插入到數據庫中。/// </summary>/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>/// <param name="batchSize">每批次寫入的數據量。</param>public void Insert(DataTable dataTable, int batchSize = 10000){Checker.ArgumentNull(dataTable, "dataTable");if (dataTable.Rows.Count == 0){return;}using (var connection = ServiceContext.Database.CreateConnection()){try{connection.TryOpen();using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand()){if (command == null){throw new BatcherException(new ArgumentException("command"));}command.Connection = connection;command.CommandText = GenerateInserSql(ServiceContext.Database, command, dataTable);command.ExecuteNonQuery();}}catch (Exception exp){throw new BatcherException(exp);}finally{connection.TryClose();}}}/// <summary>/// 生成插入數據的sql語句。/// </summary>/// <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 = new StringBuilder();var values = new StringBuilder();//將一個DataTable的數據轉換為數組的數組var data = table.ToArray();//設置ArrayBindCount屬性command.GetType().GetProperty("ArrayBindCount").SetValue(command, table.Rows.Count, null);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 == null){continue;}parameter.ParameterName = column.ColumnName;parameter.Direction = ParameterDirection.Input;parameter.DbType = column.DataType.GetDbType();parameter.Value = data[i];if (names.Length > 0){names.Append(",");values.Append(",");}names.AppendFormat("{0}", DbUtility.FormatByQuote(syntax, column.ColumnName));values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);command.Parameters.Add(parameter);}return string.Format("INSERT INTO {0}({1}) VALUES ({2})", DbUtility.FormatByQuote(syntax, table.TableName), names, values);}}

以上最重要的一步,就是將DataTable轉為數組的數組表示,即object[][],前數組的上標是列的個數,后數組是行的個數,因此循環Columns將后數組作為Parameter的值,也就是說,參數的值是一個數組。而insert語句與一般的插入語句沒有什么不一樣。

三、SQLite數據批量插入

SQLite的批量插入只需開啟事務就可以了,這個具體的原理不得而知。

public sealed class SQLiteBatcher : IBatcherProvider{/// <summary>/// 獲取或設置提供者服務的上下文。/// </summary>public ServiceContext ServiceContext { get; set; }/// <summary>/// 將 <see cref="DataTable"/> 的數據批量插入到數據庫中。/// </summary>/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>/// <param name="batchSize">每批次寫入的數據量。</param>public void Insert(DataTable dataTable, int batchSize = 10000){Checker.ArgumentNull(dataTable, "dataTable");if (dataTable.Rows.Count == 0){return;}using (var connection = ServiceContext.Database.CreateConnection()){DbTransaction transcation = null;try{connection.TryOpen();transcation = connection.BeginTransaction();using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand()){if (command == null){throw new BatcherException(new ArgumentException("command"));}command.Connection = connection;command.CommandText = GenerateInserSql(ServiceContext.Database, dataTable);if (command.CommandText == string.Empty){return;}var flag = new AssertFlag();dataTable.EachRow(row =>{var first = flag.AssertTrue();ProcessCommandParameters(dataTable, command, row, first);command.ExecuteNonQuery();});}transcation.Commit();}catch (Exception exp){if (transcation != null){transcation.Rollback();}throw new BatcherException(exp);}finally{connection.TryClose();}}}private void ProcessCommandParameters(DataTable dataTable, DbCommand command, DataRow row, bool first){for (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];}}/// <summary>/// 生成插入數據的sql語句。/// </summary>/// <param name="database"></param>/// <param name="table"></param>/// <returns></returns>private string GenerateInserSql(IDatabase database, DataTable table){var syntax = database.Provider.GetService<ISyntaxProvider>();var names = new StringBuilder();var values = new StringBuilder();var flag = new AssertFlag();table.EachColumn(column =>{if (!flag.AssertTrue()){names.Append(",");values.Append(",");}names.Append(DbUtility.FormatByQuote(syntax, column.ColumnName));values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);});return string.Format("INSERT INTO {0}({1}) VALUES ({2})", DbUtility.FormatByQuote(syntax, table.TableName), names, values);}}

四、MySql數據批量插入

/// <summary>/// 為 MySql.Data 組件提供的用于批量操作的方法。/// </summary>public sealed class MySqlBatcher : IBatcherProvider{/// <summary>/// 獲取或設置提供者服務的上下文。/// </summary>public ServiceContext ServiceContext { get; set; }/// <summary>/// 將 <see cref="DataTable"/> 的數據批量插入到數據庫中。/// </summary>/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>/// <param name="batchSize">每批次寫入的數據量。</param>public void Inse

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安乡县| 卓尼县| 聊城市| 大连市| 乌兰浩特市| 祥云县| 靖远县| 兴海县| 安阳市| 双峰县| 鹤壁市| 夏河县| 麻城市| 宁德市| 宁国市| 景德镇市| 长宁县| 鄄城县| 台南县| 日土县| 汉寿县| 乐都县| 灵石县| 定陶县| 永泰县| 英超| 江源县| 安福县| 浦江县| 清水河县| 湟中县| 始兴县| 九江县| 常熟市| 富锦市| 三亚市| 佛冈县| 二手房| 晋宁县| 中卫市| 墨竹工卡县|