将 Dapper 与 SQL Server 一起使用

Posted

技术标签:

【中文标题】将 Dapper 与 SQL Server 一起使用【英文标题】:Using Dapper with SQL Server 【发布时间】:2021-03-04 21:27:16 【问题描述】:

我目前正在使用 C# (Visual Studio 2019) 和使用 Dapper 的 SQL Server 2017 开发应用程序。下面是一个现在可以很好地在 SQL Server 中执行存储过程的例程。

C#代码使用MVVM框架,我目前有60个模型类来映射SQL Server数据库中的表。大约有 120 个存储过程产生结果,这些结果使用 Dapper 映射到模型类。

将以下代码 sn-p 视为伪代码(但它实际上可以执行存储过程并返回正确的结果)。

public List<SomeDefinedModel> ExecuteSQLSPROC(string SPROCName, SqlParameter[] parameters)

    using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(DBHelper.CNNVal("MYLocalServer")))
    
        System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand();
        command.Connection = (SqlConnection)connection;
        command.CommandText = SPROCName;

        DynamicParameters parms = new DynamicParameters();

        for (int i = 0; i < parameters.Length; i++)
        
            var parmname = parameters[i].ParameterName;
            var parmvalue = parameters[i].Value;
            parms.Add(parmname, parmvalue);
        

        var output = connection.Query<SomeDefinedModel>(SPROCName, parms, commandType: CommandType.StoredProcedure).ToList();

        return output;
    

我想改变这个例程所以这个例程使它的方法签名如下:

public List<TheNameOfTheModelToMap> ExecuteSQLSPROC(string SPROCName, SqlParameter[] parameters, TheNameOfTheModelToMap)

也就是说,Dapper 要映射到的模型的名称是一个变量——它可以是任何有效的模型。我已将变量TheNameOfTheModelToMap 定义为类型对象,并将返回值定义为var、List&lt;object&gt;,等等。由于这种语法,它们会产生错误:

var output = connection.Query<TheNameOfTheModelToMap>(SPROCName, parms, commandType: CommandType.StoredProcedure).ToList();

我想遵守 DRY 的原则,只编写一种方法来接受任何模型指定、任何存储过程指定并让 Dapper 映射查询结果。有什么可能吗?

【问题讨论】:

实现像public List&lt;T&gt; ExecuteSQLSPROC&lt;T&gt;(string SPROCName, SqlParameter[] parameters)这样的泛型方法怎么样? 这里的SqlCommand 有什么意义,你似乎没有使用它,而且 Dapper 肯定会为你解决这个问题 另外,您可能应该直接使用 SqlParameter 对象,而不是将它们添加到 DynamicParameters() 集合中。您丢失了参数方向,这将阻止您使用 Out 或 ReturnValue 参数。 你想要public List&lt;TheNameOfTheModelToMap&gt; ExecuteSQLSPROC(string SPROCName, SqlParameter[] parameters, object TheNameOfTheModelToMap)?从您的签名中不清楚TheNameOfTheModelToMap 参数的类型是什么。 【参考方案1】:

我认为你只需要一个像这样的通用方法:


public List<T> ExecuteSQLSPROC<T>(string SPROCName, SqlParameter[] parameters)

    using (var connection = new System.Data.SqlClient.SqlConnection(DBHelper.CNNVal("MYLocalServer")))
    
        var parms = new DynamicParameters();
        foreach (var parameter in parameters)
            parms.Add(parameter.ParameterName, parameter.Value);

        var output = connection.Query<T>(
                SPROCName,
                parms,
                commandType: CommandType.StoredProcedure
            )
            .ToList();

        return output;
    



所有其他方法都成为它的专门调用:

public List<SomeDefinedModel> ExecuteOneProc(SqlParameter[] parameters)
  => ExecuteSQLSPROC<SomeDefinedModel>("OneProcName", parameters);

这适合您的用例吗? 如果您需要一个处理单个值的过程(不会使用 Dapper 的 Query 方法),您只需创建 ExecuteSQLSPROC 的特殊变体,例如 ExecuteStoredProcSingleRow 或类似的东西。

【讨论】:

我使用以下语法来调用新版本的 ExecuteSQLSPROC。 ExecuteSQLSPROC 方法按照建议正确编译,但调用新方法的代码如下: public List ExecuteSQLSPROC(SqlParameter[] parameters) => ExecuteSQLSPROC("ReturnCarDetails", parameters);将无法编译并产生以下错误: CS0106 修饰符 'public'‌ 对此项无效指 lambda 表达式之后的所有内容) 好吧,在我的示例中,您必须指定存储过程返回的类型。类似于:List&lt;CarDetail&gt; ExecuteSQLSPROC(SqlParameter[] parameters) =&gt; ExecuteSQLSPROC&lt;CarDetail&gt;("ReturnCarDetails", parameters); 即返回 List 而不是 List,并调用指定泛型类型参数的泛型方法。

以上是关于将 Dapper 与 SQL Server 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何使 SQL Server 2012 与 php 一起工作?

如何使此 Access sql 语句与 Sql Server 一起使用?

如何使 Java 与 SQL Server 一起工作?

将 IAsyncEnumerable 与 Dapper 一起使用

将 Dapper 与返回游标的 Oracle 存储过程一起使用

将 BeginTransaction 与 Dapper.IDbConnection 一起使用的正确方法