谁能提出一种优雅的方法来编写通用的C#Dapper过程以返回n个结果集?

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

我使用Dapper创建了少量通用过程,以返回列表或任何给定类型的单个项(例如,使用SQL端的SP),以用于DI模型数据服务,例如

public async Task<List<TOut>> GetList<TOut>(string proc, dynamic parameters)
{
    await using var conn = new SqlConnection(connectionString);
    var cmd = parameters == null ? new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure) : new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure, parameters: parameters);
    return conn.Query<TOut>(cmd).ToList();
}

但是,我一直试图将其扩展为使用QueryMultiple方法在一个查询中返回任意数量的结果集(以提高效率,因为第一个查询非常昂贵,而其他结果集依赖于此)。我想以强类型的结果集(而不是匿名对象)结束,而无需编写大量代码。但是,我看不出有任何方法可以提供任意数量的类型参数-到目前为止,我设法做到的最好是为两个结果集生成一个方法,为三个结果集生成一个方法,依此类推:

public async Task<dynamic> Get2Lists<T1, T2>(string proc, dynamic parameters)
{
    await using var conn = new SqlConnection(connectionString);
    var cmd = parameters == null ? new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure) : new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure, parameters: parameters);
    var result = conn.QueryMultiple(cmd);
    return new
    {
        Table1 = result.Read<T1>(),
        Table2 = result.Read<T2>()
    };
}

public async Task<dynamic> Get3Lists<T1, T2, T3>(string proc, dynamic parameters)
{
    await using var conn = new SqlConnection(connectionString);
    var cmd = parameters == null ? new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure) : new CommandDefinition(commandText: proc, commandType: CommandType.StoredProcedure, parameters: parameters);
    var result = conn.QueryMultiple(cmd);
    return new
    {
        Table1 = result.Read<T1>(),
        Table2 = result.Read<T2>(),
        Table3 = result.Read<T3>()
    };
}

在我看来,必须有一种更优雅的方式-有什么建议吗?

c# sql dapper type-parameter
1个回答
2
投票

简短回答:Dapper支持使用SqlMapper.GridReader

这是我们的用法。您应该能够修改它以满足您的需求。我们有一个DapperRepository类,其中包含所有通用的dapper调用。这是一个(大大)简化的版本,向您显示所需的内容。

using Dapper;
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

public class DapperRepository
{

    private readonly string _connStringName;

    public DapperRepository(string connStringName)
    {
        _connStringName = connStringName;
    }

    private SqlConnection OpenConnection(string cs)
    {
        var connection = ConfigurationManager.ConnectionStrings[cs].ConnectionString;
        SqlConnection con = new SqlConnection(connection);
        con.Open();
        return con;
    }

    // lots of other methods removed for the brevity of this post

    // This is the method you want
    public void QuerySPMultiple(string sql, Action<SqlMapper.GridReader> callback, object parameters = null)
    {
        using (var connection = OpenConnection(_connStringName))
        {
            var gr = connection.QueryMultiple(sql, param: parameters,commandTimeout:0, commandType: CommandType.StoredProcedure);
            callback(gr);
         }
    }
}

假设我们有一个看起来像这样的类:

public class FooBar
{
    public List<Stuff> MyStuff { get; set; }
    public int MyInt { get; set; }
}

然后用一个存储的proc调用填充FooBar,该调用返回多个数据集:

// Create an instance of the repository
DapperRepository repo = new DapperRepository("your connection string");

// Create your parameters
DynamicParameters param = new DynamicParameters();
param.Add("@Name", "Value");

// Call the stored proc and get back multiple sets of data
FooBar fooBar = new FooBar();
repo.QuerySPMultiple("YourSPName", (reader) =>
{
    fooBar.MyStuff = reader.Read<Stuff>().ToList();
    fooBar.MyInt = reader.Read<int>().FirstOrDefault();
}, parameters: param);

我希望所有这些都说得通!如果没有,请随时发布后续问题。

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