使用Dapper.NET异步API时如何尊重CommandTimeout
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Dapper.NET异步API时如何尊重CommandTimeout相关的知识,希望对你有一定的参考价值。
我注意到在Dapper.NET中使用异步API时,我不会遵守在扩展方法中传递的命令超时值。然后我遇到了SqlCommand.CommandTimeout的MSDN documentation,似乎这不是“支持”的东西。
在诸如BeginExecuteReader之类的异步方法调用期间,将忽略CommandTimeout属性。
我在基类中使用以下方法。
public async Task<int> ExecuteAsync(string sql, object param = null,
CommandType commandType = CommandType.Text, int? commandTimeout = null, IDbTransaction transaction = null)
{
using (var connection = Connection)
{
Task<int> queryTask = connection.ExecuteAsync(sql, param, transaction, commandTimeout ?? CommandTimeoutDefault, commandType);
int result = await queryTask.ConfigureAwait(false);
connection.Close();
connection.Dispose();
return result;
}
}
public async Task<IEnumerable<TEntity>> QueryAsync(string sql, object param = null,
CommandType commandType = CommandType.Text, int? commandTimeout = null, IDbTransaction transaction = null)
{
using (var connection = Connection)
{
Task<IEnumerable<TEntity>> queryTask = connection.QueryAsync<TEntity>(sql, param, transaction, commandTimeout ?? CommandTimeoutDefault, commandType);
IEnumerable<TEntity> data = await queryTask.ConfigureAwait(false);
connection.Close();
connection.Dispose();
return data;
}
}
假设CommandTimeoutDefault
是30,我可以得到一个50秒的请求仍将被评估。
有没有想过如何使用异步Dapper.NET API在超时间隔内断开连接并处理连接?
答案
这是一个在当前版本的Dapper中从异步方法调用的函数。正如您所看到的那样,CommandTimeout足够受到尊重。
internal IDbCommand SetupCommand(IDbConnection cnn, Action<IDbCommand, object> paramReader)
{
IDbCommand command = cnn.CreateCommand();
Action<IDbCommand> init = CommandDefinition.GetInit(command.GetType());
if (init != null)
init(command);
if (this.Transaction != null)
command.Transaction = this.Transaction;
command.CommandText = this.CommandText;
if (this.CommandTimeout.HasValue)
{
command.CommandTimeout = this.CommandTimeout.Value;
}
else
{
int? commandTimeout = SqlMapper.Settings.CommandTimeout;
if (commandTimeout.HasValue)
{
IDbCommand dbCommand = command;
commandTimeout = SqlMapper.Settings.CommandTimeout;
int num = commandTimeout.Value;
dbCommand.CommandTimeout = num;
}
}
System.Data.CommandType? commandType = this.CommandType;
if (commandType.HasValue)
{
IDbCommand dbCommand = command;
commandType = this.CommandType;
int num = (int) commandType.Value;
dbCommand.CommandType = (System.Data.CommandType) num;
}
if (paramReader != null)
paramReader(command, this.Parameters);
return command;
}
另一答案
令人烦恼的是,SqlClient确实处理了这个问题!但是,我想知道你是否可以做一些涉及的事情:
- 你传递给dapper的取消令牌(它接受它们)
- 使用超时调用Task.Delay
- 调用Task.WhenAny传递dapper任务和延迟任务
- 检查从WhenAny返回的内容 - 如果是延迟,则发出取消信号并抛出自己的超时
- 确保取消导致的任何例外情况得到妥善处理
稍微丑陋,如果数据库提供程序本身不尊重超时,这可能是库应该封装的东西。干净地取消正在运行的命令可能还需要其他步骤,在这种情况下,可能只有库才能正确执行此操作(因为只有库可以访问该命令)
以上是关于使用Dapper.NET异步API时如何尊重CommandTimeout的主要内容,如果未能解决你的问题,请参考以下文章