首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Dapper“异步”和“等待使用”

Dapper“异步”和“等待使用”
EN

Code Review用户
提问于 2019-11-04 23:00:05
回答 1查看 4K关注 0票数 4

我一直在构建我的数据访问层,性能是我正在进行的项目的关键。

我选择使用Dapper和dotnet 3,我想利用dotnet和Dapper中最新和最伟大的异步特性,以便在负载较重的情况下进行更智能的资源分配,但是没有太多的文档。

所有的dapper似乎都使用非异步,我为SqlConnection找到的大多数示例都使用非异步方法。

我想知道是否所有异步和等待的使用是值得的开销。

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
using Dapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Outible.API.Model;
using Outible.DataAccess.Interfaces;

namespace Outible.DataAccess.Models
{
    public class Db : IDb
    {
        private readonly IOptionsMonitor<ConnectionStrings> _connectionStrings;
        private readonly ILogger<Db> _logger;

        public Db(IOptionsMonitor<ConnectionStrings> connectionStrings, ILogger<Db> logger)
        {
            _connectionStrings = connectionStrings;
            _logger = logger;
        }

        private async Task<T> CommandAsync<T>(Func<IDbConnection, IDbTransaction, int, Task<T>> command)
        {
            var connection = new SqlConnection(_connectionStrings.CurrentValue.MainDatabase);
            await connection.OpenAsync().ConfigureAwait(false);
            await using var transaction = await connection.BeginTransactionAsync();
            try
            {
                var result = await command(connection, transaction, 300).ConfigureAwait(false);

                await transaction.CommitAsync().ConfigureAwait(false);

                return result;
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync().ConfigureAwait(false);
                _logger.LogError(ex, "Rolled back transaction");
                throw;
            }
        }

        public Task<int> ExecuteAsync(string sql, object parameters)
        {
            return CommandAsync((conn, trn, timeout) => conn.ExecuteAsync(sql, parameters, trn, timeout));
        }

        public Task<T> GetAsync<T>(string sql, object parameters)
        {
            return CommandAsync((conn, trn, timeout) => conn.QuerySingleOrDefaultAsync<T>(sql, parameters, trn, timeout));
        }

        public Task<IEnumerable<T>> SelectAsync<T>(string sql, object parameters)
        {
            return CommandAsync((conn, trn, timeout) => conn.QueryAsync<T>(sql, parameters, trn, timeout));
        }
    }
}
EN

回答 1

Code Review用户

发布于 2019-11-05 01:00:35

我看到您已经将using应用于事务。

但是,考虑到为每个命令创建了一个新的SqlConnection,我建议将其封装在using语句中。

代码语言:javascript
运行
复制
private async Task<T> CommandAsync<T>(Func<IDbConnection, IDbTransaction, int, Task<T>> command)
{
    using(var connection = new SqlConnection(_connectionStrings.CurrentValue.MainDatabase))
    {
        await connection.OpenAsync().ConfigureAwait(false);
        await using var transaction = await connection.BeginTransactionAsync();
        try
        {
            T result = await command(connection, transaction, 300).ConfigureAwait(false);

            await transaction.CommitAsync().ConfigureAwait(false);

            return result;
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync().ConfigureAwait(false);
            _logger.LogError(ex, "Rolled back transaction");
            throw;
        }
    }
}
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/231856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档