3

我有一个用 C# 写成字符串的查询,我试图在 T-sql 数据库(不是存储过程)上调用它。我必须传入的参数之一是 GUID 列表。我正在尝试为此使用表值参数。鉴于查询的一部分需要动态表名,因此认为存储过程对于调试来说有些笨拙。查询的最后一部分将表上的 ID 连接到我传入的 Guid 列表中。

将参数添加到我的命令中

var ListOfIDs = new DataTable();
    ListOfIDs.Columns.Add("ID", typeof (Guid));
    selectedIDs.ForEach(x=> ListOfIDs.Rows.Add(x));

cmd.Parameters.Add(new SqlParameter("@ListOfIDs", SqlDbType.Udt)
{
   Value = ListOfIDs, UdtTypeName = "ListOfGuids"
});

我的桌子

CREATE TYPE [dbo].[ListOfGuids] AS TABLE(
    [ID] [uniqueidentifier] NULL
)

当我运行该行时:

var reader = cmd.ExecuteReader();

我得到错误:

指定类型未在目标服务器上注册。System.Data.DataTable、System.Data、Version=4.0.0.0、Culture=neutral、PublicKeyToken=b77a5c561934e089。

我一直无法找到我需要做些什么才能使其正常工作。

4

1 回答 1

7

你应该使用SqlDbType.Structured. .Udt不是表值参数或表类型,而是 CLR 用户定义类型 IIRC。TVP / 表值参数是别名类型而不是用户定义类型。您也不需要告诉它,.UdtTypeName因为这与 TVP 无关,您的代码不应Udt以任何形式或形式提及。

如果您的程序如下所示:

CREATE PROCEDURE dbo.MyProcedure
  @ListOfGUIDs dbo.ListOfGuids READONLY
AS
BEGIN
  ...
END

那么你的 C# 代码可以是:

SqlCommand cmd       = new SqlCommand("dbo.MyProcedure", conn);
cmd.CommandType      = CommandType.StoredProcedure;
SqlParameter tvparam = cmd.Parameters.AddWithValue("@ListOfGUIDs", ListOfIDs);
tvparam.SqlDbType    = SqlDbType.Structured;

或者,如果您只有一个声明,例如SELECT * FROM @ListOfGUIDs

SqlCommand cmd       = new SqlCommand("SELECT * FROM @ListOfGUIDs", conn);
cmd.CommandType      = CommandType.Text;
SqlParameter tvparam = cmd.Parameters.AddWithValue("@ListOfGUIDs", ListOfIDs);
tvparam.SqlDbType    = SqlDbType.Structured;
于 2013-10-14T19:50:13.327 回答