sp_executesql with user defined table type not behaving correctly
sp_executesql
is for executing ad-hoc T-SQL. So you should try:
EXECUTE sp_executesql N'exec dbo.Repro @MetricData',N'@MetricData dbo.UDTT READONLY',@MetricData=@p3
I was tempted to delete this question but figured someone else might run into a similar circumstance.
The root cause was my $updateCommand
had not set the CommandType. The default value is Text so my stored procedure was being called correctly. My parameters were being created and passed but as noted in the other answers just because the parameters are available does not mean they are being used.
Code in case anyone was interested in my mistake
$updateConnection = New-Object System.Data.SqlClient.SqlConnection("Data Source=localhost\localsqla;Initial Catalog=baseline;Integrated Security=SSPI;")
$updateConnection.Open()
$updateCommand = New-Object System.Data.SqlClient.SqlCommand($updateQuery)
$updateCommand.Connection = $updateConnection
# This is what I was missing
$updateCommand.CommandType = [System.Data.CommandType]::StoredProcedure
#$updateCommand.CommandType = [System.Data.CommandType]::Text
#$updateCommand.CommandType = [System.Data.CommandType]::TableDirect
$DataTransferFormat = $updateCommand.Parameters.AddWithValue("@MetricData", $dataTable)
$DataTransferFormat.SqlDbType = [System.Data.SqlDbType]::Structured
$DataTransferFormat.TypeName = $udtt
$results = $updateCommand.ExecuteNonQuery()
Running with a value of CommandType of Text would require @rob_farley's solution of changing the value of $updateQuery
to "EXEC dbo.Repro @MetricData". At that point, the sp_executesql will map values correctly and life is good.
Running with a CommandType
of TableDirect
is not supported by the SqlClient Data Provider, as the documentation indicates.
Using a CommandType
of StoredProcedure
translates to a direct invocation of the stored procedure without the sp_executesql
wrapper and works great.