使用异步ADO.NET调用填充数据集会引发InvalidOperationException



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

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

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

我不理解这一点,因为读取器被部署在调用NextResultAsync的循环之外。

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

在我看来,读者被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不使用异步方法。

最新更新