通过sqlparameter中的值列表,结构化也许

时间:2019-02-26 11:25:41

标签: c# tsql ado.net

是否可以使用SqlDbCommand和SqlParameter在C#代码中创建类似的内容?

DECLARE @Users TABLE (ID INT)
INSERT INTO @Users
VALUES (10),(20),(30)

SELECT COUNT(*) FROM @Users

我尝试过这样的事情:
1)DataTable创建者:

        private static DataTable CreateDataTable(IEnumerable<int> ids)
        {
        DataTable table = new DataTable();
        table.Columns.Add("ID", typeof(int));
        foreach (int id in ids)
        {
            table.Rows.Add(id);
        }
        return table;

2)添加SqlParameter:

 sqlParameters.Add(new SqlParameter()
                            {
                                ParameterName = $"@paramname",
                                SqlDbType = SqlDbType.Structured,
                                Value = table
                            });

3)执行命令(命令是SELECT COUNT(*)FROM @Users),参数是步骤2中的参数列表:

using (SqlCommand cmd = new SqlCommand(command, connection))
                {
                    if (parameters != null)
                        cmd.Parameters.AddRange(parameters.ToArray());

                    SqlDataReader reader = cmd.ExecuteReader();

我得到的是:

  

表类型参数'@Users'必须具有有效的类型名称。

我真的没有真正的表,所以没有可用的类型,只是希望它是

  

声明@Users表(ID INT)

那可行吗?我要实现的只是传递值列表,显然是这种情况下的整数列表。

要标记为重复项:
提供的链接不能解决问题,因为它不是缺少typename问题,而是缺少要使用的typename。问题是我无法创建任何表,也无法使用任何现有的表在SqlParameter中传递TypeName。

一个可行的解决方案:

CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [int] NOT NULL
)

然后是SqlParameter:

sqlParameters.Add(new SqlParameter()
                        {
                            ParameterName = $"@paramname",
                            SqlDbType = SqlDbType.Structured,
                            Value = table,
                            TypeName = "dbo.IntList"
                        });

尽管如此,另一步将是使用GarethD建议的内置类型。我不确定在SQL Server 2016中是否可用。

2 个答案:

答案 0 :(得分:1)

您需要使用表类型参数。首先,您需要在SQL中创建表类型。然后从C#传递参数

将数据表作为SP参数

@dt customdatatable READONLY

编写以下C#代码

DataTable dt = new DataTable();
dt.Columns.Add("customcolumnname");
DataRow dr = dt.NewRow();
dr["customcolumnname"] = "columnvalue";
dt.Rows.Add(dr);

SqlParameter[] parCollection = new SqlParameter[1];
parCollection[0] = new SqlParameter("@yourdt", dt);

答案 1 :(得分:1)

您需要在sqlParameter中添加TypeName,与在DB中创建表类型时使用的名称相同。

 sqlParameters.Add(new SqlParameter()
                            {
                                ParameterName = $"@paramname",
                                SqlDbType = SqlDbType.Structured,
                                Value = table,
                                TypeName = "dbo.MyType";
                            });

如果数据库中没有表类型,那么首先需要在SQL中创建它

CREATE TYPE [dbo].[IntegerList] AS TABLE(
    [Data] [int] NOT NULL,  
)
GO

然后在代码中输入该名称。那将起作用,并且您确实需要为此在数据库中创建表。