将 SQL 参数集合传递给函数

Posted

技术标签:

【中文标题】将 SQL 参数集合传递给函数【英文标题】:Passing a SQL parameter collection to a function 【发布时间】:2014-10-26 00:26:51 【问题描述】:

在用 C# 编写 ASP.NET CRUD 应用程序时,我经常发现自己插入了大量重复的样板代码,用于将 SQL Server 查询提取到数据表中、从查询中提取标量值到变量中、调用存储过程等等。

最近,我一直在尝试通过创建通用类和方法来处理这些基本任务来重构它。但是,为了使它们正常工作,它们需要能够采用任意数量的参数。内置的SqlParameterCollection 类似乎是显而易见的首选,但不幸的是,该类无法从用户代码中实例化。下一个选项是将List<SqlParameter> 传递给函数,然后使用foreach 将其内容添加到SqlCommand 的内置参数集合中。这行得通,但声明有点笨拙。

要在调用函数之前在代码中创建列表,我必须这样做:

List<SqlParameter> ParameterList = new List<SqlParameter>

    new SqlParameter()  ParameterName = "@Parameter1", SqlDbType = SqlDbType.VarChar, Value = InputVariable1 ,
    new SqlParameter()  ParameterName = "@Parameter2", SqlDbType = SqlDbType.VarChar, Value = InputVariable2 ,
    new SqlParameter()  ParameterName = "@Parameter3", SqlDbType = SqlDbType.VarChar, Value = InputVariable3 
;

这很难在较小的显示器上阅读,并且仍然包含许多重复的样板文件。所以我的下一步是使用重载的 Add 方法创建一个自定义类,这样就不需要了。我读过在 C# 中继承 List 是不好的,所以我改用 Collection

public class ParameterCollection : Collection<SqlParameter>

    public void Add(string    ParameterName,
                    SqlDbType ParameterType,
                    object    ParameterValue)
    
        // Create the parameter and add it to the list
        SqlParameter Parameter = new SqlParameter();
        Parameter.ParameterName = ParameterName;
        Parameter.SqlDbType     = ParameterType;
        Parameter.Value         = ParameterValue;
        base.Add(Parameter);

        // Done
        return;
    

然后我可以像这样声明一个参数集合:

ParameterCollection Parameters = new ParameterCollection

    // name          type               value
     "@Parameter1", SqlDbType.VarChar, InputVariable1 ,
     "@Parameter2", SqlDbType.VarChar, InputVariable2 ,
     "@Parameter3", SqlDbType.VarChar, InputVariable3 
;

我的问题是:是否有任何更快/更容易的方法来执行我忽略的这项任务?我目前的做法是否存在任何潜在的隐藏陷阱或不良做法?

【问题讨论】:

我认为 Visual Studio 会为您自动完成大部分此类操作。 Parameters.Add 有一堆我通常使用的重载。无论如何,如果我希望缩短“创建”SqlParameter 的时间,我可能会创建一个辅助函数(带有重载/默认值),而不是创建一个类。 这应该在CodeReview。不能不用实体框架吗? @meda:请阅读Can we stop using AddWithValue() already? - 我会推荐AddWithValue而不是其他选项。 @marc_s 有趣的文章 我必须同意明确总是更好。感谢分享! 【参考方案1】:

你可能忽略了一点,Add 返回了添加的参数,它允许我们在同一个语句中设置值:

cmd.Parameters.Add("@Parameter1", SqlDbType.VarChar).Value = paramValue;

【讨论】:

我以前见过这样的语法,但是当我尝试时它不起作用。如果我做类似 List ParameterList = new List(); ParameterList.Add(new SqlParameter("@Parameter1", SqlDbType.VarChar)).Value = InputVariable1;它会导致错误(运算符“。”不能应用于 void 类型的操作数)。 @JDG1980 您评论中的示例不起作用的原因是List&lt;T&gt;.Add has a void return。还有一些SqlParameterCollection.Add 重载return other types such as int。但是我展示的超载(最有用的一个?)returns the SqlParameter added,您可能希望将其纳入您的思考中。 如前所述,SqlParameterCollection 的问题在于它无法从用户代码中实例化,因此无法传递给函数。我试图避免在我的代码周围散布数十个多缩进的 using SqlConnection(...) ... using SqlCommand(...) ... ... 块。 @JDG1980 是的,我确实看到了您关于无法实例化SqlParameterCollection 的观点,但我的部分观点是可以将Add 行简化到您可以使用的程度它原样而不是创建一个调用与Add 行非常相似的助手。【参考方案2】:

而不是实例化和传递一个集合——正如你所说,这受到SqlParameterCollection 没有公共构造函数的阻碍——你可以通过传递SqlCommand 本身来间接传递集合。然后,您的泛型类和方法可以将参数添加到 SqlCommand.Parameters,从而无需您实例化单独的集合。

【讨论】:

【参考方案3】:

有几种方法可以执行此操作。

首先: 您必须声明新参数。

cmd.Parameters.Add("@Parameter1", SqlDbType.VarChar, 50 //the size of Varchar);

然后你添加值。

cmd.Parameters["@Parameter1"].Value = paramValue;

我更喜欢使用 Dapper 扩展来处理这些事情。它更容易,语法更具可读性,总的来说就是喜欢它。 检查链接,您可能会喜欢您所看到的: https://dapper-tutorial.net/

【讨论】:

以上是关于将 SQL 参数集合传递给函数的主要内容,如果未能解决你的问题,请参考以下文章

横向解决方法:将参数从查询中的其他位置传递给集合返回函数

VBA:将二维数组传递给集合函数[重复]

如何将 .NET 对象集合(父子)层次结构传递给 SQL Server 存储过程

在 Sql Server 中将集合作为参数传递时使用 IN 子句

MyBatis中动态sql实现传递多个参数并使用if进行参数的判断和实现like模糊搜索以及foreach实现in集合

传递给函数的参数必须是可调用的,给定数组