2

我注意到在 Dapper.NET 中使用异步 API 时,我在扩展方法中传递的命令超时值不受尊重。然后我遇到了 SqlCommand.CommandTimeout 的MSDN 文档,这似乎是它不“支持”的东西。

在异步方法调用(例如 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 在超时间隔内断开连接和处理连接?

4

2 回答 2

1

令人烦恼的是 SqlClient 自己处理这个问题!但是,我想知道您是否可以做一些涉及:

  • 您传递给 dapper 的取消令牌(它接受它们)
  • 使用超时调用 Task.Delay
  • 调用 Task.WhenAny 传入 dapper 任务和延迟任务
  • 检查哪个从WhenAny返回-如果是延迟,则发出取消信号并抛出您自己的超时
  • 确保任何由取消引起的异常都得到干净的处理

有点难看,如果数据库提供者不打算本地尊重超时,也许这是库应该封装的东西。可能还需要额外的步骤来彻底取消运行中的命令,在这种情况下,可能只有库可以正确执行此操作(因为只有库有权访问该命令)

于 2017-12-25T10:03:45.197 回答
0

这是从当前版本的 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;
    }

在此处输入图像描述

于 2017-12-25T09:52:56.877 回答