【问题标题】:C# Using dynamic parameter in stored procedureC#在存储过程中使用动态参数
【发布时间】:2018-02-16 12:16:03
【问题描述】:

我正在为 SQL Server 创建一个存储过程以从 C# 应用程序调用。存储过程包含一些动态创建的 SQL,它接收一个参数以使用查询执行 sp_executesql,但是当我从 C# 应用程序运行它时,我没有得到结果。

当我从 SQL Server Management Studio 调用该过程时,我得到了所有结果。

例如:我得到了我的表 Products

id | Descrip
1    Pen
2    Pencil
3    Table

我创建了我的存储过程

CREATE PROCEDURE [dbo].[proc_getproductslist]
    @idProducts varchar(max)
AS
BEGIN

    DECLARE @SQL nvarchar(max)

    SET @SQL = 'SELECT * FROM Products WHERE id IN ('+@idProducts +')'

    EXEC sp_executesql @SQL
END

如果我在 SSMS 中执行:

EXECUTE proc_getproductslist '''1'',''2'''

这行得通!但是...从 C# 应用程序这不起作用

C#代码:

DataTable dt = new DataTable();
DataTable d1 = new DataTable();

using (SqlConnection cn = new SqlConnection("cnxstring"))
{
    cn.Open();

    SqlCommand cmd1 = new SqlCommand("proc_getproductslist", cn, sqlTran);
    cmd1.CommandType = CommandType.StoredProcedure;

    try
    {
        cmd1.Parameters.Add("@numguia", SqlDbType.VarChar).Value = "'''1'',''2'''";

        SqlDataAdapter da1 = new SqlDataAdapter();
        da1.SelectCommand = cmd1;
        da1.Fill(d1);
    }
    catch (SqlException exsql)
    {
        try
        {
            sqlTran.Rollback();
        }
        catch (Exception exRollback)
        {
        }
    }
    catch (Exception ex)
    {
    }
    finally
    {
        cn.Close();
    }

    return d1;
}

当我从我的 C# 应用程序调用存储过程时,它不会返回任何内容。

请帮助我如何完成这项工作。

谢谢

【问题讨论】:

  • 为什么不用标准参数?

标签: c# sql-server stored-procedures dynamic


【解决方案1】:

为什么不只使用表值参数,这几乎正是它们的设计目的......

首先创建你的类型:

CREATE TYPE dbo.ListOfInt AS TABLE (Value INT NOT NULL);

那么你的程序就这么简单

CREATE PROCEDURE [dbo].[proc_getproductslist]  @idProducts dbo.ListOfInt READONLY
AS
BEGIN
    SELECT  * 
    FROM    Products 
    WHERE   id IN (SELECT Value FROM @idProducts);

END

不需要动态 SQL。顺便说一句,it is not good idea to use SELECT * in production code

最后,调用你的过程(为了简洁,去掉 try/catch)

DataTable dt = new DataTable();
DataTable d1 = new DataTable();

//Set the IDs you wish to pass
DataTable dtParam = new DataTable();
dtParam.Columns.Add("Value", typeof(int));
dtParam.Rows.Add(1);
dtParam.Rows.Add(2);


using (SqlConnection cn = new SqlConnection("cnxstring"))
using (SqlCommand cmd1 = new SqlCommand("proc_getproductslist", cn, sqlTran))
{
    cn.Open();
    cmd1.CommandType = CommandType.StoredProcedure;

    //Create and add the parameter
    var tableParam = new SqlParameter("@numguia", SqlDbType.Structured);
    tableParam.Value = dtParam;
    tableParam.TypeName = "dbo.ListOfInt";
    cmd1.Parameters.Add(tableParam);

    SqlDataAdapter da1 = new SqlDataAdapter(cmd1);
    da1.Fill(d1);
}

【讨论】:

    【解决方案2】:

    在您的 C# 代码中,带有 CommandType = CommandType.StoredProcedure 的 Select 命令的参数名称必须与 Sql 代码中定义的参数名称匹配。试试

       cmd1.Parameters.Add("@idProducts", SqlDbType.VarChar).Value = "1,2";
    

    【讨论】:

      【解决方案3】:

      在 TSQL 中 '' 被转义 '.在 C# 中并非如此。第一个和最后一个 ' 表示字符串文字。在 C# 中 " 开始和结束字符串文字。

      所以

      cmd1.Parameters.Add("@numguia", SqlDbType.VarChar).Value = "'''1'',''2'''";
      

      应该是

      cmd1.Parameters.Add("@numguia", SqlDbType.VarChar).Value = "'1','2'";
      

      或者因为它似乎是一个整数列表

      cmd1.Parameters.Add("@numguia", SqlDbType.VarChar).Value = "1,2";
      

      EG

      using System;
      using System.Collections.Generic;
      using System.Data;
      using System.Data.SqlClient;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace ConsoleApp10
      {
          class Program
          {
              static void Main(string[] args)
              {
                  using (var con = new SqlConnection("Server=localhost;database=tempdb;integrated security=true"))
                  {
                      con.Open();
      
                      var ddl = new SqlCommand(@"
      CREATE OR ALTER PROCEDURE [dbo].[proc_getproductslist]
          @idProducts varchar(max)
      AS
      BEGIN
      
          DECLARE @SQL nvarchar(max)
      
          SET @SQL = 'SELECT ''success'' result WHERE ''1'' IN ('+@idProducts +')'
      
          EXEC sp_executesql @SQL
      END
      ", con);
                      ddl.ExecuteNonQuery();
      
                      var cmd = new SqlCommand("proc_getproductslist", con);
                      cmd.CommandType = System.Data.CommandType.StoredProcedure;
      
                      cmd.Parameters.Add("@idProducts", SqlDbType.VarChar).Value = "'''1'',''2'''";
      
      
                      var result = (string)cmd.ExecuteScalar() ;
                      Console.WriteLine(result??"null");
      
                      cmd.Parameters["@idProducts"].Value = "'1','2'";
                      result = (string)cmd.ExecuteScalar();
      
                      Console.WriteLine(result??null);
      
                      Console.ReadKey();
      
                  }
              }
          }
      }
      

      输出

      null
      success
      

      【讨论】:

        猜你喜欢
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-29
        • 1970-01-01
        • 2012-06-09
        相关资源
        最近更新 更多