Share via

Performance Issue in SqlBulkCopy while updating Multiple Table

Indudhar Gowda 426 Reputation points
2021-11-18T05:40:38.213+00:00

Hello Team,

Performance Issue in SqlBulkCopy c#

await BulkHelper.PerAsync(Datas, connection, transaction);
await BulkHelper.PerAsync(Limits, connection, transaction);          
await BulkHelper.PerAsync(variables, connection, transaction);           
await BulkHelper.PerAsync(rValues, connection, transaction);           
await BulkHelper.PerAsync(traResults, connection, transaction);           
await BulkHelper.PerAsync(resLimits, connection, transaction);

"Datas" table is chained to "Limits" table and so on : Based on "Datas" table "Limits" Table will be updated.

 public static async Task PerAsync<T>(IEnumerable<T> items, SqlConnection destinationConnection, IDbTransaction transaction)
        {
            ReflectionHelper.PrepareForType<T>();

            string tableName = ReflectionHelper.GetTableNameForType<T>();

            string tempTableName = $"dbo.#{tableName}";

            DataTable dt = DataTableHelper.CreateDataTable<T>();

            ConvertToDatatable(items, dt);

            if (destinationConnection.State == ConnectionState.Closed)
            {
                destinationConnection.Open();
            }

            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection, SqlBulkCopyOptions.Default, transaction as SqlTransaction))
            {
                var command = new SqlCommand
                {
                    Connection = destinationConnection,
                    CommandType = CommandType.Text,
                    CommandText = $"SELECT TOP(0) * INTO {tempTableName} FROM {tableName};",
                    Transaction = transaction as SqlTransaction
                };

                await command.ExecuteNonQueryAsync();

                bulkCopy.DestinationTableName = tempTableName;

                foreach (DataColumn col in dt.Columns)
                {
                    bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(col.ColumnName, col.ColumnName));
                }

                await bulkCopy.WriteToServerAsync(dt);

                var updateQuery = DataTableHelper.GetUpdateQuery(typeof(T), tempTableName, tableName);
                var insertQuery = DataTableHelper.GetInsertQuery(typeof(T), tempTableName, tableName);
                var dropQuery = $"DROP TABLE {tempTableName}";
                var updateCommand = transaction != null ? new SqlCommand(updateQuery, destinationConnection, transaction as SqlTransaction) : new SqlCommand(updateQuery, destinationConnection);
                updateCommand.CommandType = CommandType.Text;

                var insertCommand = transaction != null ? new SqlCommand(insertQuery, destinationConnection, transaction as SqlTransaction) : new SqlCommand(insertQuery, destinationConnection);
                insertCommand.CommandType = CommandType.Text;

                var dropCommand = transaction != null ? new SqlCommand(dropQuery, destinationConnection, transaction as SqlTransaction) : new SqlCommand(dropQuery, destinationConnection);
                dropCommand.CommandType = CommandType.Text;

                await insertCommand.ExecuteNonQueryAsync();
                await updateCommand.ExecuteNonQueryAsync();
                await dropCommand.ExecuteNonQueryAsync();
            }
        }

        private static void ConvertToDatatable<T>(IEnumerable<T> data, DataTable dt)
        {
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
            foreach (var item in data)
            {
                var dr = dt.NewRow();
                foreach (DataColumn dataColumn in dt.Columns)
                {
                    var colData = props[dataColumn.Caption].GetValue(item);
                    dr[dataColumn] = colData ?? DBNull.Value;
                }

                dt.Rows.Add(dr);
            }
        }
    }

Requirement : Need to better solution to update, delete, Create without Concurrency.
and Also need in Parallel Excecution.

Developer technologies | .NET | Other
Developer technologies | Transact-SQL
Developer technologies | Transact-SQL

A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.

SQL Server | Other
SQL Server | Other

Additional SQL Server features and topics not covered by specific categories

Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.


1 answer

Sort by: Most helpful
  1. Jack J Jun 25,306 Reputation points
    2021-11-19T09:55:33.55+00:00

    @Indudhar Gowda ,Based on my research, you could try to use Task.WhenAll to solve the performance issue in SqlBulkCopy.
    The link Using async/await for multiple tasks describes that it will perform your operations asynchronously in Parallel.

    Therefore, we could try the following code to solve the problem.

    await Task.WhenAll(BulkHelper.PerAsync(Datas, connection, transaction),BulkHelper.PerAsync(Limits, connection, transaction),.....);     
    

    Hope the above solution could help you.

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.