Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a table-value parameter

Tags:

c#

.net

ado.net

I am trying to pass a table-value parameter to a stored procedure, but I keep getting an exception (see below).

SqlCommand c = new SqlCommand("getPermittedUsers", myConn) { CommandType = CommandType.StoredProcedure };  c.Parameters.AddWithValue("@intNotifyingUserId", notifyingUserId); c.Parameters.AddWithValue("@tSelectedPdfIds", sharedPdfs).SqlDbType = SqlDbType.Structured;  SqlDataReader dr = c.ExecuteReader();

The type is defined on the server like this:

CREATE TYPE [dbo].[IdList] AS TABLE(     [Id] [int] NOT NULL )

I have tried passing sharedPdfs as a List<int>, and IQueryable<int>, but keep getting the following exception:

Object must implement IConvertible.

Anyone know what I am doing wrong? The documentation implies that I should be able to pass a list as a TVP but doesn't give any examples.

Thank you.

like image 862
nw. Avatar asked Aug 08 '11 22:08

nw.


People also ask

How do you use table value parameters?

Table-valued parameters must be passed as input READONLY parameters to Transact-SQL routines. You cannot perform DML operations such as UPDATE, DELETE, or INSERT on a table-valued parameter in the body of a routine. You cannot use a table-valued parameter as target of a SELECT INTO or INSERT EXEC statement.

How do you pass a table as a parameter in SQL?

Create a user-defined table type that corresponds to the table that you want to populate. Pass the user-defined table to the stored procedure as a parameter. Inside the stored procedure, select the data from the passed parameter and insert it into the table that you want to populate.

What is a table valued parameter?

Table-Valued Parameters aka TVPs are commonly used to pass a table as a parameter into stored procedures or functions. They are helpful in a way, we can use a table as an input to these routines and we can get rid of dealing more complex steps to achieve this process.

Can we pass table as parameter in stored procedure?

A Table Variable of User Defined Table Type has to be created of the same schema as that of the Table Valued parameter and then it is passed as Parameter to the Stored Procedure in SQL Server. In this article I will explain with an example, how to pass Table Variable as Parameter to Stored Procedure in SQL Server.


2 Answers

The following example illustrates using either a DataTable or an IEnumerable<SqlDataRecord>:

SQL Code

CREATE TABLE dbo.PageView (     PageViewID BIGINT NOT NULL CONSTRAINT pkPageView PRIMARY KEY CLUSTERED,     PageViewCount BIGINT NOT NULL ); CREATE TYPE dbo.PageViewTableType AS TABLE (     PageViewID BIGINT NOT NULL ); CREATE PROCEDURE dbo.procMergePageView     @Display dbo.PageViewTableType READONLY AS BEGIN     MERGE INTO dbo.PageView AS T     USING @Display AS S     ON T.PageViewID = S.PageViewID     WHEN MATCHED THEN UPDATE SET T.PageViewCount = T.PageViewCount + 1     WHEN NOT MATCHED THEN INSERT VALUES(S.PageViewID, 1); END 

C# Code

private static void ExecuteProcedure(bool useDataTable, string connectionString, IEnumerable<long> ids) {     using (SqlConnection connection = new SqlConnection(connectionString)) {         connection.Open();         using (SqlCommand command = connection.CreateCommand()) {             command.CommandText = "dbo.procMergePageView";             command.CommandType = CommandType.StoredProcedure;              SqlParameter parameter;             if (useDataTable) {                 parameter = command.Parameters.AddWithValue("@Display", CreateDataTable(ids));             }             else {                 parameter = command.Parameters.AddWithValue("@Display", CreateSqlDataRecords(ids));             }             parameter.SqlDbType = SqlDbType.Structured;             parameter.TypeName = "dbo.PageViewTableType";              command.ExecuteNonQuery();         }     } }  private static DataTable CreateDataTable(IEnumerable<long> ids) {     DataTable table = new DataTable();     table.Columns.Add("ID", typeof(long));     foreach (long id in ids) {         table.Rows.Add(id);     }     return table; }  private static IEnumerable<SqlDataRecord> CreateSqlDataRecords(IEnumerable<long> ids) {     SqlMetaData[] metaData = new SqlMetaData[1];     metaData[0] = new SqlMetaData("ID", SqlDbType.BigInt);     SqlDataRecord record = new SqlDataRecord(metaData);     foreach (long id in ids) {         record.SetInt64(0, id);         yield return record;     } } 
like image 55
Ryan Prechel Avatar answered Sep 21 '22 11:09

Ryan Prechel


You can pass the parameter as a DataTable, IEnumerable<SqlDataRecord>, or DbDataReader.

like image 22
Jared Moore Avatar answered Sep 20 '22 11:09

Jared Moore