Exemple #1
0
        /// <summary>
        /// Inserts entities into table <typeparamref name="T"/>s (by default) returns inserted entities.
        /// </summary>
        /// <typeparam name="T">The element type of the array</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="data">Entities to insert</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="batchSize">Number of bulk items inserted together, 0 (the default) if all</param>
        /// <param name="bulkCopyTimeout">Number of seconds before bulk command execution timeout, 30 (the default)</param>
        /// <returns>Inserted entities</returns>
        public static IEnumerable <T> BulkInsertAndSelect <T>(this SqlConnection connection, IEnumerable <T> data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30)
        {
            var type               = typeof(T);
            var tableName          = TableMapper.GetTableName(type);
            var allProperties      = PropertiesCache.TypePropertiesCache(type);
            var keyProperties      = PropertiesCache.KeyPropertiesCache(type);
            var computedProperties = PropertiesCache.ComputedPropertiesCache(type);
            var columns            = PropertiesCache.NewColumnNamesCache(type);

            if (keyProperties.Count == 0)
            {
                var dataList = data.ToList();
                connection.BulkInsert(dataList, transaction, batchSize, bulkCopyTimeout);
                return(dataList);
            }

            var allPropertiesExceptKeyAndComputed = allProperties.Except(keyProperties.Union(computedProperties)).ToList();

            var keyPropertiesString                     = GetColumnsStringSqlServer(keyProperties, columns);
            var keyPropertiesInsertedString             = GetColumnsStringSqlServer(keyProperties, columns, "inserted.");
            var allPropertiesExceptKeyAndComputedString = GetColumnsStringSqlServer(allPropertiesExceptKeyAndComputed, columns);
            var allPropertiesString                     = GetColumnsStringSqlServer(allProperties, columns, "target.");

            var tempToBeInserted         = $"#{tableName}_TempInsert".Replace(".", string.Empty);
            var tempInsertedWithIdentity = $"@{tableName}_TempInserted".Replace(".", string.Empty);

            connection.Execute($"SELECT TOP 0 {allPropertiesExceptKeyAndComputedString} INTO {tempToBeInserted} FROM {tableName} target WITH(NOLOCK);", null, transaction);

            using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
            {
                bulkCopy.BulkCopyTimeout      = bulkCopyTimeout;
                bulkCopy.BatchSize            = batchSize;
                bulkCopy.DestinationTableName = tempToBeInserted;
                bulkCopy.WriteToServer(ToDataTable(data, tableName, allPropertiesExceptKeyAndComputed).CreateDataReader());
            }

            var table  = string.Join(", ", keyProperties.Select(k => $"[{k.Name }] bigint"));
            var joinOn = string.Join(" AND ", keyProperties.Select(k => $"target.[{k.Name }] = ins.[{k.Name }]"));

            return(connection.Query <T>($@"
                DECLARE {tempInsertedWithIdentity} TABLE ({table})
                INSERT INTO {tableName}({allPropertiesExceptKeyAndComputedString}) 
                OUTPUT {keyPropertiesInsertedString} INTO {tempInsertedWithIdentity} ({keyPropertiesString})
                SELECT {allPropertiesExceptKeyAndComputedString} FROM {tempToBeInserted}

                SELECT {allPropertiesString}
                FROM {tableName} target INNER JOIN {tempInsertedWithIdentity} ins ON {joinOn}

                DROP TABLE {tempToBeInserted};", null, transaction));
        }
Exemple #2
0
        /// <summary>
        /// Inserts entities into table <typeparamref name="T"/>s (by default) asynchronously.
        /// </summary>
        /// <typeparam name="T">The type being inserted.</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="data">Entities to insert</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="batchSize">Number of bulk items inserted together, 0 (the default) if all</param>
        /// <param name="bulkCopyTimeout">Number of seconds before bulk command execution timeout, 30 (the default)</param>
        /// <param name="identityInsert">Usage of db generated ids. By default DB generated IDs are used (identityInsert=false)</param>
        public static async Task BulkInsertAsync <T>(this SqlConnection connection, IEnumerable <T> data, SqlTransaction transaction = null, int batchSize = 0, int bulkCopyTimeout = 30, bool identityInsert = false)
        {
            var type               = typeof(T);
            var tableName          = TableMapper.GetTableName(type);
            var allProperties      = PropertiesCache.TypePropertiesCache(type);
            var keyProperties      = PropertiesCache.KeyPropertiesCache(type);
            var computedProperties = PropertiesCache.ComputedPropertiesCache(type);
            var columns            = PropertiesCache.GetColumnNamesCache(type);

            var insertProperties = allProperties.Except(computedProperties).ToList();

            if (!identityInsert)
            {
                insertProperties = insertProperties.Except(keyProperties).ToList();
            }

            var(identityInsertOn, identityInsertOff, sqlBulkCopyOptions) = GetIdentityInsertOptions(identityInsert, tableName);

            var insertPropertiesString = GetColumnsStringSqlServer(insertProperties, columns);
            var tempToBeInserted       = $"#TempInsert_{tableName}".Replace(".", string.Empty);

            await connection.ExecuteAsync($@"SELECT TOP 0 {insertPropertiesString} INTO {tempToBeInserted} FROM {FormatTableName(tableName)} target WITH(NOLOCK);", null, transaction);

            using (var bulkCopy = new SqlBulkCopy(connection, sqlBulkCopyOptions, transaction))
            {
                bulkCopy.BulkCopyTimeout      = bulkCopyTimeout;
                bulkCopy.BatchSize            = batchSize;
                bulkCopy.DestinationTableName = tempToBeInserted;
                await bulkCopy.WriteToServerAsync(ToDataTable(data, insertProperties).CreateDataReader());
            }

            await connection.ExecuteAsync($@"
                {identityInsertOn}
                INSERT INTO {FormatTableName(tableName)}({insertPropertiesString}) 
                SELECT {insertPropertiesString} FROM {tempToBeInserted}
                {identityInsertOff}

                DROP TABLE {tempToBeInserted};", null, transaction);
        }