我在我的项目中使用Dapper。我的项目包括3层。 API,业务和存储库层。
我想要用户异步查询dapper。
以下是每一层中的代码。
在存储库层
public Task<int> ChangeStatus(DriverStatus driverStatus)
{
using (IDbConnection connection = DapperConnection)
{
var updateQuery = @"UPDATE [dbo].[DriverLocation] Set [Latitude]=@Latitude, [Longitude]=@Longitude, [IsOnline]=@IsOnline Where [DriverId]=@DriverId";
return connection.ExecuteAsync(updateQuery, new
{
Latitude = driverStatus.Latitude,
Longitude = driverStatus.Longitude,
IsOnline = driverStatus.IsOnline,
DriverId = driverStatus.DriverId
});
}
}
现在我的业务层方法调用存储库方法。
public Task<int> ChangeStatus(DriverStatus driverStatus)
{
try
{
//Some Code here.
return driverRepository.ChangeStatus(driverStatus);
}
catch (Exception ex)
{
Logger.Error(ex);
return Task.FromResult<int>(0);
}
}
现在API方法调用业务层方法。
public async Task<IHttpActionResult> ChangeStatus(DriverStatus driverStatus)
{
ApiResponse apiResponse = new ApiResponse();
var isUpdated = await driverBl.ChangeStatus(driverStatus);
if(isUpdated > 0)
{
apiResponse.Message = "Driver status changed successfully.";
return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, apiResponse));
}
else
{
apiResponse.Message = "Driver status could not be changed.";
return ResponseMessage(Request.CreateResponse(HttpStatusCode.BadRequest, apiResponse));
}
}
因为我只在我的API方法中使用了await关键字,所以在返回结果之前我的连接对象可能被处理掉了,所以它让我误以为错误。
BeginExecuteNonQuery需要一个开放且可用的连接。该 连接的当前状态已关闭。
如何使用using
语句使用dapper的异步方法?
答案 0 :(得分:0)
使用async / await,您需要确保在整个调用堆栈中使用它。
您的回购图层应如下所示:
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
using (IDbConnection connection = DapperConnection)
{
var updateQuery = @"UPDATE [dbo].[DriverLocation] Set [Latitude]=@Latitude, [Longitude]=@Longitude, [IsOnline]=@IsOnline Where [DriverId]=@DriverId";
return await connection.ExecuteAsync(updateQuery, new
{
Latitude = driverStatus.Latitude,
Longitude = driverStatus.Longitude,
IsOnline = driverStatus.IsOnline,
DriverId = driverStatus.DriverId
});
}
}
你的BLL层应如下所示:
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
try
{
//Some Code here.
return await driverRepository.ChangeStatus(driverStatus);
}
catch (Exception ex)
{
Logger.Error(ex);
return 0;
}
}
答案 1 :(得分:0)
您的问题是您在存储库层中省略了异步并等待使用,并且当它与using语句结合使用时,它将导致不可预测的行为。
当您调用connection.ExecuteAsync时,您启动了一个依赖于连接的任务,因此连接必须保持打开状态,并且只要任务未完成就不应该处理。
在你的情况下,你在启动任务后立即返回并立即处理连接(因为你有一个using语句,一旦连接超出范围就会处理连接),所有这一切都发生在任务之前已经完成了。
为了防止在任务完成之前处理连接,您需要以异步方式等待&#34;使用async和await关键字的操作,并且仅在await返回方法的结果之后。
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
using (IDbConnection connection = DapperConnection)
{
var updateQuery = @"UPDATE [dbo].[DriverLocation] Set [Latitude]=@Latitude, [Longitude]=@Longitude, [IsOnline]=@IsOnline Where [DriverId]=@DriverId";
return await connection.ExecuteAsync(updateQuery, new
{
Latitude = driverStatus.Latitude,
Longitude = driverStatus.Longitude,
IsOnline = driverStatus.IsOnline,
DriverId = driverStatus.DriverId
});
}
}
有关Eliding Async and Await Stephen Cleary博客文章中有关该主题的更多信息。
您还有一个错误,在您的业务层中,您的try catch块无法正常工作,以便从您拥有to block or await it的异步方法中捕获异常:
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
try
{
//Some Code here.
return await driverRepository.ChangeStatus(driverStatus);
}
catch (Exception ex)
{
Logger.Error(ex);
return 0;
}
}
最后一件与此无关的事情是,在业务层吞下例外并向上层做出错误陈述真的是一个好主意吗?