【问题标题】:Asynchronus methods in .net core api.net core api 中的异步方法
【发布时间】:2019-01-10 02:02:02
【问题描述】:

我正在使用Dapper将.net core api与Oracle DB连接。我有以下方法。

public IDbConnection GetConnection()
    {
        var connectionString = configuration.GetSection("ConnectionStrings").GetSection("AsyncDB").Value;
        var conn = new OracleConnection(connectionString);
        return conn;
    }

public Object GetProducts()
    {
        //throw new System.NotImplementedException();
        object result = null;
        try
        {
            OracleDynamicParameters dynamicParameters = new OracleDynamicParameters();
            dynamicParameters.Add("EMPCURSOR", OracleDbType.RefCursor, ParameterDirection.Output);

            var conn = this.GetConnection();
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }

            if (conn.State == ConnectionState.Open)
            {
                var query = "SPGETPRODUCTINFO";
                result = SqlMapper.Query(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure);
            }
        }
        catch (Exception e)
        {
            throw e;
        }

        return result;
    }

过程 SPGETPRODUCTINFO 从数据库返回行。

使用 async/await 关键字将方法转为异步方法的方法有哪些?

【问题讨论】:

    标签: .net-core dapper


    【解决方案1】:

    您使此方法异步的方式与您将任何其他方法异步的方式相同。您将该方法标记为异步,如果它返回 void,则让它返回一个 Task 或 Task 其中 T 是它之前返回的类。将其更改为使用任何可用方法的同步版本并等待结果。

    你这里的异常处理不好。首先,您正在执行 throw e; 其中 e 是一个捕获的异常。不要那样做。如果您需要重新抛出捕获的异常,只需执行throw;。这样您就可以保留堆栈跟踪。此外,这个 try/catch 完全没有意义。如果您不打算采取任何补救措施或记录任何内容,那就没有意义了。您可以从此代码中完全删除 try/catch。

    您没有正确处理数据库连接。 OracleConnection 实现IDisposable。您需要使用 using 语句或在 finally 块中处理它。

    类名是GetProducts,但你只是返回一个对象。那不是很好。现在,任何消费代码都必须将其转换为正确的类型才能使用它。 Dapper 的全部意义在于它可以将您的查询映射到强类型对象。根据此方法的名称,您应该返回一个 IEnumerable 或类似的东西。

    您在获得数据库连接后立即检查它的状态。这没有任何意义。如果您获得了新的连接,则可以假定它已关闭并且您需要打开它。

    考虑到所有这些,您应该会得到这样的结果:

    public IDbConnection GetConnection()
    {
        var connectionString = configuration.GetSection("ConnectionStrings").GetSection("AsyncDB").Value;
        var conn = new OracleConnection(connectionString);
        return conn;
    }
    
    public Task<IEnumerable<Product>> GetProducts()
    {
        OracleDynamicParameters dynamicParameters = new OracleDynamicParameters();
        dynamicParameters.Add("EMPCURSOR", OracleDbType.RefCursor, ParameterDirection.Output);
    
        const string query = "SPGETPRODUCTINFO";
    
        using (var conn = this.GetConnection())
        {
            await conn.OpenAsync();
            var products = await conn.QueryAsync<Product>(query, param: dynamicParameters, commandType: CommandType.StoredProcedure);
            return products;
        }
    }
    

    既然 GetProducts 是异步的,上面调用它的任何方法都需要异步并更改为返回一个任务,并等待它。任何调用需要异步并更改为返回任务并等待它的方法。一直向上调用堆栈,直到到达事件处理程序或应用程序的主要方法。

    【讨论】:

      【解决方案2】:

      首先,你的方法需要转为Async

      public Object GetProducts()
      

      public async Task<Object> GetProductsAsync();
      public async Task<Object> GetProductsAsync(CancellationToken cancellationToken = default(CancellationToken));
      

      如果方法支持 Async 实现,一般约定显示方法名称以 Async 关键字结尾。

      您可以检查方法是否具有异步实现。比如SqlMapper.Query有Async实现,一般跟SqlMapper.QueryAsync一样。

      此外,异步实现具有返回类型任务。为了处理异步实现,您可以这样做

      result = await SqlMapper.QueryAsync(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure);
      

      另外,如果您希望您的方法支持取消,那么您需要将CancellationToken cancellationToken = default(CancellationToken) 作为参数,您的方法将是

      result = await SqlMapper.QueryAsync(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure, cancellationToken: cancellationToken);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-06-14
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-14
        • 1970-01-01
        相关资源
        最近更新 更多