使用异步 ADO.NET 调用填充数据集会抛出 InvalidOperationException

Filling a DataSet using asynchronous ADO.NET calls throws InvalidOperationException

我希望能够使用 .NET 4.5+ 异步 ADO.NET 方法,用可能 return 多个结果集的查询结果填充数据集。我正在使用的代码如下。当我 运行 代码时,我看到前两个 table 已成功填充 - 以下内容输出到控制台:

Table Table1 loaded with 1 row(s)
Table Table2 loaded with 1 row(s)

然后在第三个table被填充之前,我得到一个System.InvalidOperationException : Invalid attempt to call NextResultAsync when reader is closed

我不明白这一点,因为 reader 位于调用 NextResultAsync 的循环之外。

我使用的是 Visual Studio 2017,LocalDB @@VERSION 是 "Microsoft SQL Server 2016 (SP1) (KB3182545) - 13.0.4001.0 ..."(在连接字符串中不使用 Asynchronous Processing 关键字)。

在我看来 reader 被 DataTable.Load 关闭了 - 但为什么呢?为什么在第二个循环而不是第一个?

谁能告诉我我做错了什么?

[Test]
public void RunTestQuery()
{
    const string QueryText = @"
DECLARE @Table1 TABLE (Col1 VARCHAR(50))
DECLARE @Table2 TABLE (Col1 VARCHAR(50))
DECLARE @Table3 TABLE (Col1 VARCHAR(50))

INSERT INTO @Table1 VALUES ('T1Value')
INSERT INTO @Table2 VALUES ('T2Value')
INSERT INTO @Table3 VALUES ('T3Value')

SELECT * FROM @Table1
SELECT * FROM @Table2
SELECT * FROM @Table3
";
    var dataSet = GetDataSet(QueryText).Result;
    Assert.AreEqual(3, dataSet.Tables.Count);
}

private async Task<DataSet> GetDataSet(string commandText)
{
    DataSet dataSet = new DataSet();

    using (var connection = new System.Data.SqlClient.SqlConnection())
    {
        connection.ConnectionString = @"Server=(LocalDB)\MSSQLLocalDB;Trusted_Connection=True";
        await connection.OpenAsync();
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = commandText;
            using (var reader = await command.ExecuteReaderAsync())
            {
                do
                {
                    var table = dataSet.Tables.Add();
                    table.Load(reader);
                    Console.WriteLine($"Table {table.TableName} loaded with {table.Rows.Count} row(s)");
                } while (await reader.NextResultAsync());
            }
        }
        return dataSet;
    }
}

我看过 DataTable.Load 方法,有问题的代码是:

...
loadAdapter.FillFromReader(new DataTable[]
{
    this
}, reader, 0, 0);
if (!reader.IsClosed && !reader.NextResult())
{
    reader.Close();
}
...

DataTable.Load 在内部调用 reader.NextResult,因此不能在调用 reader.NextResult[Async].

的循环中使用

所以我必须编写自定义方法来填充 DataTable,这可能是更好的解决方案,因为 DataTable.Load 不使用异步方法。