‘Must Declare the Scalar Variable’ Error When Passing a Table-Valued Parameter to a Parameterized SQL Statement

First things first: I have no idea where you are getting the tableName and columnName, but if they are user-supplied, then this is open to SQL injection. At the very least, use QUOTENAME() to ensure no actual code is injected.

Secondly, you are not actually using the TVP. The code you have is just saying IN (@IDTable) which is not how you use a TVP.

A TVP is just a table variable, and should be used like any other table:

protected virtual void DoDeleteRecords(List<Guid> ids)
{   
    if (ids.Count == 0)
        return;
    DataTable tvp = new DataTable();
    tvp.Columns.Add("Id", typeof(Guid));

    foreach (Guid id in ids)
        tvp.Rows.Add(id);

    const string sql = @"
DELETE FROM table
WHERE idColumnName IN (SELECT * FROM @IDTable);
";

    using(SqlConnection connection = new SqlConnection(CoreSettings.ConnectionString))
    using(SqlCommand command = new SqlCommand(sql, connection))
    {
        command.Parameters.Add(
            new SqlParameter("@IDTable", SqlDbType.Structured)
        {
            Value = tvp,
            Direction = ParameterDirection.Input,
            TypeName = "dbo.IDList"
        });

        connection.Open();
        command.ExecuteNonQuery();
    }
}

Leave a Comment