Question

I have a query written as a string in C# that I'm attempting to call on a T-sql database (not a stored procedure). One of the parameters I have to pass in is a list of GUIDs. I'm attempting to use a table-valued parameter for this. Given that part of the query requires dynamic table names a stored procedure is considered somewhat clunky for debugging. The final part of the query joins the ID on the table to the list of Guids I'm passing in.

Adding the parameter to my command in

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"
});

My table

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

When I run the line:

var reader = cmd.ExecuteReader();

I get the error:

Specified type is not registered on the target server.System.Data.DataTable, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.

I have been unable to locate what I need to do to get this working.

Was it helpful?

Solution

You should be using SqlDbType.Structured. .Udt is not a table-valued parameter or table type, that's a CLR User-Defined Type IIRC. A TVP / table-valued parameter is an alias type not a user-defined type. You also don't need to tell it the .UdtTypeName because, again, this has nothing to do with TVPs, and your code shouldn't be mentioning Udt in any shape or form.

If your procedure looks like this:

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

Then your C# code can be:

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

Or, if you just have a statement, like SELECT * FROM @ListOfGUIDs then:

SqlCommand cmd       = new SqlCommand("SELECT * FROM @ListOfGUIDs", conn);
cmd.CommandType      = CommandType.Text;
SqlParameter tvparam = cmd.Parameters.AddWithValue("@ListOfGUIDs", ListOfIDs);
tvparam.SqlDbType    = SqlDbType.Structured;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top