【发布时间】:2014-07-03 18:34:05
【问题描述】:
我正在编写一个简单的类,它将连接到 SQL DB 并从中获取数据。
我想让它异步,但我在异步编程方面遇到了一些问题。
代码:
public async Task<ICommand> ExecuteAsync(SqlConnection connection)
{
var cmd = new SqlCommand(Query);
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
if(connection.State != ConnectionState.Open)
await connection.OpenAsync();
using (SqlDataReader sqlDataReader = await cmd.ExecuteReaderAsync())
{
if (sqlDataReader.HasRows)
{
while (await sqlDataReader.ReadAsync())
{
Entry = new Entry();
Entry.ID = (int) sqlDataReader["ID"];
Entry.User = (string) sqlDataReader["UserName"];
object o = sqlDataReader["EntryType"];
Entry.EntryType = o.Equals("Enter") ? EntryType.Enter : EntryType.Leave;
Entry.DateTime = (DateTime) sqlDataReader["EntryDate"];
}
}
}
使用此代码,调试器总是在 OpenAsync() 方法之后停止执行。它没有命中下一条语句。
你能告诉我我做错了什么吗?
问候
--编辑-- 我现在正在桌面上运行它(简单单元测试) 我添加了 try-catch 来处理异常。
我的最小样本:
ExecuteAsync 方法:
public async Task<ICommand> ExecuteAsync(SqlConnection connection)
{
var cmd = new SqlCommand(Query);
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
if(connection.State != ConnectionState.Open)
await connection.OpenAsync().ConfigureAwait(false);
using (SqlDataReader sqlDataReader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
{
if (sqlDataReader.HasRows)
{
while (await sqlDataReader.ReadAsync().ConfigureAwait(false))
{
Entry = new Entry();
Entry.ID = (int) sqlDataReader["ID"];
// Entry.User = (string) sqlDataReader["UserName"]; // 对象 o = sqlDataReader["EntryType"]; // Entry.EntryType = o.Equals("Enter") ? EntryType.Enter:EntryType.Leave; // Entry.DateTime = (DateTime) sqlDataReader["EntryDate"]; } } } 返回这个; }
调用此方法:
public void ExecuteCommandAsync(ICommand command, ReadFinished continueWith)
{
if(continueWith == null)
throw new NullReferenceException("Parameter 'continueWith' cannot be null");
command.ExecuteAsync(_connection).ContinueWith(task => continueWith(task.Result)).ConfigureAwait(false);
}
我的测试用例:
public void TestMethod1()
{
TimeTableDBConnector.DbConnector connector = new DbConnector(null);
var getEntryByIDCommand = new GetEntryByIDCommand(1);
ICommand result;
try
{
connector.ExecuteCommandAsync(getEntryByIDCommand, ContinueWith );
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private void ContinueWith(ICommand command)
{
GetEntryCommand cmd = (GetEntryCommand) command;
}
【问题讨论】:
-
这个 sn-p 看起来不错。当您使用
connection.Open()而不是connection.OpenAsync()时,连接是否有效?您是在桌面应用程序还是在服务(或 Web 应用程序)中执行此操作?您能否将其缩减为显示此行为的最小完整示例应用程序?是否有可能抛出异常而您没有正确处理? -
用更多代码查看我的编辑。此外,相同的代码,没有异步也能完美运行
-
@Tomasz,删除了我的答案,因为已经发布了更多详细信息。单元测试不使用
SynchronizationContext,所以我的回答不适用。 -
尝试这样称呼它 -
command.ExecuteAsync(...).Wait()。您不能在单元测试中触发并忘记异步任务 - 很可能,一旦您退出TestMethod1,测试就会停止。在获得异步响应之前,您必须在 某处 进行阻塞。 -
谢谢,等待方法帮助
标签: c# async-await sqldatareader