14

I need to use Table Valued Parameter with string query

I have the following code

string query = "SELECT * FROM Tabla1 T1 INNER JOIN @listItems T2 ON T2.Id = T1.Id";
var results = sqlConnection.Query(query , new TableValuedParameter<string>("@listItems", "string_list_Type", valuesList));

the variable valueList is a List

The execution give me a error: "Could not find stored procedure"

Is posible usa table valued parameters without use procedure ?

thanks regards

4
  • What you have posted does not even compile. "The non-generic type 'Dapper.TableValuedParameter' cannot be used with type arguments" Commented Aug 21, 2015 at 17:13
  • Also, it seems that TableValuedParameter is an internal class so you can't create a new instance of it directly. Commented Aug 21, 2015 at 17:24
  • @Darek they probably used one of the generic TableValuedParameter implementations. I have something similar and run into the exact same error. Commented Dec 14, 2021 at 14:21
  • Does the answer below help? @TomLint Commented Feb 14, 2022 at 18:44

2 Answers 2

28

Without seeing full code sample it is hard to tell what the problem could be. Consider this, which executes perfectly fine:

First, TVP definition

CREATE TYPE [dbo].[TVPSTRING] AS TABLE(
    [VALUE] NVARCHAR(MAX) NULL
)

Then sample Dapper code:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Dapper;

namespace CPTVP
{
    class Program
    {
        static void Main(string[] args)
        {
            var dt = new DataTable();
            dt.Columns.Add("StringsStringsEverywhere", typeof(string));
            foreach (int i in Enumerable.Range(0,10))
            {
                dt.Rows.Add(string.Format("{0:0000}", i));
            }

            using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Scratch;Integrated Security=true;"))
            {
                Console.WriteLine(String.Join("\n", conn.Query<string>("SELECT * FROM @tvpstr", new {tvpstr=dt.AsTableValuedParameter("dbo.TVPSTRING")})));
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

What about a TVP with multiple columns?
0

Assuming the OP used the same generic TableValuedParameter class I did, the solution lies in its implementation of the SqlMapper.IDynamicParameters AddParameters method, and the fact that it explicitly sets the CommandType of the IDbCommand to CommandType.StoredProcedure as shown below:

public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
    var sqlCommand = (SqlCommand)command;
    sqlCommand.CommandType = CommandType.StoredProcedure;
    var list = _values.Select(s =>
    {
        var sqlDataRecord = new SqlDataRecord(_tvpDefinition);
        _actionMapping(sqlDataRecord, s);
        return sqlDataRecord;
    }).ToList();

    if (list.Count == 0)
    {
        return;
    }

    var sqlParameter = sqlCommand.Parameters.Add(_name, SqlDbType.Structured);
    sqlParameter.Direction = ParameterDirection.Input;
    sqlParameter.TypeName = _typeName;
    sqlParameter.Value = list;
}

By removing the line that explicitly sets the CommandType, the TableValuedParameter class now works for normal queries, too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.