Beispiel #1
0
 /// <summary>
 /// Bulk insert a list of data entity objects into the database.
 /// </summary>
 /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
 /// <param name="connection">The connection object to be used.</param>
 /// <param name="entities">The list of the data entities to be bulk-inserted.</param>
 /// <param name="mappings">The list of the columns to be used for mappings. If this parameter is not set, then all columns will be used for mapping.</param>
 /// <param name="options">The bulk-copy options to be used.</param>
 /// <param name="bulkCopyTimeout">The timeout in seconds to be used.</param>
 /// <param name="batchSize">The size per batch to be used.</param>
 /// <param name="transaction">The transaction to be used.</param>
 /// <returns>The number of rows affected by the execution.</returns>
 public static int BulkInsert <TEntity>(this SqlConnection connection,
                                        IEnumerable <TEntity> entities,
                                        IEnumerable <BulkInsertMapItem> mappings = null,
                                        SqlBulkCopyOptions options = SqlBulkCopyOptions.Default,
                                        int?bulkCopyTimeout        = null,
                                        int?batchSize = null,
                                        SqlTransaction transaction = null)
     where TEntity : class
 {
     using (var reader = new DataEntityDataReader <TEntity>(entities))
     {
         return(BulkInsertInternal(connection: connection,
                                   tableName: ClassMappedNameCache.Get <TEntity>(),
                                   reader: reader,
                                   mappings: mappings,
                                   options: options,
                                   bulkCopyTimeout: bulkCopyTimeout,
                                   batchSize: batchSize,
                                   transaction: transaction));
     }
 }
Beispiel #2
0
 /// <summary>
 /// Bulk insert a list of data entity objects into the database in an asynchronous way.
 /// </summary>
 /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
 /// <param name="tableName">The target table for bulk-insert operation.</param>
 /// <param name="connection">The connection object to be used.</param>
 /// <param name="entities">The list of the data entities to be bulk-inserted.</param>
 /// <param name="mappings">The list of the columns to be used for mappings. If this parameter is not set, then all columns will be used for mapping.</param>
 /// <param name="options">The bulk-copy options to be used.</param>
 /// <param name="bulkCopyTimeout">The timeout in seconds to be used.</param>
 /// <param name="batchSize">The size per batch to be used.</param>
 /// <param name="transaction">The transaction to be used.</param>
 /// <returns>The number of rows affected by the execution.</returns>
 public static async Task <int> BulkInsertAsync <TEntity>(this SqlConnection connection,
                                                          string tableName,
                                                          IEnumerable <TEntity> entities,
                                                          IEnumerable <BulkInsertMapItem> mappings = null,
                                                          SqlBulkCopyOptions options = SqlBulkCopyOptions.Default,
                                                          int?bulkCopyTimeout        = null,
                                                          int?batchSize = null,
                                                          SqlTransaction transaction = null)
     where TEntity : class
 {
     using (var reader = new DataEntityDataReader <TEntity>(entities))
     {
         return(await BulkInsertAsyncInternal(connection : connection,
                                              tableName : tableName,
                                              reader : reader,
                                              mappings : mappings,
                                              options : options,
                                              bulkCopyTimeout : bulkCopyTimeout,
                                              batchSize : batchSize,
                                              transaction : transaction));
     }
 }
Beispiel #3
0
        /// <summary>
        /// Bulk insert a list of data entity objects into the database in an asynchronous way.
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
        /// <param name="tableName">The target table for bulk-insert operation.</param>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="entities">The list of the data entities to be bulk-inserted.</param>
        /// <param name="mappings">The list of the columns to be used for mappings. If this parameter is not set, then all columns will be used for mapping.</param>
        /// <param name="options">The bulk-copy options to be used.</param>
        /// <param name="bulkCopyTimeout">The timeout in seconds to be used.</param>
        /// <param name="batchSize">The size per batch to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <returns>The number of rows affected by the execution.</returns>
        public static async Task <int> BulkInsertAsync <TEntity>(this IDbConnection connection,
                                                                 string tableName,
                                                                 IEnumerable <TEntity> entities,
                                                                 IEnumerable <BulkInsertMapItem> mappings = null,
                                                                 SqlBulkCopyOptions options = SqlBulkCopyOptions.Default,
                                                                 int?bulkCopyTimeout        = null,
                                                                 int?batchSize = null,
                                                                 IDbTransaction transaction = null,
                                                                 ITrace trace = null)
            where TEntity : class
        {
            // Validate
            InvokeValidatorValidateBulkInsertAsync(connection);

            // Get the provider
            var provider = connection.GetDbOperation();

            // Before Execution
            if (trace != null)
            {
                var cancellableTraceLog = new CancellableTraceLog("BulkInsert.Before", entities, null);
                trace.BeforeBulkInsert(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException("BulkInsert.Cancelled");
                    }
                    return(0);
                }
                entities = (IEnumerable <TEntity>)cancellableTraceLog.Parameter ?? entities;
            }

            // Variables for the operation
            var result = 0;

            // Before Execution Time
            var beforeExecutionTime = DateTime.UtcNow;

            // Actual execution
            using (var reader = new DataEntityDataReader <TEntity>(entities))
            {
                result = await provider.BulkInsertAsync(connection : connection,
                                                        tableName : tableName,
                                                        reader : reader,
                                                        mappings : mappings,
                                                        options : options,
                                                        bulkCopyTimeout : bulkCopyTimeout,
                                                        batchSize : batchSize,
                                                        transaction : transaction);
            }

            // After Execution
            if (trace != null)
            {
                trace.AfterBulkInsert(new TraceLog("BulkInsert.After", entities, result,
                                                   DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Return the result
            return(result);
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        /// <param name="mappings"></param>
        /// <param name="options"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="hasOrderingColumn"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int WriteToServerInternal <TEntity>(SqlConnection connection,
                                                           string tableName,
                                                           IEnumerable <TEntity> entities,
                                                           IEnumerable <BulkInsertMapItem> mappings = null,
                                                           SqlBulkCopyOptions options = default,
                                                           int?bulkCopyTimeout        = null,
                                                           int?batchSize              = null,
                                                           bool hasOrderingColumn     = false,
                                                           SqlTransaction transaction = null)
            where TEntity : class
        {
            // Throw an error if there are no mappings
            if (mappings?.Any() != true)
            {
                throw new MissingMappingException("There are no mapping(s) found for this operation.");
            }

            // Variables needed
            int result;

            // Actual Execution
            using (var sqlBulkCopy = (SqlBulkCopy)Activator.CreateInstance(typeof(SqlBulkCopy), connection, options, transaction))
            {
                // Set the destinationtable
                Compiler.SetProperty(sqlBulkCopy, "DestinationTableName", tableName);

                // Set the timeout
                if (bulkCopyTimeout.HasValue)
                {
                    Compiler.SetProperty(sqlBulkCopy, "BulkCopyTimeout", bulkCopyTimeout.Value);
                }

                // Set the batch size
                if (batchSize.HasValue)
                {
                    Compiler.SetProperty(sqlBulkCopy, "BatchSize", batchSize.Value);
                }

                // Add the order column
                if (hasOrderingColumn)
                {
                    mappings = AddOrderColumnMapping(mappings);
                }

                // Add the mappings
                AddMappings(sqlBulkCopy, mappings);

                // Open the connection and do the operation
                connection.EnsureOpen();
                using (var reader = new DataEntityDataReader <TEntity>(tableName, entities, connection, transaction, hasOrderingColumn))
                {
                    var writeToServerMethod = Compiler.GetParameterizedVoidMethodFunc <SqlBulkCopy>("WriteToServer", new[] { typeof(DbDataReader) });
                    writeToServerMethod(sqlBulkCopy, new[] { reader });
                    result = reader.RecordsAffected;
                }

                // Ensure the result
                if (result <= 0)
                {
                    // Set the return value
                    var rowsCopiedFieldOrProperty = Compiler.GetFieldGetterFunc <SqlBulkCopy, int>("_rowsCopied") ??
                                                    Compiler.GetPropertyGetterFunc <SqlBulkCopy, int>("RowsCopied");
                    result = (int)rowsCopiedFieldOrProperty?.Invoke(sqlBulkCopy);
                }
            }

            // Return the result
            return(result);
        }
Beispiel #5
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TSqlBulkCopy"></typeparam>
        /// <typeparam name="TSqlBulkCopyOptions"></typeparam>
        /// <typeparam name="TSqlBulkCopyColumnMappingCollection"></typeparam>
        /// <typeparam name="TSqlBulkCopyColumnMapping"></typeparam>
        /// <typeparam name="TSqlTransaction"></typeparam>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        /// <param name="mappings"></param>
        /// <param name="options"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="hasOrderingColumn"></param>
        /// <param name="transaction"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private static async Task <int> WriteToServerAsyncInternal <TEntity, TSqlBulkCopy, TSqlBulkCopyOptions, TSqlBulkCopyColumnMappingCollection,
                                                                    TSqlBulkCopyColumnMapping, TSqlTransaction>(DbConnection connection,
                                                                                                                string tableName,
                                                                                                                IEnumerable <TEntity> entities,
                                                                                                                IEnumerable <BulkInsertMapItem> mappings = null,
                                                                                                                TSqlBulkCopyOptions options = default,
                                                                                                                int?bulkCopyTimeout         = null,
                                                                                                                int?batchSize                       = null,
                                                                                                                bool hasOrderingColumn              = false,
                                                                                                                TSqlTransaction transaction         = null,
                                                                                                                CancellationToken cancellationToken = default)
            where TEntity : class
            where TSqlBulkCopy : class, IDisposable
            where TSqlBulkCopyOptions : Enum
            where TSqlBulkCopyColumnMappingCollection : class
            where TSqlBulkCopyColumnMapping : class
            where TSqlTransaction : DbTransaction
        {
            // Throw an error if there are no mappings
            if (mappings?.Any() != true)
            {
                throw new MissingMappingException("There are no mapping(s) found for this operation.");
            }

            // Variables needed
            var result       = default(int);
            var entityType   = entities?.FirstOrDefault()?.GetType() ?? typeof(TEntity);
            var entityFields = entityType.IsDictionaryStringObject() ?
                               GetDictionaryStringObjectFields(entities?.FirstOrDefault() as IDictionary <string, object>) :
                               FieldCache.Get(entityType);

            // Actual Execution
            using (var sqlBulkCopy = (TSqlBulkCopy)Activator.CreateInstance(typeof(TSqlBulkCopy), connection, options, transaction))
            {
                // Set the destinationtable
                Compiler.SetProperty <TSqlBulkCopy>(sqlBulkCopy, "DestinationTableName", tableName);

                // Set the timeout
                if (bulkCopyTimeout.HasValue)
                {
                    Compiler.SetProperty <TSqlBulkCopy>(sqlBulkCopy, "BulkCopyTimeout", bulkCopyTimeout.Value);
                }

                // Set the batch size
                if (batchSize.HasValue)
                {
                    Compiler.SetProperty <TSqlBulkCopy>(sqlBulkCopy, "BatchSize", batchSize.Value);
                }

                // Add the order column
                if (hasOrderingColumn)
                {
                    mappings = AddOrderColumnMapping(mappings);
                }

                // Add the mappings
                AddMappings <TSqlBulkCopy, TSqlBulkCopyColumnMappingCollection, TSqlBulkCopyColumnMapping>(sqlBulkCopy, mappings);

                // Open the connection and do the operation
                await connection.EnsureOpenAsync();

                using (var reader = new DataEntityDataReader <TEntity>(tableName, entities, connection, transaction, hasOrderingColumn))
                {
                    var writeToServerMethod = Compiler.GetParameterizedMethodFunc <TSqlBulkCopy, Task>("WriteToServerAsync", new[] { typeof(DbDataReader), typeof(CancellationToken) });
                    await writeToServerMethod(sqlBulkCopy, new object[] { reader, cancellationToken });

                    result = reader.RecordsAffected;
                }

                // Ensure the result
                if (result <= 0)
                {
                    // Set the return value
                    var rowsCopiedFieldOrProperty = Compiler.GetFieldGetterFunc <TSqlBulkCopy, int>("_rowsCopied") ??
                                                    Compiler.GetPropertyGetterFunc <TSqlBulkCopy, int>("RowsCopied");
                    result = (int)rowsCopiedFieldOrProperty?.Invoke(sqlBulkCopy);
                }
            }

            // Return the result
            return(result);
        }