是否创建Dapper方法的异步版本和同步版本,而无需复制代码?

时间:2019-05-27 12:51:47

标签: c# asynchronous synchronization dapper

假设我有一个简单的类,其中包含数据库访问方法。数据库访问通过Dapper。在不复制代码的情况下,创建这些方法的异步和同步版本的最简单方法是什么?让我们以两个方法为例:GetUsers()和GetUsersAsync()。在这种情况下,两种方法将具有相同的逻辑。唯一的区别是,它将调用同步和其他异步版本的Dapper方法,例如查询与QueryAsync。

仅调用GetUsersAsync()。结果不是一个好主意。有没有人足够优雅地解决了这个问题?

2 个答案:

答案 0 :(得分:0)

数据访问层(DAL)中的方法不应包含比实际查询多得多的逻辑。您可以将查询字符串和任何参数定义为两种方法都可以访问的私有字段,例如:

private const string ConnectionString = "...";
private const string Query = "SELECT Id, Name FROM Users";

public IEnumerable<User> GetUsers()
{
    using (var cn = new SqlConnection(ConnectionString))
        return cn.Query<SerieDailyValueDto>(Query).ToArray();
}

public Task<IEnumerable<User>> GetUsersAsync()
{
    using (var cn = new SqlConnection(ConnectionString))
        return await cn.QueryAsync<SerieDailyValueDto>(Query).ToArray();
}

如果您有任何其他逻辑,则可以在执行查询之前两个版本都调用的私有方法中实现它。

答案 1 :(得分:0)

我已经使用nHibernate完成了与您的问题类似的操作。 对此进行检查(属于我的文件的一部分):

不幸的是,这些是最重要的功能,必须以某种方式进行复制。 这些函数执行整个可重复代码。操作参数是他们真正需要做的(例如:insert)上下文主要是nHibernate会话。在nHibernate中,每个操作都必须在会话内。 GetContextForStatement仅返回新会话或先前打开的有效会话。

    //sync version
    T GeneralExecuteAction<T>(Func<ISession, T> action)
    {
        lastDbError = DbError.Ok;
        using (var ctx = GetContextForStatement())
        {
            try
            {
                T result = action(ctx.session);
                ctx.CommitTransactionIfExists();
                return result;
            }
            catch (Exception ex)
            {
                ctx.RollbackTransactionIfExists();
                lastDbError = new DbError(ex);
                return default(T);
            }
        }
    }

    //async version 
    async Task<T> GeneralExecuteAction<T>(Func<ISession, Task<T>> action)
    {
        lastDbError = DbError.Ok;

        using (var ctx = GetContextForStatement())
        {
            try
            {
                T result = await action(ctx.session);
                await ctx.CommitTransactionIfExistsAsync();
                return result;
            }
            catch (Exception ex)
            {
                await ctx.RollbackTransactionIfExistsAsync();
                lastDbError = new DbError(ex);
                return default(T);
            }
        }
    }

现在,您可以在公共方法中使用以上功能: 例如,保存的同步版本:

    public DbError Save<T>(T obj) where T : class
    {
        GeneralExecuteAction((s) =>
        {
            s.Save(obj); //s is nHibernate session
            return true;
        });

        return lastDbError;
    }

保存的异步版本

    public async Task<DbError> SaveAsync<T>(T obj) where T : class
    {
        await GeneralExecuteAction((s) =>
        {
            s.Save(obj);
            return Task.FromResult(true);
        });

        return lastDbError;
    }