Заполнение DataSet с использованием асинхронных вызовов ADO. NET вызывает InvalidOperationException - PullRequest
0 голосов
/ 26 марта 2020

Я хочу иметь возможность заполнять DataSet результатами запроса, который может возвращать несколько наборов результатов, используя асинхронный метод ADO. NET 4.5+. 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.

Я не понимаю этого, так как читатель расположен вне l oop, который вызывает NextResultAsyn c.

Я использую Visual Studio 2017 и LocalDB @@ VERSION is " Microsoft SQL Server 2016 (SP1) (KB3182545) - 13.0.4001.0 ... "(не использует ключевое слово Asynchronous Processing в строке подключения).

Мне кажется, что читатель закрыт DataTable.Load - но почему? и почему на втором oop, а не на первом?

Может кто-нибудь сказать мне, что я делаю не так?

[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;
    }
}

1 Ответ

0 голосов
/ 28 марта 2020

Я посмотрел на метод DataTable.Load, и код ошибки:

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

Т.е. DataTable.Load внутренне вызывает reader.NextResult, поэтому его нельзя использовать в oop который вызывает reader.NextResult[Async].

Так что мне придется написать собственный метод для заполнения DataTable, что, вероятно, будет лучшим решением, поскольку DataTable.Load не использует асин c методы .

...