异步SQL批量复制和批量选择

时间:2014-09-15 11:35:18

标签: .net sql-server

以下代码无法正常工作(抛出#34;致读者的致命错误.NextResult()")

我的目标是执行批量选择,然后通过批量复制插入每个结果集async的数据。

我认为问题在于reader.NextResult()当前结果集是从内存中释放的,但由于异步批量操作正在使用它,因此会抛出致命错误(InvalidOperationException)。有什么想法吗?

                    var sqlQuery = new DbExtensions.SqlBuilder();
                    foreach (var table in tableBatch)
                    {
                        sqlQuery
                            .SELECT("*")
                            .FROM("[" + table.TableName + "]");
                    }

                    var selectCmd = sqlQuery.ToCommand(clientDb);

                    logger.Info("Executing select", batchSelectSize);
                    var reader = selectCmd.ExecuteReader();

                    var i = 0;
                    while (reader.HasRows)
                    {
                        logger.Info("Bulk insert");
                        var table = tableBatch.ElementAt(i);
                        var bulkCopy = new SqlBulkCopy(serverDb, SqlBulkCopyOptions.Default, tx);
                        bulkCopy.DestinationTableName = String.Format("[{0}]", table.TableName);
                        bulkCopy.EnableStreaming = table.EnableStreaming;                            
                        bulkCopy.WriteToServerAsync(reader);

                        i++;

                        reader.NextResult(); // fatal error occures (sometimes)
                    }

                    logger.Info("Waiting for bulk operations to complete");
                    Task.WaitAll();

                    logger.Info("Committing transaction");
                    tx.Commit();

2 个答案:

答案 0 :(得分:2)

是的,你没有await结果;你过早地前进了。那应该是:

await bulkCopy.WriteToServerAsync(reader);

await bulkCopy.WriteToServerAsync(reader).ConfigureAwait(false);

另请注意Task.WaitAll()没有任何用处;你说"现在等待完成这些任务的所有零"。

另请注意,如果您要async,那么您可以在async进行整个过程:

var reader = await selectCmd.ExecuteReaderAsync();
...
await bulkCopy.WriteToServerAsync(reader);
...
await reader.NextResultAsync();

(如果需要的话,也许每个都有.ConfigureAwait(false)

答案 1 :(得分:1)

是。您必须推迟NextResult,直到您确定WriteToServerAsync已完成其工作为止。正确执行此操作的最简单方法是使包含方法成为async方法,并await WriteToServerAsync,如下所示:

await bulkCopy.WriteToServerAsync(reader);

有关asyncawait的详情,请参阅async/await tutorials like this one from dotnetperls和/或Microsoft's own documentation