如何创建 Dapper QueryMultipleAsync 的泛型方法?

问题描述 投票:0回答:1

我正在尝试创建一个通用方法来使用 Dapper 获取多个数据集。我将指定预期数据类型的列表,该方法将为我提供特定数据类型的对象列表。

public async Task<List<object>> GetMultipleAsync<U>(string storedProcedure, U parameters, List<Type> types)
{
    var result = new List<object>();
    try
    {
        using (var multi = await _connection.QueryMultipleAsync(storedProcedure, parameters, commandType: CommandType.StoredProcedure, transaction: _transaction))
        {
            foreach (var type in types)
            {
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
                {
                    // Handle list types
                    var elementType = type.GetGenericArguments()[0];
                    var method = typeof(SqlMapper.GridReader)
                        .GetMethods()
                        .FirstOrDefault(m => m.Name == nameof(SqlMapper.GridReader.ReadAsync) &&
                                             m.IsGenericMethod);

                    var genericMethod = method.MakeGenericMethod(elementType);
                    var task = (Task)genericMethod.Invoke(multi, null);
                    await task.ConfigureAwait(false);

                    var resultProperty = task.GetType().GetProperty("Result");
                    var data = resultProperty.GetValue(task);

                    result.Add(data);
                }
                else
                {
                    // Handle single value types
                    var method = typeof(SqlMapper.GridReader)
                        .GetMethods()
                        .FirstOrDefault(m => m.Name == nameof(SqlMapper.GridReader.ReadSingleAsync) &&
                                             m.IsGenericMethod);


                    var genericMethod = method.MakeGenericMethod(type);
                    var task = (Task)genericMethod.Invoke(multi, null);
                    await task.ConfigureAwait(false);

                    var resultProperty = task.GetType().GetProperty("Result");
                    var data = resultProperty.GetValue(task);

                    result.Add(data);
                }
            }
        }
    }
    catch (Exception ex)
    { // Handle exception;
    }
    return result;
}

我将发送预期类型的数据类型列表,例如

var types = new List<Type>
{
    typeof(List<ModelA>),
    typeof(List<ModelB>),
    typeof(long)
};

var resultMultiple = await _dataAccess.GetMultipleAsync<DynamicParameters>(storedProcedure, parameters, types);

输出应该是

var ListA = resultMultiple[0] as List<ModelA>;
var ListB = resultMultiple[1] as List<ModelB>;
var val = resultMultiple[2] as long;

此方法会抛出错误

Parameter count mismatch.

c# generics dapper
1个回答
0
投票

你把这件事搞得太复杂了。 Dapper 已经允许您传递

Type
对象来动态构造它,您不需要自己执行此操作。您唯一的问题是构建
List<T>
,因为 Dapper 返回
IEnumerable<T>

public async Task<List<object>> GetMultipleAsync<U>(string storedProcedure, U parameters, List<Type> types)
{
    var result = new List<object>();
    try
    {
        using var multi = await _connection.QueryMultipleAsync(storedProcedure, parameters, commandType: CommandType.StoredProcedure, transaction: _transaction);
        foreach (var type in types)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
            {
                // Handle list types
                var elementType = type.GetGenericArguments()[0];
                var data = multi.ReadAsync(elementType);
                var list =                 typeof(Enumerable).GetMethod(nameof(Enumerable.ToList)).Invoke(data);
                result.Add(list);
            }
            else
            {
                // Handle single value types
                var data = multi.ReadFirstOrDefaultAsync(type);
                result.Add(data);
            }
        }
    }
    catch (Exception ex)
    { // Handle exception;
    }
    return result;
}

我必须说,在字段中保存连接和事务有点代码味道,并且只能在某种正确处理的工作单元对象上完成。

© www.soinside.com 2019 - 2024. All rights reserved.