C# using语句内部的Dapper异步查询需要一个开放的可用连接
我正在我的项目中使用。我的项目由3层组成。API、业务和存储库层 我希望用户异步查询dapper 下面是每一层的代码 存储库层C# using语句内部的Dapper异步查询需要一个开放的可用连接,c#,asp.net,asynchronous,asp.net-web-api,dapper,C#,Asp.net,Asynchronous,Asp.net Web Api,Dapper,我正在我的项目中使用。我的项目由3层组成。API、业务和存储库层 我希望用户异步查询dapper 下面是每一层的代码 存储库层 public Task<int> ChangeStatus(DriverStatus driverStatus) { using (IDbConnection connection = DapperConnection) { var updateQuery = @
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
});
}
}
公共任务更改状态(DriverStatus DriverStatus)
{
使用(IDbConnection=DAPPonnection)
{
var updateQuery=@“更新[dbo].[DriverLocation]设置[Latitude]=@Latitude,[Latitude]=@Latitude,[IsOnline]=@IsOnline,其中[DriverId]=@DriverId”;
返回连接.ExecuteAsync(updateQuery,新建
{
纬度=驾驶员状态。纬度,
经度=驾驶员状态。经度,
IsOnline=driverStatus.IsOnline,
driverrid=driverStatus.driverrid
});
}
}
现在我的业务层方法调用上述存储库方法
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);
}
}
公共任务更改状态(DriverStatus DriverStatus)
{
尝试
{
//这里有一些代码。
返回DriverReplicatory.ChangeStatus(driverStatus);
}
捕获(例外情况除外)
{
记录器错误(ex);
返回Task.FromResult(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));
}
}
公共异步任务更改状态(DriverStatus DriverStatus)
{
ApiResponse ApiResponse=新的ApiResponse();
var isUpdated=等待驱动程序bl.ChangeStatus(驱动程序状态);
如果(IsUpdate>0)
{
apiResponse.Message=“驱动程序状态已成功更改。”;
返回响应消息(Request.CreateResponse(HttpStatusCode.OK,apiResponse));
}
其他的
{
apiResponse.Message=“无法更改驱动程序状态。”;
返回ResponseMessage(Request.CreateResponse(HttpStatusCode.BadRequest,apiResponse));
}
}
由于我只在API方法中使用了wait关键字,所以我的连接对象可能在返回结果之前就被处理掉了,所以它将我抛出下面的错误
BeginExecutenQuery需要一个开放且可用的连接。这个
连接的当前状态为关闭
如何使用
和语句使用dapper的异步方法?使用async/wait,您需要确保在整个调用堆栈中都使用它
您的回购层应如下所示:
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
});
}
}
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
try
{
//Some Code here.
return await driverRepository.ChangeStatus(driverStatus);
}
catch (Exception ex)
{
Logger.Error(ex);
return 0;
}
}
公共异步任务更改状态(DriverStatus DriverStatus)
{
使用(IDbConnection=DAPPonnection)
{
var updateQuery=@“更新[dbo].[DriverLocation]设置[Latitude]=@Latitude,[Latitude]=@Latitude,[IsOnline]=@IsOnline,其中[DriverId]=@DriverId”;
return wait connection.ExecuteAsync(updateQuery,new
{
纬度=驾驶员状态。纬度,
经度=驾驶员状态。经度,
IsOnline=driverStatus.IsOnline,
driverrid=driverStatus.driverrid
});
}
}
您的BLL层应该如下所示:
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
});
}
}
public async Task<int> ChangeStatus(DriverStatus driverStatus)
{
try
{
//Some Code here.
return await driverRepository.ChangeStatus(driverStatus);
}
catch (Exception ex)
{
Logger.Error(ex);
return 0;
}
}
公共异步任务更改状态(DriverStatus DriverStatus)
{
尝试
{
//这里有一些代码。
返回等待驾驶员返回。更改状态(驾驶员状态);
}
捕获(例外情况除外)
{
记录器错误(ex);
返回0;
}
}
您的问题是您忽略了async并在存储库层中等待使用,当这与using语句结合使用时,将导致不可预测的行为。
调用connection.ExecuteAsync时,您启动了一个依赖于该连接的任务,因此该连接必须保持打开状态,只要该任务未完成,就不应释放该连接。
在您的情况下,您在启动任务后立即返回,并且正在立即处理连接(因为您有一个using语句,该语句将在连接超出范围时立即处理连接),所有这些都发生在任务完成之前。
为了防止在任务完成之前处理连接,您需要使用async和wait关键字“以异步方式等待”操作,并且仅在wait之后从方法返回结果
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
});
}
}
公共异步任务更改状态(DriverStatus DriverStatus)
{
使用(IDbConnection=DAPPonnection)
{
var updateQuery=@“更新[dbo].[DriverLocation]设置[Latitude]=@Latitude,[Latitude]=@Latitude,[IsOnline]=@IsOnline,其中[DriverId]=@DriverId”;
return wait connection.ExecuteAsync(updateQuery,new
{
纬度=驾驶员状态。纬度,
经度=驾驶员状态。经度,
IsOnline=driverStatus.IsOnline,
driverrid=driverStatus.driverrid
});
}
}
有关该主题的更多信息,请参阅Stephen Cleary的博客文章。
您还有一个错误,在您的业务层中,您的try-catch块未按预期工作,以便从您拥有的异步方法捕获异常:
公共异步任务更改状态(DriverStatus DriverStatus)
{
尝试
{
//这里有一些代码。
返回等待驾驶员返回。更改状态(驾驶员状态);
}
捕获(例外情况除外)
{
记录器错误(ex);
返回0;
}
}
最后一件不相关的事情是,在业务层吞下异常并向上层做出错误陈述真的是一个好主意吗?在调用过程中,您应该始终使用async
。@maccettura:然后我必须在API、业务和服务的所有三个位置等待关键字。是吗?是的,这就是async
/等待的方式
works@maccettura:对不起,我不是异步概念方面的专家。但是如果使用awa