Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new instance of <see cref="DataEntityDataReader{TEntity}"/> object.
        /// </summary>
        /// <param name="entities">The list of the data entity object to be used for manipulation.</param>
        /// <param name="connection">The actual <see cref="IDbConnection"/> object used.</param>
        /// <param name="transaction">The transaction object that is currently in used.</param>
        public DataEntityDataReader(IEnumerable <TEntity> entities, IDbConnection connection, IDbTransaction transaction)
        {
            if (entities == null)
            {
                throw new NullReferenceException("The entities could not be null.");
            }

            // Fields
            m_isClosed        = false;
            m_isDisposed      = false;
            m_position        = -1;
            m_recordsAffected = -1;

            // Properties
            if (connection != null)
            {
                var fields = DbFieldCache.Get(connection, ClassMappedNameCache.Get <TEntity>(), transaction);
                if (fields?.Any() == true)
                {
                    Properties = PropertyCache.Get <TEntity>()
                                 .Where(p => fields.FirstOrDefault(f => string.Equals(f.UnquotedName, p.GetUnquotedMappedName(), StringComparison.OrdinalIgnoreCase)) != null)
                                 .AsList();
                }
            }
            if (Properties == null)
            {
                Properties = PropertyCache.Get <TEntity>().AsList();
            }
            Enumerator = entities.GetEnumerator();
            Entities   = entities;
            FieldCount = Properties.Count;
        }
Ejemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TPrimaryKey"></typeparam>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="primaryKeys"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="pseudoTableType"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int BinaryBulkDeleteByKeyBase <TPrimaryKey>(this NpgsqlConnection connection,
                                                                   string tableName,
                                                                   IEnumerable <TPrimaryKey> primaryKeys,
                                                                   int?bulkCopyTimeout = null,
                                                                   int?batchSize       = null,
                                                                   BulkImportPseudoTableType pseudoTableType = default,
                                                                   NpgsqlTransaction transaction             = null)
        {
            var identityBehavior = BulkImportIdentityBehavior.Unspecified;
            var dbSetting        = connection.GetDbSetting();
            var dbFields         = DbFieldCache.Get(connection, tableName, transaction);
            var primaryKey       = dbFields.FirstOrDefault(dbField => dbField.IsPrimary);
            var pseudoTableName  = tableName;
            IEnumerable <NpgsqlBulkInsertMapItem> mappings = null;

            return(PseudoBasedBinaryImport(connection,
                                           tableName,
                                           bulkCopyTimeout,
                                           dbFields,

                                           // getPseudoTableName
                                           () =>
                                           pseudoTableName = GetBinaryBulkDeleteByKeyPseudoTableName(tableName ?? ClassMappedNameCache.Get <TPrimaryKey>(), dbSetting),

                                           // getMappings
                                           () =>
                                           mappings = new[]
            {
                new NpgsqlBulkInsertMapItem(primaryKey.Name, primaryKey.Name)
            },

                                           // binaryImport
                                           (tableName) =>
                                           connection.BinaryImport(tableName,
                                                                   GetExpandoObjectData(primaryKeys, primaryKey.AsField()),
                                                                   mappings,
                                                                   dbFields,
                                                                   bulkCopyTimeout,
                                                                   batchSize,
                                                                   identityBehavior,
                                                                   dbSetting,
                                                                   transaction),

                                           // getDeleteToPseudoCommandText
                                           () =>
                                           GetDeleteByKeyCommandText(pseudoTableName,
                                                                     tableName,
                                                                     dbFields.FirstOrDefault(dbField => dbField.IsPrimary)?.AsField(),
                                                                     dbSetting),

                                           // setIdentities
                                           null,

                                           null,
                                           false,
                                           identityBehavior,
                                           pseudoTableType,
                                           dbSetting,
                                           transaction));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Query all the data from the table.
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entity.</typeparam>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The name of the target table.</param>
        /// <param name="fields">The mapping list of <see cref="Field"/> objects to be used.</param>
        /// <param name="orderBy">The order definition of the fields to be used.</param>
        /// <param name="hints">The table hints to be used.</param>
        /// <param name="cacheKey">
        /// The key to the cache item.By setting this argument, it will return the item from the cache if present, otherwise it will query the database.
        /// This will only work if the 'cache' argument is set.
        /// </param>
        /// <param name="cacheItemExpiration">The expiration in minutes of the cache item.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="cache">The cache object to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <returns>An enumerable list of data entity objects.</returns>
        internal static IEnumerable <TEntity> QueryAllInternal <TEntity>(this IDbConnection connection,
                                                                         string tableName,
                                                                         IEnumerable <Field> fields       = null,
                                                                         IEnumerable <OrderField> orderBy = null,
                                                                         string hints                       = null,
                                                                         string cacheKey                    = null,
                                                                         int?cacheItemExpiration            = Constant.DefaultCacheItemExpirationInMinutes,
                                                                         int?commandTimeout                 = null,
                                                                         IDbTransaction transaction         = null,
                                                                         ICache cache                       = null,
                                                                         ITrace trace                       = null,
                                                                         IStatementBuilder statementBuilder = null)
            where TEntity : class
        {
            // Ensure the fields
            fields = GetQualifiedFields <TEntity>(fields) ??
                     DbFieldCache.Get(connection, tableName, transaction)?.AsFields();

            // Return
            return(QueryAllInternalBase <TEntity>(connection: connection,
                                                  tableName: tableName,
                                                  fields: fields,
                                                  orderBy: orderBy,
                                                  hints: hints,
                                                  cacheKey: cacheKey,
                                                  cacheItemExpiration: cacheItemExpiration,
                                                  commandTimeout: commandTimeout,
                                                  transaction: transaction,
                                                  cache: cache,
                                                  trace: trace,
                                                  statementBuilder: statementBuilder));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Inserts multiple data in the database in an asynchronous way. By default, the database fields are used unless the 'fields' argument is defined.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The name of the target table to be used.</param>
        /// <param name="entities">The list of dynamic objects to be inserted.</param>
        /// <param name="batchSize">The batch size of the insertion.</param>
        /// <param name="fields">The mapping list of <see cref="Field"/> objects to be used.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <returns>The number of inserted rows.</returns>
        internal static Task <int> InsertAllAsyncInternal(this IDbConnection connection,
                                                          string tableName,
                                                          IEnumerable <object> entities,
                                                          int batchSize = Constant.DefaultBatchOperationSize,
                                                          IEnumerable <Field> fields = null,
                                                          int?commandTimeout         = null,
                                                          IDbTransaction transaction = null,
                                                          ITrace trace = null,
                                                          IStatementBuilder statementBuilder = null)
        {
            // Check the fields
            if (fields == null)
            {
                fields = DbFieldCache.Get(connection, tableName)?.AsFields();
            }

            // Return the result
            return(InsertAllAsyncInternalBase <object>(connection: connection,
                                                       tableName: tableName,
                                                       entities: entities,
                                                       batchSize: batchSize,
                                                       fields: fields,
                                                       commandTimeout: commandTimeout,
                                                       transaction: transaction,
                                                       trace: trace,
                                                       statementBuilder: statementBuilder,
                                                       skipIdentityCheck: true));
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Gets the identity <see cref="DbField"/> object.
 /// </summary>
 /// <param name="request">The request object.</param>
 /// <returns>The identity <see cref="DbField"/> object.</returns>
 private static DbField GetIdentityField(BaseRequest request)
 {
     if (request.Type != null && request.Type != typeof(object))
     {
         var identityProperty = IdentityCache.Get(request.Type);
         if (identityProperty != null)
         {
             var primaryProperty = PrimaryCache.Get(request.Type);
             var isPrimary       = false;
             if (primaryProperty != null)
             {
                 isPrimary = string.Equals(primaryProperty.GetMappedName(), identityProperty.GetMappedName(), StringComparison.OrdinalIgnoreCase);
             }
             return(new DbField(identityProperty.GetMappedName(),
                                isPrimary,
                                true,
                                false,
                                identityProperty.PropertyInfo.PropertyType,
                                null,
                                null,
                                null,
                                null));
         }
     }
     return(DbFieldCache.Get(request.Connection, request.Name, request.Transaction)?.FirstOrDefault(f => f.IsIdentity));
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Count the number of rows from the table.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="request">The actual <see cref="CountAllRequest"/> object.</param>
        /// <param name="param">The mapped object parameters.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <returns>An integer value that holds the number of rows from the table.</returns>
        internal static long CountAllInternalBase(this IDbConnection connection,
                                                  CountAllRequest request,
                                                  object param,
                                                  int?commandTimeout         = null,
                                                  IDbTransaction transaction = null,
                                                  ITrace trace = null)
        {
            // Variables
            var commandType = CommandType.Text;
            var commandText = CommandTextCache.GetCountAllText(request);
            var sessionId   = Guid.Empty;

            // Before Execution
            if (trace != null)
            {
                sessionId = Guid.NewGuid();
                var cancellableTraceLog = new CancellableTraceLog(sessionId, commandText, param, null);
                trace.BeforeCountAll(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException(commandText);
                    }
                    return(default(int));
                }
                commandText = (cancellableTraceLog.Statement ?? commandText);
                param       = (cancellableTraceLog.Parameter ?? param);
            }

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

            // Actual Execution
            var result = ExecuteScalarInternal <long>(connection: connection,
                                                      commandText: commandText,
                                                      param: param,
                                                      commandType: commandType,
                                                      cacheKey: null,
                                                      cacheItemExpiration: null,
                                                      commandTimeout: commandTimeout,
                                                      transaction: transaction,
                                                      cache: null,
                                                      entityType: request.Type,
                                                      dbFields: DbFieldCache.Get(connection, request.Name, transaction, true),
                                                      skipCommandArrayParametersCheck: true);

            // After Execution
            if (trace != null)
            {
                trace.AfterCountAll(new TraceLog(sessionId, commandText, param, result,
                                                 DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Result
            return(result);
        }
Ejemplo n.º 7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="fields"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static IEnumerable <Field> GetActualFields(IDbConnection connection,
                                                           string tableName,
                                                           IEnumerable <Field> fields,
                                                           IDbTransaction transaction)
        {
            if (fields?.Any() != true)
            {
                return(null);
            }
            var dbFields = DbFieldCache.Get(connection, tableName, transaction);

            return(GetActualFieldsInternal(fields, dbFields, connection.GetDbSetting()));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Truncates a table from the database.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="request">The actual <see cref="TruncateRequest"/> object.</param>
        /// <param name="commandTimeout">The command timeout in seconds 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.</returns>
        internal static int TruncateInternalBase(this IDbConnection connection,
                                                 TruncateRequest request,
                                                 int?commandTimeout         = null,
                                                 IDbTransaction transaction = null,
                                                 ITrace trace = null)
        {
            // Variables
            var commandType = CommandType.Text;
            var commandText = CommandTextCache.GetTruncateText(request);
            var sessionId   = Guid.Empty;

            // Before Execution
            if (trace != null)
            {
                sessionId = Guid.NewGuid();
                var cancellableTraceLog = new CancellableTraceLog(sessionId, commandText, null, null);
                trace.BeforeTruncate(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException(commandText);
                    }
                }
                commandText = (cancellableTraceLog.Statement ?? commandText);
            }

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

            // Actual Execution
            var result = ExecuteNonQueryInternal(connection: connection,
                                                 commandText: commandText,
                                                 param: null,
                                                 commandType: commandType,
                                                 commandTimeout: commandTimeout,
                                                 transaction: transaction,
                                                 entityType: request.Type,
                                                 dbFields: DbFieldCache.Get(connection, request.Name, transaction, true),
                                                 skipCommandArrayParametersCheck: true);

            // After Execution
            if (trace != null)
            {
                trace.AfterTruncate(new TraceLog(sessionId, commandText, null, result,
                                                 DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Return the result
            return(result);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Initializes the current instance of <see cref="DataEntityDataReader{TEntity}"/> object.
        /// </summary>
        public void Initialize()
        {
            if (IsInitialized)
            {
                return;
            }
            var dbFields = (IEnumerable <DbField>)null;

            if (Connection != null)
            {
                dbFields = DbFieldCache.Get(Connection, TableName, Transaction, false);
            }
            InitializeInternal(dbFields);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Initializes the current instance of <see cref="DataEntityDataReader{TEntity}"/> object.
        /// </summary>
        public void Initialize()
        {
            if (IsInitialized)
            {
                return;
            }
            var dbFields = (IEnumerable <DbField>)null;

            if (Connection != null)
            {
                dbFields = DbFieldCache.Get(Connection, ClassMappedNameCache.Get <TEntity>(), Transaction);
            }
            InitializeInternal(dbFields);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Get the actual list of <see cref="Field"/> objects of the table based on the actual list of <see cref="DbField"/> objects.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="fields">The target name of the table.</param>
        /// <param name="tableName">The list of fields from the data entity object.</param>
        /// <param name="transaction">The transaction object that is currently in used.</param>
        /// <returns>The actual list of <see cref="Field"/> objects of the table.</returns>
        private static IEnumerable <Field> GetActualFields(IDbConnection connection, string tableName, IEnumerable <Field> fields, IDbTransaction transaction)
        {
            if (fields?.Any() != true)
            {
                return(null);
            }

            // Get all the fields from the database
            var dbFields = DbFieldCache.Get(connection, tableName, transaction);

            // Return the filtered one
            return(dbFields?.Any() == true?
                   fields.Where(f => dbFields.FirstOrDefault(df => string.Equals(df.UnquotedName, f.UnquotedName, StringComparison.OrdinalIgnoreCase)) != null) :
                       fields);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Get the actual list of <see cref="Field"/> objects of the table based on the actual list of <see cref="DbField"/> objects.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="fields">The target name of the table.</param>
        /// <param name="tableName">The list of fields from the data entity object.</param>
        /// <returns>The actual list of <see cref="Field"/> objects of the table.</returns>
        private static IEnumerable <Field> GetActualFields(IDbConnection connection, string tableName, IEnumerable <Field> fields)
        {
            if (fields?.Any() != true)
            {
                return(null);
            }

            // Get all the fields from the database
            var dbFields = DbFieldCache.Get(connection, tableName);

            // Return the filtered one
            return(dbFields?.Any() == true?
                   fields.Where(f => dbFields.FirstOrDefault(df => df.UnquotedName.ToLower() == f.UnquotedName.ToLower()) != null) :
                       fields);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Ensures that the <see cref="DbFieldCache.Get(IDbConnection, string, IDbTransaction)"/> method is being called one.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity to check.</typeparam>
        /// <param name="transaction">The transaction object that is currently in used.</param>
        private void EnsureSingleCallForDbFieldCacheGet <TEntity>(IDbTransaction transaction)
            where TEntity : class
        {
            var key      = GetDbFieldGetCallsCacheKey <TEntity>();
            var dbFields = (IEnumerable <DbField>)null;

            // Try get the value
            if (cache.TryGetValue(key, out dbFields) == false)
            {
                using (var connection = (IDbConnection)Activator.CreateInstance(this.connection.GetType(), new object[] { connectionString }))
                {
                    dbFields = DbFieldCache.Get(connection, ClassMappedNameCache.Get <TEntity>(), transaction, false);
                    cache.TryAdd(key, dbFields);
                }
            }
        }
Ejemplo n.º 14
0
 /// <summary>
 /// Gets the identity <see cref="DbField"/> object.
 /// </summary>
 /// <param name="request">The request object.</param>
 /// <returns>The identity <see cref="DbField"/> object.</returns>
 private static DbField GetIdentityField(BaseRequest request)
 {
     if (request.Type != null && request.Type != typeof(object))
     {
         var identityProperty = IdentityCache.Get(request.Type);
         if (identityProperty != null)
         {
             var primaryPropery = PrimaryCache.Get(request.Type);
             var isPrimary      = false;
             if (primaryPropery != null)
             {
                 isPrimary = primaryPropery.GetUnquotedMappedName().ToLower() == identityProperty.GetUnquotedMappedName().ToLower();
             }
             return(new DbField(identityProperty.GetUnquotedMappedName(), isPrimary, true, false,
                                identityProperty.PropertyInfo.PropertyType, null, null, null));
         }
     }
     return(DbFieldCache.Get(request.Connection, request.Name)?.FirstOrDefault(f => f.IsIdentity));
 }
Ejemplo n.º 15
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        /// <param name="dbFields"></param>
        /// <param name="mappings"></param>
        /// <param name="options"></param>
        /// <param name="hints"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="isReturnIdentity"></param>
        /// <param name="usePhysicalPseudoTempTable"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int BulkInsertInternalBase <TEntity>(SqlConnection connection,
                                                            string tableName,
                                                            IEnumerable <TEntity> entities,
                                                            IEnumerable <DbField> dbFields           = null,
                                                            IEnumerable <BulkInsertMapItem> mappings = null,
                                                            SqlBulkCopyOptions options = default,
                                                            string hints                    = null,
                                                            int?bulkCopyTimeout             = null,
                                                            int?batchSize                   = null,
                                                            bool?isReturnIdentity           = null,
                                                            bool?usePhysicalPseudoTempTable = null,
                                                            SqlTransaction transaction      = null)
            where TEntity : class
        {
            // Validate
            // ThrowIfNullOrEmpty(entities);

            // Variables needed
            var dbSetting      = connection.GetDbSetting();
            var hasTransaction = transaction != null;
            int result;

            transaction = CreateOrValidateCurrentTransaction(connection, transaction);

            try
            {
                // Get the DB Fields
                dbFields ??= DbFieldCache.Get(connection, tableName, transaction, true);

                // Variables needed
                var identityDbField = dbFields?.FirstOrDefault(dbField => dbField.IsIdentity);
                var entityType      = entities?.FirstOrDefault()?.GetType() ?? typeof(TEntity);
                var entityFields    = entityType.IsDictionaryStringObject() ?
                                      GetDictionaryStringObjectFields(entities?.FirstOrDefault() as IDictionary <string, object>) :
                                      FieldCache.Get(entityType);
                var fields = dbFields?.Select(dbField => dbField.AsField());

                // Filter the fields (based on mappings)
                if (mappings?.Any() == true)
                {
                    fields = fields?
                             .Where(e =>
                                    mappings.Any(mapping => string.Equals(mapping.DestinationColumn, e.Name, StringComparison.OrdinalIgnoreCase)) == true);
                }
                else
                {
                    // Filter the fields (based on the data entity)
                    if (entityFields?.Any() == true)
                    {
                        fields = fields?
                                 .Where(e =>
                                        entityFields.Any(f => string.Equals(f.Name, e.Name, StringComparison.OrdinalIgnoreCase)) == true);
                    }

                    // Explicitly define the mappings
                    mappings = fields?
                               .Select(e =>
                                       new BulkInsertMapItem(e.Name, e.Name));
                }

                // Throw an error if there are no fields
                if (fields?.Any() != true)
                {
                    throw new MissingFieldException("There are no field(s) found for this operation.");
                }

                // Pseudo temp table
                var withPseudoExecution = isReturnIdentity == true && identityDbField != null;
                var tempTableName       = CreateBulkInsertTempTableIfNecessary(connection,
                                                                               tableName,
                                                                               usePhysicalPseudoTempTable,
                                                                               transaction,
                                                                               withPseudoExecution,
                                                                               dbSetting,
                                                                               fields);

                // WriteToServer
                result = WriteToServerInternal(connection,
                                               tempTableName ?? tableName,
                                               entities,
                                               mappings,
                                               options,
                                               bulkCopyTimeout,
                                               batchSize,
                                               withPseudoExecution,
                                               transaction);

                // Check if this is with pseudo
                if (withPseudoExecution)
                {
                    // Merge the actual data
                    var sql = GetBulkInsertSqlText(tableName,
                                                   tempTableName,
                                                   fields,
                                                   identityDbField?.AsField(),
                                                   hints,
                                                   dbSetting,
                                                   withPseudoExecution);

                    // Execute the SQL
                    using (var reader = (DbDataReader)connection.ExecuteReader(sql, commandTimeout: bulkCopyTimeout, transaction: transaction))
                    {
                        var mapping       = mappings?.FirstOrDefault(e => string.Equals(e.DestinationColumn, identityDbField.Name, StringComparison.OrdinalIgnoreCase));
                        var identityField = mapping != null ? new Field(mapping.SourceColumn) : identityDbField.AsField();
                        result = SetIdentityForEntities(entities, reader, identityField);
                    }

                    // Drop the table after used
                    sql = GetDropTemporaryTableSqlText(tempTableName, dbSetting);
                    connection.ExecuteNonQuery(sql, transaction: transaction);
                }

                CommitTransaction(transaction, hasTransaction);
            }
            catch
            {
                RollbackTransaction(transaction, hasTransaction);
                throw;
            }
            finally
            {
                DisposeTransaction(transaction, hasTransaction);
            }

            // Return the result
            return(result);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Query all the data from the database.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The name of the target table.</param>
        /// <param name="fields">The list of fields to be queried.</param>
        /// <param name="orderBy">The order definition of the fields to be used.</param>
        /// <param name="hints">The table hints to be used. See <see cref="SqlTableHints"/> class.</param>
        /// <param name="cacheKey">
        /// The key to the cache. If the cache key is present in the cache, then the item from the cache will be returned instead. Setting this
        /// to null would force to query from the database.
        /// </param>
        /// <param name="cacheItemExpiration">The expiration in minutes of the cache item.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="cache">The cache object to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <returns>An enumerable list of data entity object.</returns>
        internal static async Task <IEnumerable <dynamic> > QueryAllAsyncInternalBase(this IDbConnection connection,
                                                                                      string tableName,
                                                                                      IEnumerable <Field> fields       = null,
                                                                                      IEnumerable <OrderField> orderBy = null,
                                                                                      string hints                       = null,
                                                                                      string cacheKey                    = null,
                                                                                      int cacheItemExpiration            = Constant.DefaultCacheItemExpirationInMinutes,
                                                                                      int?commandTimeout                 = null,
                                                                                      IDbTransaction transaction         = null,
                                                                                      ICache cache                       = null,
                                                                                      ITrace trace                       = null,
                                                                                      IStatementBuilder statementBuilder = null)
        {
            // Get Cache
            if (cacheKey != null)
            {
                var item = cache?.Get(cacheKey, false);
                if (item != null)
                {
                    return((IEnumerable <dynamic>)item.Value);
                }
            }

            // Check the fields
            if (fields?.Any() != true)
            {
                fields = DbFieldCache.Get(connection, tableName)?.Select(f => f.AsField());
            }

            // Variables
            var commandType = CommandType.Text;
            var request     = new QueryAllRequest(tableName,
                                                  connection,
                                                  fields,
                                                  orderBy,
                                                  hints,
                                                  statementBuilder);
            var commandText = CommandTextCache.GetQueryAllText(request);
            var param       = (object)null;

            // Before Execution
            if (trace != null)
            {
                var cancellableTraceLog = new CancellableTraceLog(commandText, param, null);
                trace.BeforeQueryAll(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException(commandText);
                    }
                    return(null);
                }
                commandText = (cancellableTraceLog.Statement ?? commandText);
                param       = (cancellableTraceLog.Parameter ?? param);
            }

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

            // Actual Execution
            var result = await ExecuteQueryAsyncInternal(connection : connection,
                                                         commandText : commandText,
                                                         param : param,
                                                         commandType : commandType,
                                                         commandTimeout : commandTimeout,
                                                         transaction : transaction,
                                                         tableName : tableName,
                                                         skipCommandArrayParametersCheck : true);

            // After Execution
            if (trace != null)
            {
                trace.AfterQueryAll(new TraceLog(commandText, param, result,
                                                 DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Set Cache
            if (cacheKey != null)
            {
                cache?.Add(cacheKey, result, cacheItemExpiration);
            }

            // Result
            return(result);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Query all the data from 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="orderBy">The order definition of the fields to be used.</param>
        /// <param name="hints">The table hints to be used. See <see cref="SqlTableHints"/> class.</param>
        /// <param name="cacheKey">
        /// The key to the cache. If the cache key is present in the cache, then the item from the cache will be returned instead. Setting this
        /// to null would force to query from the database.
        /// </param>
        /// <param name="cacheItemExpiration">The expiration in minutes of the cache item.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="cache">The cache object to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <returns>An enumerable list of data entity object.</returns>
        internal static Task <IEnumerable <TEntity> > QueryAllAsyncInternalBase <TEntity>(this IDbConnection connection,
                                                                                          IEnumerable <OrderField> orderBy = null,
                                                                                          string hints                       = null,
                                                                                          string cacheKey                    = null,
                                                                                          int cacheItemExpiration            = Constant.DefaultCacheItemExpirationInMinutes,
                                                                                          int?commandTimeout                 = null,
                                                                                          IDbTransaction transaction         = null,
                                                                                          ICache cache                       = null,
                                                                                          ITrace trace                       = null,
                                                                                          IStatementBuilder statementBuilder = null)
            where TEntity : class
        {
            // Get Cache
            if (cacheKey != null)
            {
                var item = cache?.Get(cacheKey, false);
                if (item != null)
                {
                    return(Task.FromResult((IEnumerable <TEntity>)item.Value));
                }
            }

            // Variables
            var commandType = CommandType.Text;
            var request     = new QueryAllRequest(typeof(TEntity),
                                                  connection,
                                                  FieldCache.Get <TEntity>(),
                                                  orderBy,
                                                  hints,
                                                  statementBuilder);
            var commandText = CommandTextCache.GetQueryAllText(request);
            var param       = (object)null;

            // Database pre-touch for field definitions
            DbFieldCache.Get(connection, ClassMappedNameCache.Get <TEntity>());

            // Before Execution
            if (trace != null)
            {
                var cancellableTraceLog = new CancellableTraceLog(commandText, param, null);
                trace.BeforeQueryAll(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException(commandText);
                    }
                    return(Task.FromResult <IEnumerable <TEntity> >(null));
                }
                commandText = (cancellableTraceLog.Statement ?? commandText);
                param       = (cancellableTraceLog.Parameter ?? param);
            }

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

            // Actual Execution
            var result = ExecuteQueryAsyncInternal <TEntity>(connection: connection,
                                                             commandText: commandText,
                                                             param: param,
                                                             commandType: commandType,
                                                             commandTimeout: commandTimeout,
                                                             transaction: transaction,
                                                             basedOnFields: false,
                                                             skipCommandArrayParametersCheck: true);

            // After Execution
            if (trace != null)
            {
                trace.AfterQueryAll(new TraceLog(commandText, param, result,
                                                 DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Set Cache
            if (cacheKey != null /* && result.Result?.Any() == true */)
            {
                cache?.Add(cacheKey, result, cacheItemExpiration);
            }

            // Result
            return(result);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Inserts a new row in the table.
        /// </summary>
        /// <typeparam name="TEntity">The type of the object (whether a data entity or a dynamic).</typeparam>
        /// <typeparam name="TResult">The target type of the result.</typeparam>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The name of the target table to be used.</param>
        /// <param name="entity">The data entity or dynamic object to be inserted.</param>
        /// <param name="fields">The mapping list of <see cref="Field"/> objects to be used.</param>
        /// <param name="hints">The table hints to be used.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <param name="skipIdentityCheck">True to skip the identity check.</param>
        /// <returns>The value of the identity field if present, otherwise, the value of the primary field.</returns>
        internal static TResult InsertInternalBase <TEntity, TResult>(this IDbConnection connection,
                                                                      string tableName,
                                                                      TEntity entity,
                                                                      IEnumerable <Field> fields = null,
                                                                      string hints                       = null,
                                                                      int?commandTimeout                 = null,
                                                                      IDbTransaction transaction         = null,
                                                                      ITrace trace                       = null,
                                                                      IStatementBuilder statementBuilder = null,
                                                                      bool skipIdentityCheck             = false)
            where TEntity : class
        {
            // Variables needed
            var dbSetting = connection.GetDbSetting();

            // Get the function
            var callback = new Func <InsertExecutionContext <TEntity> >(() =>
            {
                // Variables needed
                var identity        = (Field)null;
                var dbFields        = DbFieldCache.Get(connection, tableName, transaction);
                var inputFields     = (IEnumerable <DbField>)null;
                var identityDbField = dbFields?.FirstOrDefault(f => f.IsIdentity);

                // Set the identity field
                if (skipIdentityCheck == false)
                {
                    identity = IdentityCache.Get <TEntity>()?.AsField();
                    if (identity == null && identityDbField != null)
                    {
                        identity = FieldCache.Get <TEntity>().FirstOrDefault(field =>
                                                                             string.Equals(field.Name.AsUnquoted(true, dbSetting), identityDbField.Name.AsUnquoted(true, dbSetting), StringComparison.OrdinalIgnoreCase));
                    }
                }

                // Filter the actual properties for input fields
                inputFields = dbFields?
                              .Where(dbField => dbField.IsIdentity == false)
                              .Where(dbField =>
                                     fields.FirstOrDefault(field => string.Equals(field.Name.AsUnquoted(true, dbSetting), dbField.Name.AsUnquoted(true, dbSetting), StringComparison.OrdinalIgnoreCase)) != null)
                              .AsList();

                // Variables for the entity action
                var identityPropertySetter = (Action <TEntity, object>)null;

                // Get the identity setter
                if (skipIdentityCheck == false && identity != null)
                {
                    identityPropertySetter = FunctionCache.GetDataEntityPropertyValueSetterFunction <TEntity>(identity);
                }

                // Identify the requests
                var insertRequest = (InsertRequest)null;

                // Create a different kind of requests
                if (typeof(TEntity) == StaticType.Object)
                {
                    insertRequest = new InsertRequest(tableName,
                                                      connection,
                                                      transaction,
                                                      fields,
                                                      hints,
                                                      statementBuilder);
                }
                else
                {
                    insertRequest = new InsertRequest(typeof(TEntity),
                                                      connection,
                                                      transaction,
                                                      fields,
                                                      hints,
                                                      statementBuilder);
                }

                // Return the value
                return(new InsertExecutionContext <TEntity>
                {
                    CommandText = CommandTextCache.GetInsertText(insertRequest),
                    InputFields = inputFields,
                    ParametersSetterFunc = FunctionCache.GetDataEntityDbCommandParameterSetterFunction <TEntity>(
                        string.Concat(typeof(TEntity).FullName, StringConstant.Period, tableName, ".Insert"),
                        inputFields?.AsList(),
                        null,
                        dbSetting),
                    IdentityPropertySetterFunc = identityPropertySetter
                });
            });

            // Get the context
            var context = InsertExecutionContextCache <TEntity> .Get(tableName, fields, callback);

            var sessionId = Guid.Empty;

            // Before Execution
            if (trace != null)
            {
                sessionId = Guid.NewGuid();
                var cancellableTraceLog = new CancellableTraceLog(sessionId, context.CommandText, entity, null);
                trace.BeforeInsert(cancellableTraceLog);
                if (cancellableTraceLog.IsCancelled)
                {
                    if (cancellableTraceLog.IsThrowException)
                    {
                        throw new CancelledExecutionException(context.CommandText);
                    }
                    return(default(TResult));
                }
                context.CommandText = (cancellableTraceLog.Statement ?? context.CommandText);
                entity = (TEntity)(cancellableTraceLog.Parameter ?? entity);
            }

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

            // Execution variables
            var result = default(TResult);

            // Create the command
            using (var command = (DbCommand)connection.EnsureOpen().CreateCommand(context.CommandText,
                                                                                  CommandType.Text, commandTimeout, transaction))
            {
                // Set the values
                context.ParametersSetterFunc(command, entity);

                // Actual Execution
                result = Converter.ToType <TResult>(command.ExecuteScalar());

                // Get explicity if needed
                if (Equals(result, default(TResult)) == true && dbSetting.IsMultiStatementExecutable == false)
                {
                    result = Converter.ToType <TResult>(connection.GetDbHelper().GetScopeIdentity(connection, transaction));
                }

                // Set the return value
                if (Equals(result, default(TResult)) == false)
                {
                    context.IdentityPropertySetterFunc?.Invoke(entity, result);
                }
            }

            // After Execution
            if (trace != null)
            {
                trace.AfterInsert(new TraceLog(sessionId, context.CommandText, entity, result,
                                               DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Return the result
            return(result);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Bulk insert an instance of <see cref="DbDataReader"/> object into the database.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The target table for bulk-insert operation.</param>
        /// <param name="reader">The <see cref="DbDataReader"/> object to be used in the bulk-insert operation.</param>
        /// <param name="dbFields">The list of <see cref="DbField"/> objects.</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>
        internal static int BulkInsertInternal(SqlConnection connection,
                                               string tableName,
                                               DbDataReader reader,
                                               IEnumerable <DbField> dbFields           = null,
                                               IEnumerable <BulkInsertMapItem> mappings = null,
                                               SqlBulkCopyOptions?options = null,
                                               int?bulkCopyTimeout        = null,
                                               int?batchSize = null,
                                               SqlTransaction transaction = null)
        {
            // Validate the objects
            SqlConnectionExtension.ValidateTransactionConnectionObject(connection, transaction);

            // Get the DB Fields
            dbFields = dbFields ?? DbFieldCache.Get(connection, tableName, transaction);
            if (dbFields?.Any() != true)
            {
                throw new InvalidOperationException($"No database fields found for '{tableName}'.");
            }

            // Variables needed
            var result       = 0;
            var readerFields = Enumerable
                               .Range(0, reader.FieldCount)
                               .Select((index) => reader.GetName(index));
            var mappingFields = new List <Tuple <string, string> >();

            // To fix the casing problem of the bulk inserts
            foreach (var dbField in dbFields)
            {
                var readerField = readerFields.FirstOrDefault(field =>
                                                              string.Equals(field, dbField.Name, StringComparison.OrdinalIgnoreCase));
                if (!string.IsNullOrEmpty(readerField))
                {
                    mappingFields.Add(new Tuple <string, string>(readerField, dbField.Name));
                }
            }

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

            // Actual Execution
            using (var sqlBulkCopy = new SqlBulkCopy(connection, options.GetValueOrDefault(), transaction))
            {
                // Set the destinationtable
                sqlBulkCopy.DestinationTableName = tableName;

                // Set the timeout
                if (bulkCopyTimeout != null && bulkCopyTimeout.HasValue)
                {
                    sqlBulkCopy.BulkCopyTimeout = bulkCopyTimeout.Value;
                }

                // Set the batch szie
                if (batchSize != null && batchSize.HasValue)
                {
                    sqlBulkCopy.BatchSize = batchSize.Value;
                }

                // Add the mappings
                if (mappings == null)
                {
                    // Iterate the filtered fields
                    foreach (var field in mappingFields)
                    {
                        sqlBulkCopy.ColumnMappings.Add(field.Item1, field.Item2);
                    }
                }
                else
                {
                    // Iterate the provided mappings
                    foreach (var mapItem in mappings)
                    {
                        sqlBulkCopy.ColumnMappings.Add(mapItem.SourceColumn, mapItem.DestinationColumn);
                    }
                }

                // Open the connection and do the operation
                connection.EnsureOpen();
                sqlBulkCopy.WriteToServer(reader);

                // Hack the 'SqlBulkCopy' object
                var copiedField = GetRowsCopiedFieldFromMicrosoftDataSqlBulkCopy();

                // Set the return value
                result = copiedField != null ? (int)copiedField.GetValue(sqlBulkCopy) : reader.RecordsAffected;
            }

            // Result
            return(result);
        }
Ejemplo n.º 20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="reader"></param>
        /// <param name="qualifiers"></param>
        /// <param name="mappings"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="keepIdentity"></param>
        /// <param name="pseudoTableType"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int BinaryBulkDeleteBase(this NpgsqlConnection connection,
                                                string tableName,
                                                DbDataReader reader,
                                                IEnumerable <Field> qualifiers = null,
                                                IEnumerable <NpgsqlBulkInsertMapItem> mappings = null,
                                                int?bulkCopyTimeout = null,
                                                bool keepIdentity   = true,
                                                BulkImportPseudoTableType pseudoTableType = default,
                                                NpgsqlTransaction transaction             = null)
        {
            var dbSetting        = connection.GetDbSetting();
            var dbFields         = DbFieldCache.Get(connection, tableName, transaction);
            var pseudoTableName  = tableName;
            var identityBehavior = keepIdentity ? BulkImportIdentityBehavior.KeepIdentity : BulkImportIdentityBehavior.Unspecified;

            return(PseudoBasedBinaryImport(connection,
                                           tableName,
                                           bulkCopyTimeout,
                                           dbFields,

                                           // getPseudoTableName
                                           () =>
                                           pseudoTableName = GetBinaryBulkDeletePseudoTableName(tableName, dbSetting),

                                           // getMappings
                                           () =>
            {
                var includeIdentity = identityBehavior == BulkImportIdentityBehavior.KeepIdentity;
                var includePrimary = true;

                return mappings = mappings?.Any() == true ? mappings :
                                  GetMappings(reader,
                                              dbFields,
                                              includePrimary,
                                              includeIdentity,
                                              dbSetting);
            },

                                           // binaryImport
                                           (tableName) =>
                                           connection.BinaryImport(tableName,
                                                                   reader,
                                                                   mappings,
                                                                   dbFields,
                                                                   bulkCopyTimeout,
                                                                   identityBehavior,
                                                                   dbSetting,
                                                                   transaction),

                                           // getDeleteToPseudoCommandText
                                           () =>
                                           GetDeleteCommandText(pseudoTableName,
                                                                tableName,
                                                                mappings.Select(mapping => new Field(mapping.DestinationColumn)),
                                                                qualifiers,
                                                                dbFields.FirstOrDefault(dbField => dbField.IsPrimary)?.AsField(),
                                                                dbFields.FirstOrDefault(dbField => dbField.IsIdentity)?.AsField(),
                                                                identityBehavior,
                                                                dbSetting),

                                           // setIdentities
                                           null,

                                           qualifiers,
                                           false,
                                           identityBehavior,
                                           pseudoTableType,
                                           dbSetting,
                                           transaction: transaction));
        }
Ejemplo n.º 21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="table"></param>
        /// <param name="rowState"></param>
        /// <param name="mappings"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="identityBehavior"></param>
        /// <param name="pseudoTableType"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int BinaryBulkInsertBase(this NpgsqlConnection connection,
                                                string tableName,
                                                DataTable table,
                                                DataRowState?rowState = null,
                                                IEnumerable <NpgsqlBulkInsertMapItem> mappings = null,
                                                int?bulkCopyTimeout = null,
                                                int?batchSize       = null,
                                                BulkImportIdentityBehavior identityBehavior = default,
                                                BulkImportPseudoTableType pseudoTableType   = default,
                                                NpgsqlTransaction transaction = null)
        {
            var dbSetting       = connection.GetDbSetting();
            var dbFields        = DbFieldCache.Get(connection, tableName, transaction);
            var pseudoTableName = tableName;

            return(PseudoBasedBinaryImport(connection,
                                           tableName,
                                           bulkCopyTimeout,
                                           dbFields,

                                           // getPseudoTableName
                                           () =>
                                           pseudoTableName = GetBinaryBulkInsertPseudoTableName(tableName, dbSetting),

                                           // getMappings
                                           () =>
            {
                var includeIdentity = identityBehavior == BulkImportIdentityBehavior.KeepIdentity;
                var isPrimaryAnIdentity = IsPrimaryAnIdentity(dbFields);
                var includePrimary = isPrimaryAnIdentity == false ||
                                     (isPrimaryAnIdentity && includeIdentity);

                return mappings = mappings?.Any() == true ? mappings :
                                  GetMappings(table,
                                              dbFields,
                                              includePrimary,
                                              includeIdentity,
                                              dbSetting);
            },

                                           // binaryImport
                                           (tableName) =>
                                           connection.BinaryImport(tableName,
                                                                   table,
                                                                   rowState,
                                                                   mappings,
                                                                   dbFields,
                                                                   bulkCopyTimeout,
                                                                   batchSize,
                                                                   identityBehavior,
                                                                   dbSetting,
                                                                   transaction),

                                           // getMergeToPseudoCommandText
                                           () =>
                                           GetInsertCommandText(pseudoTableName,
                                                                tableName,
                                                                mappings.Select(mapping => new Field(mapping.DestinationColumn)),
                                                                dbFields.FirstOrDefault(dbField => dbField.IsIdentity)?.AsField(),
                                                                identityBehavior,
                                                                dbSetting),

                                           // setIdentities
                                           (identityResults) =>
                                           SetDataTableIdentities(table, dbFields, identityResults, dbSetting),

                                           null,
                                           true,
                                           identityBehavior: identityBehavior,
                                           pseudoTableType: pseudoTableType,
                                           dbSetting,
                                           transaction: transaction));
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Bulk insert an instance of <see cref="DataTable"/> object into the database.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The target table for bulk-insert operation.</param>
        /// <param name="dataTable">The <see cref="DataTable"/> object to be used in the bulk-insert operation.</param>
        /// <param name="rowState">The state of the rows to be copied to the destination.</param>
        /// <param name="dbFields">The list of <see cref="DbField"/> objects.</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>
        internal static int BulkInsertInternal(SqlConnection connection,
                                               string tableName,
                                               DataTable dataTable,
                                               DataRowState?rowState                    = null,
                                               IEnumerable <DbField> dbFields           = null,
                                               IEnumerable <BulkInsertMapItem> mappings = null,
                                               SqlBulkCopyOptions?options               = null,
                                               int?bulkCopyTimeout        = null,
                                               int?batchSize              = null,
                                               SqlTransaction transaction = null)
        {
            // Validate the objects
            SqlConnectionExtension.ValidateTransactionConnectionObject(connection, transaction);

            // Get the DB Fields
            dbFields = dbFields ?? DbFieldCache.Get(connection, tableName, transaction);
            if (dbFields?.Any() != true)
            {
                throw new InvalidOperationException($"No database fields found for '{tableName}'.");
            }

            // Variables needed
            var result      = 0;
            var tableFields = GetDataColumns(dataTable)
                              .Select(column => column.ColumnName);
            var mappingFields = new List <Tuple <string, string> >();

            // To fix the casing problem of the bulk inserts
            foreach (var dbField in dbFields)
            {
                var tableField = tableFields.FirstOrDefault(field =>
                                                            string.Equals(field, dbField.Name, StringComparison.OrdinalIgnoreCase));
                if (tableField != null)
                {
                    mappingFields.Add(new Tuple <string, string>(tableField, dbField.Name));
                }
            }

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

            // Actual Execution
            using (var sqlBulkCopy = new SqlBulkCopy(connection, options.GetValueOrDefault(), transaction))
            {
                // Set the destinationtable
                sqlBulkCopy.DestinationTableName = tableName;

                // Set the timeout
                if (bulkCopyTimeout != null && bulkCopyTimeout.HasValue)
                {
                    sqlBulkCopy.BulkCopyTimeout = bulkCopyTimeout.Value;
                }

                // Set the batch szie
                if (batchSize != null && batchSize.HasValue)
                {
                    sqlBulkCopy.BatchSize = batchSize.Value;
                }

                // Add the mappings
                if (mappings == null)
                {
                    // Iterate the filtered fields
                    foreach (var field in mappingFields)
                    {
                        sqlBulkCopy.ColumnMappings.Add(field.Item1, field.Item2);
                    }
                }
                else
                {
                    // Iterate the provided mappings
                    foreach (var mapItem in mappings)
                    {
                        sqlBulkCopy.ColumnMappings.Add(mapItem.SourceColumn, mapItem.DestinationColumn);
                    }
                }

                // Open the connection and do the operation
                connection.EnsureOpen();
                if (rowState.HasValue == true)
                {
                    sqlBulkCopy.WriteToServer(dataTable, rowState.Value);
                }
                else
                {
                    sqlBulkCopy.WriteToServer(dataTable);
                }

                // Set the return value
                result = GetDataRows(dataTable, rowState).Count();
            }

            // Result
            return(result);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Inserts multiple data in the database in an asynchronous way.
        /// </summary>
        /// <typeparam name="TEntity">The type of the object (whether a data entity or a dynamic).</typeparam>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The name of the target table to be used.</param>
        /// <param name="entities">The list of data entity or dynamic objects to be inserted.</param>
        /// <param name="batchSize">The batch size of the insertion.</param>
        /// <param name="fields">The mapping list of <see cref="Field"/> objects to be used.</param>
        /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
        /// <param name="transaction">The transaction to be used.</param>
        /// <param name="trace">The trace object to be used.</param>
        /// <param name="statementBuilder">The statement builder object to be used.</param>
        /// <param name="skipIdentityCheck">True to skip the identity check.</param>
        /// <returns>The number of inserted rows.</returns>
        internal static async Task <int> InsertAllAsyncInternalBase <TEntity>(this IDbConnection connection,
                                                                              string tableName,
                                                                              IEnumerable <TEntity> entities,
                                                                              int batchSize = Constant.DefaultBatchOperationSize,
                                                                              IEnumerable <Field> fields = null,
                                                                              int?commandTimeout         = null,
                                                                              IDbTransaction transaction = null,
                                                                              ITrace trace = null,
                                                                              IStatementBuilder statementBuilder = null,
                                                                              bool skipIdentityCheck             = false)
            where TEntity : class
        {
            // Guard the parameters
            var count = GuardInsertAll(entities);

            // Validate the batch size
            batchSize = Math.Min(batchSize, count);

            // Get the function
            var callback = new Func <int, InsertAllExecutionContext <TEntity> >((int batchSizeValue) =>
            {
                // Variables needed
                var identity        = (Field)null;
                var dbFields        = DbFieldCache.Get(connection, tableName);
                var inputFields     = (IEnumerable <DbField>)null;
                var outputFields    = (IEnumerable <DbField>)null;
                var identityDbField = dbFields?.FirstOrDefault(f => f.IsIdentity);

                // Set the identity value
                if (skipIdentityCheck == false)
                {
                    identity = IdentityCache.Get <TEntity>()?.AsField();
                    if (identity == null && identityDbField != null)
                    {
                        identity = FieldCache.Get <TEntity>().FirstOrDefault(field =>
                                                                             field.UnquotedName.ToLower() == identityDbField.UnquotedName.ToLower());
                    }
                }

                // Filter the actual properties for input fields
                inputFields = dbFields?
                              .Where(dbField => dbField.IsIdentity == false)
                              .Where(dbField =>
                                     fields.FirstOrDefault(field => field.UnquotedName.ToLower() == dbField.UnquotedName.ToLower()) != null)
                              .AsList();

                // Set the output fields
                if (batchSizeValue > 1)
                {
                    outputFields = identityDbField?.AsEnumerable();
                }

                // Variables for the context
                var multipleEntitiesFunc = (Action <DbCommand, IList <TEntity> >)null;
                var identitySettersFunc  = (List <Action <TEntity, DbCommand> >)null;
                var singleEntityFunc     = (Action <DbCommand, TEntity>)null;
                var identitySetterFunc   = (Action <TEntity, object>)null;

                // Get if we have not skipped it
                if (skipIdentityCheck == false && identity != null)
                {
                    if (batchSizeValue <= 1)
                    {
                        identitySetterFunc = FunctionCache.GetDataEntityPropertyValueSetterFunction <TEntity>(identity);
                    }
                    else
                    {
                        identitySettersFunc = new List <Action <TEntity, DbCommand> >();
                        for (var index = 0; index < batchSizeValue; index++)
                        {
                            identitySettersFunc.Add(FunctionCache.GetDataEntityPropertySetterFromDbCommandParameterFunction <TEntity>(identity, identity.UnquotedName, index));
                        }
                    }
                }

                // Identity which objects to set
                if (batchSizeValue <= 1)
                {
                    singleEntityFunc = FunctionCache.GetDataEntityDbCommandParameterSetterFunction <TEntity>(
                        string.Concat(typeof(TEntity).FullName, ".", tableName, ".InsertAll"),
                        inputFields?.AsList(),
                        null);
                }
                else
                {
                    multipleEntitiesFunc = FunctionCache.GetDataEntitiesDbCommandParameterSetterFunction <TEntity>(
                        string.Concat(typeof(TEntity).FullName, ".", tableName, ".InsertAll"),
                        inputFields?.AsList(),
                        outputFields,
                        batchSizeValue);
                }

                // Identify the requests
                var insertAllRequest = (InsertAllRequest)null;
                var insertRequest    = (InsertRequest)null;

                // Create a different kind of requests
                if (typeof(TEntity) == typeof(object))
                {
                    if (batchSizeValue > 1)
                    {
                        insertAllRequest = new InsertAllRequest(tableName,
                                                                connection,
                                                                fields,
                                                                batchSizeValue,
                                                                statementBuilder);
                    }
                    else
                    {
                        insertRequest = new InsertRequest(tableName,
                                                          connection,
                                                          fields,
                                                          statementBuilder);
                    }
                }
                else
                {
                    if (batchSizeValue > 1)
                    {
                        insertAllRequest = new InsertAllRequest(typeof(TEntity),
                                                                connection,
                                                                fields,
                                                                batchSizeValue,
                                                                statementBuilder);
                    }
                    else
                    {
                        insertRequest = new InsertRequest(typeof(TEntity),
                                                          connection,
                                                          fields,
                                                          statementBuilder);
                    }
                }

                // Return the value
                return(new InsertAllExecutionContext <TEntity>
                {
                    CommandText = batchSizeValue > 1 ? CommandTextCache.GetInsertAllText(insertAllRequest) : CommandTextCache.GetInsertText(insertRequest),
                    InputFields = inputFields,
                    OutputFields = outputFields,
                    BatchSize = batchSizeValue,
                    SingleDataEntityParametersSetterFunc = singleEntityFunc,
                    MultipleDataEntitiesParametersSetterFunc = multipleEntitiesFunc,
                    IdentityPropertySetterFunc = identitySetterFunc,
                    IdentityPropertySettersFunc = identitySettersFunc
                });
            });

            // Get the context
            var context = (InsertAllExecutionContext <TEntity>)null;

            // Identify the number of entities (performance), get an execution context from cache
            context = batchSize == 1 ? InsertAllExecutionContextCache <TEntity> .Get(tableName, fields, 1, callback) :
                      InsertAllExecutionContextCache <TEntity> .Get(tableName, fields, batchSize, callback);

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

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

            // Execution variables
            var result = 0;

            // Make sure to create transaction if there is no passed one
            var hasTransaction = (transaction != null);

            try
            {
                // Ensure the connection is open
                await connection.EnsureOpenAsync();

                if (hasTransaction == false)
                {
                    // Create a transaction
                    transaction = connection.BeginTransaction();
                }

                // Create the command
                using (var command = (DbCommand)connection.CreateCommand(context.CommandText,
                                                                         CommandType.Text, commandTimeout, transaction))
                {
                    // Directly execute if the entities is only 1 (performance)
                    if (context.BatchSize == 1)
                    {
                        foreach (var entity in entities)
                        {
                            // Set the values
                            context.SingleDataEntityParametersSetterFunc(command, entity);

                            // Actual Execution
                            var returnValue = ObjectConverter.DbNullToNull(await command.ExecuteScalarAsync());

                            // Set the return value
                            if (returnValue != null)
                            {
                                context.IdentityPropertySetterFunc?.Invoke(entity, returnValue);
                            }

                            // Iterate the result
                            result++;
                        }
                    }
                    else
                    {
                        foreach (var batchEntities in entities.Split(batchSize))
                        {
                            var batchItems = batchEntities.AsList();

                            // Break if there is no more records
                            if (batchItems.Count <= 0)
                            {
                                break;
                            }

                            // Check if the batch size has changed (probably the last batch on the enumerables)
                            if (batchItems.Count != batchSize)
                            {
                                // Get a new execution context from cache
                                context = InsertAllExecutionContextCache <TEntity> .Get(tableName, fields, batchItems.Count, callback);

                                // Set the command properties
                                command.CommandText = context.CommandText;

                                // Prepare the command
                                command.Prepare();
                            }

                            // Set the values
                            context.MultipleDataEntitiesParametersSetterFunc(command, batchItems);

                            // Actual Execution
                            result += await command.ExecuteNonQueryAsync();

                            // Set the identities
                            if (context.IdentityPropertySettersFunc != null && command.Parameters.Count > 0)
                            {
                                for (var index = 0; index < batchItems.Count; index++)
                                {
                                    var func = context.IdentityPropertySettersFunc.ElementAt(index);
                                    func(batchItems[index], command);
                                }
                            }
                        }
                    }
                }

                if (hasTransaction == false)
                {
                    // Commit the transaction
                    transaction.Commit();
                }
            }
            catch
            {
                if (hasTransaction == false)
                {
                    // Rollback for any exception
                    transaction.Rollback();
                }
                throw;
            }
            finally
            {
                if (hasTransaction == false)
                {
                    // Rollback and dispose the transaction
                    transaction.Dispose();
                }
            }

            // After Execution
            if (trace != null)
            {
                trace.AfterInsertAll(new TraceLog(context.CommandText, entities, result,
                                                  DateTime.UtcNow.Subtract(beforeExecutionTime)));
            }

            // Return the result
            return(result);
        }
Ejemplo n.º 24
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="connection"></param>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        /// <param name="qualifiers"></param>
        /// <param name="mappings"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="keepIdentity"></param>
        /// <param name="pseudoTableType"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        private static int BinaryBulkDeleteBase <TEntity>(this NpgsqlConnection connection,
                                                          string tableName,
                                                          IEnumerable <TEntity> entities,
                                                          IEnumerable <Field> qualifiers = null,
                                                          IEnumerable <NpgsqlBulkInsertMapItem> mappings = null,
                                                          int?bulkCopyTimeout = null,
                                                          int?batchSize       = null,
                                                          bool keepIdentity   = true,
                                                          BulkImportPseudoTableType pseudoTableType = default,
                                                          NpgsqlTransaction transaction             = null)
            where TEntity : class
        {
            var entityType       = entities?.First()?.GetType() ?? typeof(TEntity); // Solving the anonymous types
            var isDictionary     = entityType.IsDictionaryStringObject();
            var dbSetting        = connection.GetDbSetting();
            var dbFields         = DbFieldCache.Get(connection, tableName, transaction);
            var pseudoTableName  = tableName;
            var identityBehavior = keepIdentity ? BulkImportIdentityBehavior.KeepIdentity : BulkImportIdentityBehavior.Unspecified;

            return(PseudoBasedBinaryImport(connection,
                                           tableName,
                                           bulkCopyTimeout,
                                           dbFields,

                                           // getPseudoTableName
                                           () =>
                                           pseudoTableName = GetBinaryBulkDeletePseudoTableName(tableName ?? ClassMappedNameCache.Get <TEntity>(), dbSetting),

                                           // getMappings
                                           () =>
            {
                var includeIdentity = identityBehavior == BulkImportIdentityBehavior.KeepIdentity;
                var includePrimary = true;

                return mappings = mappings?.Any() == true ? mappings :
                                  isDictionary ?
                                  GetMappings(entities?.First() as IDictionary <string, object>,
                                              dbFields,
                                              includePrimary,
                                              includeIdentity,
                                              dbSetting) :
                                  GetMappings(dbFields,
                                              PropertyCache.Get(entityType),
                                              includePrimary,
                                              includeIdentity,
                                              dbSetting);
            },

                                           // binaryImport
                                           (tableName) =>
                                           connection.BinaryImport <TEntity>(tableName,
                                                                             entities,
                                                                             mappings,
                                                                             dbFields,
                                                                             bulkCopyTimeout,
                                                                             batchSize,
                                                                             identityBehavior,
                                                                             dbSetting,
                                                                             transaction),

                                           // getDeleteToPseudoCommandText
                                           () =>
                                           GetDeleteCommandText(pseudoTableName,
                                                                tableName,
                                                                mappings.Select(mapping => new Field(mapping.DestinationColumn)),
                                                                qualifiers,
                                                                dbFields.FirstOrDefault(dbField => dbField.IsPrimary)?.AsField(),
                                                                dbFields.FirstOrDefault(dbField => dbField.IsIdentity)?.AsField(),
                                                                identityBehavior,
                                                                dbSetting),

                                           // setIdentities
                                           (identityResults) =>
                                           SetIdentities(entityType, entities, dbFields, identityResults, dbSetting),

                                           qualifiers,
                                           false,
                                           identityBehavior,
                                           pseudoTableType,
                                           dbSetting,
                                           transaction));
        }
Ejemplo n.º 25
0
        /// <summary>
        ///
        /// </summary>
        /// <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="reader"></param>
        /// <param name="qualifiers"></param>
        /// <param name="mappings"></param>
        /// <param name="options"></param>
        /// <param name="hints"></param>
        /// <param name="bulkCopyTimeout"></param>
        /// <param name="batchSize"></param>
        /// <param name="usePhysicalPseudoTempTable"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        internal static int BulkUpdateInternalBase <TSqlBulkCopy, TSqlBulkCopyOptions, TSqlBulkCopyColumnMappingCollection,
                                                    TSqlBulkCopyColumnMapping, TSqlTransaction>(DbConnection connection,
                                                                                                string tableName,
                                                                                                DbDataReader reader,
                                                                                                IEnumerable <Field> qualifiers           = null,
                                                                                                IEnumerable <BulkInsertMapItem> mappings = null,
                                                                                                TSqlBulkCopyOptions options = default,
                                                                                                string hints                    = null,
                                                                                                int?bulkCopyTimeout             = null,
                                                                                                int?batchSize                   = null,
                                                                                                bool?usePhysicalPseudoTempTable = null,
                                                                                                TSqlTransaction transaction     = null)
            where TSqlBulkCopy : class, IDisposable
            where TSqlBulkCopyOptions : Enum
            where TSqlBulkCopyColumnMappingCollection : class
            where TSqlBulkCopyColumnMapping : class
            where TSqlTransaction : DbTransaction
        {
            // Validate
            ThrowIfNullOrEmpty(reader);

            // Variables
            var dbSetting      = connection.GetDbSetting();
            var hasTransaction = (transaction != null);
            var result         = default(int);

            // Check the transaction
            if (transaction == null)
            {
                // Add the transaction if not present
                transaction = (TSqlTransaction)connection.EnsureOpen().BeginTransaction();
            }
            else
            {
                // Validate the objects
                SqlConnectionExtension.ValidateTransactionConnectionObject(connection, transaction);
            }

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

            // Must be fixed name so the RepoDb.Core caches will not be bloated
            var tempTableName = string.Concat("_RepoDb_BulkUpdate_", GetTableName(tableName, dbSetting));

            // Add a # prefix if not physical
            if (usePhysicalPseudoTempTable != true)
            {
                tempTableName = string.Concat("#", tempTableName);
            }

            try
            {
                // Get the DB Fields
                var dbFields = DbFieldCache.Get(connection, tableName, transaction, true);

                // Variables needed
                var readerFields = Enumerable.Range(0, reader.FieldCount)
                                   .Select((index) => reader.GetName(index));
                var fields                   = dbFields?.Select(dbField => dbField.AsField());
                var primaryDbField           = dbFields?.FirstOrDefault(dbField => dbField.IsPrimary);
                var identityDbField          = dbFields?.FirstOrDefault(dbField => dbField.IsIdentity);
                var primaryOrIdentityDbField = (primaryDbField ?? identityDbField);

                // Validate the primary keys
                if (qualifiers?.Any() != true)
                {
                    if (primaryOrIdentityDbField == null)
                    {
                        throw new MissingPrimaryKeyException($"No primary key or identity key found for table '{tableName}'.");
                    }
                    else
                    {
                        qualifiers = new[] { primaryOrIdentityDbField.AsField() };
                    }
                }

                // Filter the fields (based on the data reader)
                if (readerFields?.Any() == true)
                {
                    fields = fields
                             .Where(e =>
                                    readerFields.Any(fieldName => string.Equals(fieldName, e.Name, StringComparison.OrdinalIgnoreCase)) == true);
                }

                // Filter the fields (based on the mappings)
                if (mappings?.Any() == true)
                {
                    fields = fields
                             .Where(e =>
                                    mappings.Any(m => string.Equals(m.SourceColumn, e.Name, StringComparison.OrdinalIgnoreCase)) == true);
                }

                // Throw an error if there are no fields
                if (fields?.Any() != true)
                {
                    throw new MissingFieldException("There are no field(s) found for this operation.");
                }

                // Create a temporary table
                var sql = GetCreateTemporaryTableSqlText(tableName,
                                                         tempTableName,
                                                         fields,
                                                         dbSetting);
                connection.ExecuteNonQuery(sql, transaction: transaction);

                // Set the options to KeepIdentity if needed
                if (object.Equals(options, default(TSqlBulkCopyOptions)) &&
                    identityDbField?.IsIdentity == true &&
                    qualifiers?.Any(
                        field => string.Equals(field.Name, identityDbField?.Name, StringComparison.OrdinalIgnoreCase)) == true &&
                    fields?.Any(
                        field => string.Equals(field.Name, identityDbField?.Name, StringComparison.OrdinalIgnoreCase)) == true)
                {
                    options = Compiler.GetEnumFunc <TSqlBulkCopyOptions>("KeepIdentity")();
                }

                // Filter the DB Fields
                var filteredDbFields = dbFields?
                                       .Where(dbField =>
                                              fields?.Any(field => string.Equals(field.Name, dbField.Name, StringComparison.OrdinalIgnoreCase)) == true);

                // Do the bulk insertion first
                BulkInsertInternalBase <TSqlBulkCopy, TSqlBulkCopyOptions, TSqlBulkCopyColumnMappingCollection,
                                        TSqlBulkCopyColumnMapping, TSqlTransaction>(connection,
                                                                                    tempTableName,
                                                                                    reader,
                                                                                    filteredDbFields,
                                                                                    mappings,
                                                                                    options,
                                                                                    null,
                                                                                    bulkCopyTimeout,
                                                                                    batchSize,
                                                                                    false,
                                                                                    false,
                                                                                    transaction);

                // Create the clustered index
                sql = GetCreateTemporaryTableClusteredIndexSqlText(tempTableName,
                                                                   qualifiers,
                                                                   dbSetting);
                connection.ExecuteNonQuery(sql, transaction: transaction);

                // Update the actual update
                sql = GetBulkUpdateSqlText(tableName,
                                           tempTableName,
                                           fields,
                                           qualifiers,
                                           primaryDbField?.AsField(),
                                           identityDbField?.AsField(),
                                           hints,
                                           dbSetting);
                result = connection.ExecuteNonQuery(sql, commandTimeout: bulkCopyTimeout, transaction: transaction);

                // Drop the table after used
                sql = GetDropTemporaryTableSqlText(tempTableName, dbSetting);
                connection.ExecuteNonQuery(sql, transaction: transaction);

                // Commit the transaction
                if (hasTransaction == false)
                {
                    transaction?.Commit();
                }
            }
            catch
            {
                // Rollback the transaction
                if (hasTransaction == false)
                {
                    transaction?.Rollback();
                }

                // Throw
                throw;
            }
            finally
            {
                // Dispose the transaction
                if (hasTransaction == false)
                {
                    transaction?.Dispose();
                }
            }

            // Result
            return(result);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Bulk insert an instance of <see cref="DataTable"/> object into the database.
        /// </summary>
        /// <param name="connection">The connection object to be used.</param>
        /// <param name="tableName">The target table for bulk-insert operation.</param>
        /// <param name="dataTable">The <see cref="DataTable"/> object to be used in the bulk-insert operation.</param>
        /// <param name="rowState">The state of the rows to be copied to the destination.</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>
        internal static int BulkInsertInternal(SqlConnection connection,
                                               string tableName,
                                               DataTable dataTable,
                                               DataRowState rowState = DataRowState.Unchanged,
                                               IEnumerable <BulkInsertMapItem> mappings = null,
                                               SqlBulkCopyOptions options = SqlBulkCopyOptions.Default,
                                               int?bulkCopyTimeout        = null,
                                               int?batchSize = null,
                                               SqlTransaction transaction = null)
        {
            // Validate the objects
            DbConnectionExtension.ValidateTransactionConnectionObject(connection, transaction);

            // Variables for the operation
            var result = 0;

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

            // Actual Execution
            using (var sqlBulkCopy = new SqlBulkCopy(connection, options, transaction))
            {
                // Set the destinationtable
                sqlBulkCopy.DestinationTableName = tableName;

                // Set the timeout
                if (bulkCopyTimeout != null && bulkCopyTimeout.HasValue)
                {
                    sqlBulkCopy.BulkCopyTimeout = bulkCopyTimeout.Value;
                }

                // Set the batch szie
                if (batchSize != null && batchSize.HasValue)
                {
                    sqlBulkCopy.BatchSize = batchSize.Value;
                }

                // Add the mappings
                if (mappings == null)
                {
                    // Variables needed
                    var dbSetting      = connection.GetDbSetting();
                    var dbFields       = DbFieldCache.Get(connection, tableName, transaction);
                    var fields         = GetDataColumns(dataTable).Select(column => column.ColumnName);
                    var filteredFields = new List <Tuple <string, string> >();

                    // To fix the casing problem of the bulk inserts
                    foreach (var dbField in dbFields)
                    {
                        var field = fields.FirstOrDefault(f =>
                                                          string.Equals(f.AsUnquoted(true, dbSetting), dbField.Name.AsUnquoted(true, dbSetting), StringComparison.OrdinalIgnoreCase));
                        if (field != null)
                        {
                            filteredFields.Add(new Tuple <string, string>(field, dbField.Name.AsUnquoted(true, dbSetting)));
                        }
                    }

                    // Iterate the filtered fields
                    foreach (var field in filteredFields)
                    {
                        sqlBulkCopy.ColumnMappings.Add(field.Item1, field.Item2);
                    }
                }
                else
                {
                    // Iterate the provided mappings
                    foreach (var mapItem in mappings)
                    {
                        sqlBulkCopy.ColumnMappings.Add(mapItem.SourceColumn, mapItem.DestinationColumn);
                    }
                }

                // Open the connection and do the operation
                connection.EnsureOpen();
                sqlBulkCopy.WriteToServer(dataTable, rowState);

                // Set the return value
                result = GetDataRows(dataTable, rowState).Count();
            }

            // Result
            return(result);
        }