From 98f16dbd82e7fdf89cf4f3944ee055739a56079e Mon Sep 17 00:00:00 2001 From: Zhuhai Date: Fri, 19 Apr 2024 15:56:34 +0800 Subject: [PATCH 1/3] add table param --- src/Dapper.Bulk/DapperBulk.cs | 63 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/Dapper.Bulk/DapperBulk.cs b/src/Dapper.Bulk/DapperBulk.cs index 956060c..f585e13 100644 --- a/src/Dapper.Bulk/DapperBulk.cs +++ b/src/Dapper.Bulk/DapperBulk.cs @@ -22,14 +22,15 @@ public static class DapperBulk /// The type being inserted. /// Open SqlConnection /// Entities to insert + /// TableName /// The transaction to run under, null (the default) if none /// Number of bulk items inserted together, 0 (the default) if all /// Number of seconds before bulk command execution timeout, 30 (the default) /// Usage of db generated ids. By default DB generated IDs are used (identityInsert=false) - public static void BulkInsert(this SqlConnection connection, IEnumerable data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) + public static void BulkInsert(this SqlConnection connection, IEnumerable data, string tableName, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) { var type = typeof(T); - BulkInsert(connection,type,data.Cast(),transaction,batchSize,bulkCopyTimeout,identityInsert); + BulkInsert(connection, type, data.Cast(), tableName, transaction, batchSize, bulkCopyTimeout, identityInsert); } /// @@ -39,25 +40,26 @@ public static void BulkInsert(this SqlConnection connection, IEnumerable d /// Open SqlConnection /// The type being inserted. /// Entities to insert + /// TableName /// The transaction to run under, null (the default) if none /// Number of bulk items inserted together, 0 (the default) if all /// Number of seconds before bulk command execution timeout, 30 (the default) /// Usage of db generated ids. By default DB generated IDs are used (identityInsert=false) - public static void BulkInsert(this SqlConnection connection, Type type, IEnumerable data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) - { - var tableName = TableMapper.GetTableName(type); + public static void BulkInsert(this SqlConnection connection, Type type, IEnumerable data, string tableName, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) + { + tableName = string.IsNullOrWhiteSpace(tableName) ? TableMapper.GetTableName(type) : tableName; var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); var columns = PropertiesCache.GetColumnNamesCache(type); var insertProperties = allProperties.Except(computedProperties).ToList(); - + if (!identityInsert) insertProperties = insertProperties.Except(keyProperties).ToList(); var (identityInsertOn, identityInsertOff, sqlBulkCopyOptions) = GetIdentityInsertOptions(identityInsert, tableName); - + var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); @@ -85,15 +87,16 @@ public static void BulkInsert(this SqlConnection connection, Type type, IEnumera /// The element type of the array /// Open SqlConnection /// Entities to insert + /// TableName /// The transaction to run under, null (the default) if none /// Number of bulk items inserted together, 0 (the default) if all /// Number of seconds before bulk command execution timeout, 30 (the default) /// Usage of db generated ids. By default DB generated IDs are used (identityInsert=false) /// Inserted entities - public static IEnumerable BulkInsertAndSelect(this SqlConnection connection, IEnumerable data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) + public static IEnumerable BulkInsertAndSelect(this SqlConnection connection, IEnumerable data, string tableName, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) { var type = typeof(T); - var tableName = TableMapper.GetTableName(type); + tableName = string.IsNullOrWhiteSpace(tableName) ? TableMapper.GetTableName(type) : tableName; var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); @@ -102,18 +105,18 @@ public static IEnumerable BulkInsertAndSelect(this SqlConnection connectio if (keyProperties.Count == 0) { var dataList = data.ToList(); - connection.BulkInsert(dataList, transaction, batchSize, bulkCopyTimeout); + connection.BulkInsert(dataList, tableName, transaction, batchSize, bulkCopyTimeout); return dataList; } var insertProperties = allProperties.Except(computedProperties).ToList(); - + if (!identityInsert) insertProperties = insertProperties.Except(keyProperties).ToList(); var (identityInsertOn, identityInsertOff, sqlBulkCopyOptions) = GetIdentityInsertOptions(identityInsert, tableName); - - var keyPropertiesString = GetColumnsStringSqlServer(keyProperties,columns); + + var keyPropertiesString = GetColumnsStringSqlServer(keyProperties, columns); var keyPropertiesInsertedString = GetColumnsStringSqlServer(keyProperties, columns, "inserted."); var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var allPropertiesString = GetColumnsStringSqlServer(allProperties, columns, "target."); @@ -133,7 +136,7 @@ public static IEnumerable BulkInsertAndSelect(this SqlConnection connectio var table = string.Join(", ", keyProperties.Select(k => $"[{(columns.ContainsKey(k.Name) ? columns[k.Name] : k.Name)}] bigint")); var joinOn = string.Join(" AND ", keyProperties.Select(k => $"target.[{(columns.ContainsKey(k.Name) ? columns[k.Name] : k.Name)}] = ins.[{(columns.ContainsKey(k.Name) ? columns[k.Name] : k.Name)}]")); - + return connection.Query($@" {identityInsertOn} DECLARE {tempInsertedWithIdentity} TABLE ({table}) @@ -154,27 +157,28 @@ public static IEnumerable BulkInsertAndSelect(this SqlConnection connectio /// The type being inserted. /// Open SqlConnection /// Entities to insert + /// TableName /// The transaction to run under, null (the default) if none /// Number of bulk items inserted together, 0 (the default) if all /// Number of seconds before bulk command execution timeout, 30 (the default) /// Usage of db generated ids. By default DB generated IDs are used (identityInsert=false) - public static async Task BulkInsertAsync(this SqlConnection connection, IEnumerable data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) + public static async Task BulkInsertAsync(this SqlConnection connection, IEnumerable data, string tableName, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) { var type = typeof(T); - var tableName = TableMapper.GetTableName(type); + tableName = string.IsNullOrWhiteSpace(tableName) ? TableMapper.GetTableName(type) : tableName; var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); var columns = PropertiesCache.GetColumnNamesCache(type); var insertProperties = allProperties.Except(computedProperties).ToList(); - + if (!identityInsert) insertProperties = insertProperties.Except(keyProperties).ToList(); var (identityInsertOn, identityInsertOff, sqlBulkCopyOptions) = GetIdentityInsertOptions(identityInsert, tableName); - - var insertPropertiesString = GetColumnsStringSqlServer(insertProperties,columns); + + var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); await connection.ExecuteAsync($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); @@ -202,15 +206,16 @@ await connection.ExecuteAsync($@" /// The type being inserted. /// Open SqlConnection /// Entities to insert + /// TableName /// The transaction to run under, null (the default) if none /// Number of bulk items inserted together, 0 (the default) if all /// Number of seconds before bulk command execution timeout, 30 (the default) /// Usage of db generated ids. By default DB generated IDs are used (identityInsert=false) /// Inserted entities - public static async Task> BulkInsertAndSelectAsync(this SqlConnection connection, IEnumerable data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) + public static async Task> BulkInsertAndSelectAsync(this SqlConnection connection, IEnumerable data, string tableName, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false) { var type = typeof(T); - var tableName = TableMapper.GetTableName(type); + tableName = string.IsNullOrWhiteSpace(tableName) ? TableMapper.GetTableName(type) : tableName; var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); @@ -219,20 +224,20 @@ public static async Task> BulkInsertAndSelectAsync(this SqlCon if (keyProperties.Count == 0) { var dataList = data.ToList(); - await connection.BulkInsertAsync(dataList, transaction, batchSize, bulkCopyTimeout); + await connection.BulkInsertAsync(dataList, tableName, transaction, batchSize, bulkCopyTimeout); return dataList; } var insertProperties = allProperties.Except(computedProperties).ToList(); - + if (!identityInsert) insertProperties = insertProperties.Except(keyProperties).ToList(); var (identityInsertOn, identityInsertOff, sqlBulkCopyOptions) = GetIdentityInsertOptions(identityInsert, tableName); - - var keyPropertiesString = GetColumnsStringSqlServer(keyProperties,columns); - var keyPropertiesInsertedString = GetColumnsStringSqlServer(keyProperties,columns, "inserted."); - var insertPropertiesString = GetColumnsStringSqlServer(insertProperties,columns); + + var keyPropertiesString = GetColumnsStringSqlServer(keyProperties, columns); + var keyPropertiesInsertedString = GetColumnsStringSqlServer(keyProperties, columns, "inserted."); + var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var allPropertiesString = GetColumnsStringSqlServer(allProperties, columns, "target."); var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); @@ -240,7 +245,7 @@ public static async Task> BulkInsertAndSelectAsync(this SqlCon await connection.ExecuteAsync($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); - using (var bulkCopy = new SqlBulkCopy(connection,sqlBulkCopyOptions, transaction)) + using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction)) { bulkCopy.BulkCopyTimeout = bulkCopyTimeout; bulkCopy.BatchSize = batchSize; @@ -272,7 +277,7 @@ private static string GetColumnsStringSqlServer(IEnumerable proper return string.Join(", ", properties.Select(property => $"{tablePrefix}[{columnNames[property.Name]}] ")); } - + private static DataTable ToDataTable(IEnumerable data, IList properties) { var typeCasts = new Type[properties.Count]; From 841c566614024eb67f2cda2a9d1463c806215b92 Mon Sep 17 00:00:00 2001 From: Zhuhai Date: Fri, 19 Apr 2024 16:44:38 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Dapper.Bulk/DapperBulk.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Dapper.Bulk/DapperBulk.cs b/src/Dapper.Bulk/DapperBulk.cs index f585e13..9d70c24 100644 --- a/src/Dapper.Bulk/DapperBulk.cs +++ b/src/Dapper.Bulk/DapperBulk.cs @@ -344,9 +344,9 @@ internal static string FormatTableName(string table) } private static (string identityInsertOn, string identityInsertOff, SqlBulkCopyOptions bulkCopyOptions) - GetIdentityInsertOptions(bool identityInsert, string tableName) - => identityInsert - ? ($"SET IDENTITY_INSERT {FormatTableName(tableName)} ON", - $"SET IDENTITY_INSERT {FormatTableName(tableName)} OFF", SqlBulkCopyOptions.KeepIdentity) - : (string.Empty, string.Empty, SqlBulkCopyOptions.Default); + GetIdentityInsertOptions(bool identityInsert, string tableName)=> (string.Empty, string.Empty, SqlBulkCopyOptions.Default); + //=> identityInsert + // ? ($"SET IDENTITY_INSERT {FormatTableName(tableName)} ON", + // $"SET IDENTITY_INSERT {FormatTableName(tableName)} OFF", SqlBulkCopyOptions.KeepIdentity) + // : (string.Empty, string.Empty, SqlBulkCopyOptions.Default); } From 8c80a93406c77939c03f7cb40f7769acc0abe328 Mon Sep 17 00:00:00 2001 From: Zhuhai Date: Fri, 19 Apr 2024 16:58:28 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=9C=AA=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=97=B6=E6=89=93=E5=BC=80=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Dapper.Bulk/DapperBulk.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Dapper.Bulk/DapperBulk.cs b/src/Dapper.Bulk/DapperBulk.cs index 9d70c24..3c366dc 100644 --- a/src/Dapper.Bulk/DapperBulk.cs +++ b/src/Dapper.Bulk/DapperBulk.cs @@ -63,6 +63,11 @@ public static void BulkInsert(this SqlConnection connection, Type type, IEnumera var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + connection.Execute($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction)) @@ -124,6 +129,11 @@ public static IEnumerable BulkInsertAndSelect(this SqlConnection connectio var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); var tempInsertedWithIdentity = $"@TempInserted_{tableName}".Replace(".", string.Empty); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + connection.Execute($"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction)) @@ -181,6 +191,11 @@ public static async Task BulkInsertAsync(this SqlConnection connection, IEnum var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns); var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + await connection.ExecuteAsync($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction)) @@ -243,6 +258,11 @@ public static async Task> BulkInsertAndSelectAsync(this SqlCon var tempToBeInserted = $"#TempInsert_{tableName}".Replace(".", string.Empty); var tempInsertedWithIdentity = $"@TempInserted_{tableName}".Replace(".", string.Empty); + if (connection.State != ConnectionState.Open) + { + connection.Open(); + } + await connection.ExecuteAsync($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction); using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction))