代码之家  ›  专栏  ›  技术社区  ›  DocSmiley

T-SQL表类型,指定的类型未注册

  •  4
  • DocSmiley  · 技术社区  · 12 年前

    我有一个用C#写成字符串的查询,我正试图在T-sql数据库(而不是存储过程)上调用它。我必须传入的参数之一是GUID列表。我正试图使用 table-valued parameter 为此。考虑到查询的一部分需要动态表名,存储过程在调试时会显得有些笨拙。查询的最后一部分将表上的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。

    我一直找不到我需要做些什么才能让它发挥作用。

    1 回复  |  直到 12 年前
        1
  •  7
  •   Aaron Bertrand    12 年前

    你应该使用 SqlDbType.Structured . .Udt 不是表值参数或表类型,而是CLR用户定义类型IIRC。TVP/表值参数是 别名类型 不是a 用户自定义类型 。你也不需要告诉它 .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;