Parallel.Foreach and BulkCopy

parallel-foreach sqlbulkcopy

Question

I have a C# library which connects to 59 servers of the same database structure and imports data to my local db to the same table. At this moment I am retrieving data server by server in foreach loop:

foreach (var systemDto in systems)
{
    var sourceConnectionString = _systemService.GetConnectionStringAsync(systemDto.Ip).Result;
    var dbConnectionFactory = new DbConnectionFactory(sourceConnectionString,
        "System.Data.SqlClient");
    var dbContext = new DbContext(dbConnectionFactory);
    var storageRepository = new StorageRepository(dbContext);
    var usedStorage = storageRepository.GetUsedStorageForCurrentMonth();

    var dtUsedStorage = new DataTable();
    dtUsedStorage.Load(usedStorage);
    var dcIp = new DataColumn("IP", typeof(string)) {DefaultValue = systemDto.Ip};
    var dcBatchDateTime = new DataColumn("BatchDateTime", typeof(string))
    {
        DefaultValue = batchDateTime
    };
    dtUsedStorage.Columns.Add(dcIp);
    dtUsedStorage.Columns.Add(dcBatchDateTime);

    using (var blkCopy = new SqlBulkCopy(destinationConnectionString))
    {
        blkCopy.DestinationTableName = "dbo.tbl";
        blkCopy.WriteToServer(dtUsedStorage);
    }
}

Because there are many systems to retrieve data, I wonder if it is possible to use Pararel.Foreach loop? Will BulkCopy lock the table during WriteToServer and next WriteToServer will wait until previous will complete?

-- EDIT 1

I've changed Foreach to Parallel.Foreach but I face one problem. Inside this loop I have async method: _systemService.GetConnectionStringAsync(systemDto.Ip) and this line returns error:

System.NotSupportedException: A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

Any ideas how can I handle this?

Expert Answer

In general, it will get blocked and will wait until the previous operation complete.

There are some factors that may affect if SqlBulkCopy can be run in parallel or not.

I remember when adding the Parallel feature to my .NET Bulk Operations, I had hard time to make it work correctly in parallel but that worked well when the table has no index (which is likely never the case)

Even when worked, the performance gain was not a lot faster.

Perhaps you will find more information here: MSDN - Importing Data in Parallel with Table Level Locking



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why