首页 > 解决方案 > 传递 sqlparameter 中的值列表,可能是结构化的

问题描述

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

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

SELECT COUNT(*) FROM @Users

我尝试过这样的事情:
1)数据表创建者:

        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)

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

关于标记为重复:
提供的链接不能解决问题,因为它不是缺少类型名问题,而是缺少要使用的类型名。问题是我不能创建任何表,也不能使用任何现有的表在 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 中可用。

标签: c#tsqlado.net

解决方案


您需要在 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

然后在您的代码中给出该名称。这将起作用,您确实需要为此在数据库中创建表。


推荐阅读