在 mvc 中使用 dapper 的动态结果

Posted

技术标签:

【中文标题】在 mvc 中使用 dapper 的动态结果【英文标题】:Dynamic results using dapper in mvc 【发布时间】:2017-03-27 09:10:49 【问题描述】:

我正在尝试以下方式使用 dapper 和存储过程返回动态结果。我这样做的方式是否正确?

using (IDbConnection dbConnection = Connection)

    dbConnection.Open();

    var result = dbConnection.Query<dynamic>("LMSSP_GetSelectedTableData",
        new
        
            TableName = TableName,
            LangaugeID = AppTenant.SelectedLanguageID,
            UserID = AppTenant.UserID
        , commandType: CommandType.StoredProcedure).ToList();


    if (result != null)
    
        // Added just for checking the data
        foreach (var item in (IDictionary<string, object>)result.FirstOrDefault())
        
            string key = item.Key;
            string value = item.Value.ToString();

        
    

我的存储过程所做的是,我将传递任何表名并基于它返回结果/记录。所以,显然我的记录数,列将根据传递的表名而变化。

为了实现这一点,我使用了动态关键字和 dapper。

所以我的问题是如何将这些数据作为模型传递给视图,并根据属性/列数据类型在视图上呈现控件。我可以获取列 OR PropertyInfo 的数据类型吗?

但是,当 dapper 从数据库中检索记录时,它会以 dapper 行类型返回?

【问题讨论】:

如果您的存储过程根据输入返回不同的模式,这对我来说表明数据库设计不佳 @Rob 它只适用于少数表,主要是我们手中的系统表,而不是客户端。你能告诉我解决办法吗? 【参考方案1】:

使用相同的 SP 从不同的表中获取数据会令人困惑(不是好的设计)。但是,为了从技术上解决您的问题,您可以创建具有控制信息列表的模型。控制信息示例

public class ControlInformation

    public string Name  get; set; 

    public dynamic Value  get; set; 

    public string ControlType  get; set; 

    // Applicable for drop down or multi select
    public string AllValues  get; set; 

模型将具有 ControlInformations 列表

public List<ControlInformation> ControlInformations  get; set; 

View 将呈现控件(基于控件类型的部分视图) 例如:非常基本的情况,为 int 呈现不同的视图,为 rest 呈现另一个视图。我有 2 个局部视图“IntCtrl”和“StringCtrl”。

@foreach (var item in Model.ControlInformations)
    
        if (@item.ControlType == "System.Int32")
        
            html.RenderPartial("IntCtrl", item);
        
        else
        
            Html.RenderPartial("StringCtrl", item);
        
    

希望对您有所帮助。

【讨论】:

【参考方案2】:

这里我们调用返回 Datatable 的方法:

    public DataTable GetMTDReport(bool isDepot, int userId)
    
        using (IDbConnection _connection = DapperConnection)
        
            var parameters = new DynamicParameters();
            parameters.Add("@IsDepot", isDepot);
            parameters.Add("@userId", userId);
            var res = this.ExecuteSP<dynamic>(SPNames.SSP_MTDReport, parameters);
            return ToDataTable(res);
        
    

在此我们可以通过调用我们的自定义方法“ExecuteSP”来调用存储过程:

    public virtual IEnumerable<TEntity> ExecuteSP<TEntity>(string spName, object parameters = null)
    
        using (IDbConnection _connection = DapperConnection)
        
            _connection.Open();
            return _connection.Query<TEntity>(spName, parameters, commandTimeout:0 , commandType: CommandType.StoredProcedure);
        
    

这里是连接数据库的“DapperConnection”方法: 您可以使用键 ["MainConnection"]

提供连接字符串
public class DataConnection

    public IDbConnection DapperConnection
    
        get
        
            return new SqlConnection(ConfigurationManager.ConnectionStrings["MainConnection"].ToString());
        
    

最后我们调用“ToDataTable”方法来改变我们在 datatable 中的响应。我们将在 DapperRow 中收到来自数据库的响应,因为我们在存储过程中传递了动态类型。

    public DataTable ToDataTable(IEnumerable<dynamic> items)
    
        if (items == null) return null;
        var data = items.ToArray();
        if (data.Length == 0) return null;

        var dt = new DataTable();
        foreach (var pair in ((IDictionary<string, object>)data[0]))
        
            dt.Columns.Add(pair.Key, (pair.Value ?? string.Empty).GetType());
        
        foreach (var d in data)
        
            dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
        
        return dt;
     

【讨论】:

以上是关于在 mvc 中使用 dapper 的动态结果的主要内容,如果未能解决你的问题,请参考以下文章

获取 dapper.QueryMultiple 方法返回的结果集计数

如何让 Dapper 动态不区分大小写?

Dapper 映射结果列表

从 dapper 中的多个查询返回可枚举的结果

mvc Dapper_Report_Down_ExcelFile

DB2 - 使用带有字符串数组参数的 Dapper 选择查询将不会返回正确的结果