使用SqlParameter传递多个参数

3

我知道如何向SQL查询传递一个参数,但我想创建一个函数来传递多个参数,这些参数将具有不同的类型,我卡在这里了。

public List<T> RawSql<T>(string query,  params object[] parameters)
{
    var command = context.Database.GetDbConnection().CreateCommand();

    command.CommandText = query;
    command.CommandType = CommandType.Text;

    SqlParameter parameter = new SqlParameter();
    parameter.ParameterName = "@bookId";
    parameter.SqlDbType = SqlDbType.Int;

    parameter.Value = parameters[0];

    command.Parameters.Add(parameter);

    var result = command.ExecuteReader())

    return result;
}

用法:

var rows = helper.RawSql("myStoreProc @bookId", x=> new Book { Id = (bool)x[0] }, bookId);

但是我该如何更改RawSql函数以传递多个参数,例如这样:
var rows = helper.RawSql("myStoreProc @bookId, @authorName", x=> new Book { Id = (bool)x[0] }, bookId, authorName);

2
为什么要重复造轮子?直接使用Dapper吧... - ATC
3
你在这里的问题将是如何给参数命名。坦白地说,你让自己变得很难。已经有一个名为“dapper”的工具可以做到这一点;然后,你只需使用:var data = connection.Query<Book>("myStoreProc", new { bookId, authorName }, commandType: CommandType.StoredProcedure).AsList(); - 这将做你所期望的一切,包括基于列名称的数据绑定 Book(经过优化等)(注意:对于所有通常情况都存在方法)。 - Marc Gravell
为什么不创建更多的SqlParamters并将它们添加到command.Parameters中? - devlin carnate
有一个可以在一行中完成的params重载 - 第一次使用“helper”几乎没有必要:cmd.Parameters.Add(string, dbtype).Value = data。该集合创建参数,命名它,告诉它类型并在一行代码中设置值。如果这很关键,像Dapper这样的ORM允许您使用最后面的语法。 - Ňɏssa Pøngjǣrdenlarp
3个回答

1
我建议您使用Dapper而不是重新发明轮子-但如果由于某些原因您无法这样做,我建议将方法签名更改为接受params SqlParameter[] parameters而不是params object[] parameters - 然后在方法中所需的全部内容都是command.Parameters.AddRange(parameters);
正如Marc Gravel在他的评论中写道-如果您只是使用object[],那么命名参数将成为最大的问题。

我正在使用 .NET Core 2.0,因此无法使用 .Query 函数。我不知道 Dapper。我会去了解一下,谢谢。 - lory

0

这里是我写的一种方法,用于比较来自两个不同日期的值:

public DataTable sqlToDTCompare(string conStr, string stpName, DateTime startDate, DateTime endDate, int percent)
    {
        //receives connection string and stored procedure name
        //then returns populated data table
        DataTable dt = new DataTable();

        using (var con = new SqlConnection(conStr))
        using (var cmd = new SqlCommand(stpName, con))
        using (var da = new SqlDataAdapter(cmd))
        {
            cmd.Parameters.Add("@StartDate", SqlDbType.Date).Value = startDate;
            cmd.Parameters.Add("@EndDate", SqlDbType.Date).Value = endDate;
            cmd.Parameters.Add("@Percent", SqlDbType.Int).Value = percent;
            cmd.CommandType = CommandType.StoredProcedure;
            da.Fill(dt);
        }

        return dt;
    }

该方法将数据返回到一个DataTable(在撰写时需要)。您可以使用此方法,并进行修改以更好地适应您的需求。


你想要使用的是类似于以下内容的东西:
SqlCommand.Parameters.Add("@Param1", SqlDbType.Type).Value = param1;
SqlCommand.Parameters.Add("@Param2", SqlDbType.Type).Value = param2;
SqlCommand.Parameters.Add("@Param3", SqlDbType.Type).Value = param3;
.....

SqlDbType.Type 中的 .Type 可以更改为匹配您需要的任何 SQL 数据类型(例如,SqlDbType.Date)。


0

我以前曾经做过类似的实现。

public IEnumerable<SampleModel> RetrieveSampleByFilter(string query, params SqlParameter[] parameters)
{
     using(var connection = new SqlConnection(dbConnection))
          using(var command = new SqlCommand(query, connection))
          {
              connection.Open();
              if(parameters.Length > 0)
                  foreach(var parameter in parameters)
                       command.Parameters.Add(parameter);

                       // Could also do, instead of loop:
                       // command.Parameters.AddRange(parameters);

              using(var reader = command.ExecuteReader())
                   while(reader != null)
                        yield return new Sample()
                        {
                             Id = reader["Id"],
                             ...
                        }                   
          }
}

我实际上编写了一个扩展方法来读取返回到我的对象中的值,但这允许您传递查询和一系列参数以简单地返回您的对象。

我建议使用Dapper,可以节省很多时间。但是我发现尝试重用以上类型的解决方案时会经常创建一些紧密耦合的问题。

通过采用这种方法,您将特定信息推送到其他位置,这将直接将逻辑从存储库中分离出来,并与另一个依赖项和知识紧密耦合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接