请看以下两种方法。第一个返回 IAsyncEnumerable
。第二个尝试消耗它。
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
public static class SqlUtility
{
public static async IAsyncEnumerable<IDataRecord> GetRecordsAsync(
string connectionString, SqlParameter[] parameters, string commandText,
[EnumeratorCancellation]CancellationToken cancellationToken)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.Parameters.AddRange(parameters);
using (var reader = await command.ExecuteReaderAsync()
.ConfigureAwait(false))
{
while (await reader.ReadAsync().ConfigureAwait(false))
{
yield return reader;
}
}
}
}
}
public static async Task Example()
{
const string connectionString =
"Server=localhost;Database=[Redacted];Integrated Security=true";
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("VideoID", SqlDbType.Int) { Value = 1000 }
};
const string commandText = "select * from Video where VideoID=@VideoID";
IAsyncEnumerable<IDataRecord> records = GetRecordsAsync(connectionString,
parameters, commandText, CancellationToken.None);
IDataRecord firstRecord = await records.FirstAsync().ConfigureAwait(false);
object videoID = firstRecord["VideoID"]; //Should be 1000.
// Instead, I get this exception:
// "Invalid attempt to call MetaData when reader is closed."
}
}
当代码尝试读取结果 IDataReader
(在 object videoID = firstRecord["VideoID"];
)时,我得到这个异常:
Invalid attempt to call MetaData when reader is closed.
这是因为 SqlDataReader
被释放了。有人可以提供推荐的方法以异步方式枚举 SqlDataReader
以便每个结果记录都可用于调用方法吗?谢谢。
最佳答案
在这种情况下,LINQ 不是你的 friend ,因为 FirstAsync
将在迭代器 返回结果之前关闭迭代器,这不是 ADO.NET 所期望的;基本上:不要在这里使用 LINQ,或者至少:不要以这种方式使用。您可以使用 Select
之类的东西在序列仍然打开时执行投影,或者将此处的所有工作卸载到类似的工具可能更容易小巧玲珑。或者,手动执行:
await foreach (var record in records)
{
// TODO: process record
// (perhaps "break"), because you only want the first
}
关于c# - 如何使用 SqlDataReader 返回和使用 IAsyncEnumerable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58825715/