Если вы проверите исходный код , вы увидите, что ваши подозрения почти верны. Когда buffered
ложно, QueryAsync
будет передавать синхронно .
if (command.Buffered)
{
var buffer = new List<T>();
var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
object val = func(reader);
if (val == null || val is T)
{
buffer.Add((T)val);
}
else
{
buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
}
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
Как поясняется в комментарии, невозможно использовать ReadAsync
, когда ожидается, что тип возвращаемого значения будет IEnumerable. Вот почему должны были быть введены асинхронные перечислители C # 8.
Код для ExecuteReaderSync:
private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDataReader, object> func, object parameters)
{
using (reader)
{
while (reader.Read())
{
yield return (T)func(reader);
}
while (reader.NextResult()) { /* ignore subsequent result sets */ }
(parameters as IParameterCallbacks)?.OnCompleted();
}
}
Используется Read
вместо ReadAsync
.
C # 8 асинхронные потоки позволят переписать это, чтобы вернуть IAsyncEnumerable
. Простое изменение языковой версии не решит проблему.
С учетом текущей документации по асинхронным потокам это может выглядеть следующим образом:
private static async IAsyncEnumerable<T> ExecuteReaderASync<T>(IDataReader reader, Func<IDataReader, object> func, object parameters)
{
using (reader)
{
while (await reader.ReadAsync())
{
yield return (T)func(reader);
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
command.OnCompleted();
(parameters as IParameterCallbacks)?.OnCompleted();
}
}
Buuuuuut асинхронные потоки - это одна из вещей, которая может работать только на .NET Core и, вероятно, еще не реализована. Когда я пытался написать один в Sharplab.io, Kaboom. [connection lost, reconnecting…]