I'm trying to generate DataTable object to pass as a value (TVP) to a stored procured input.
The problem is that the TVP has two auto generated columns, one is an identity and the other is computed.
Calling ExecuteNonQuery fails with an exception:
"INSERT into an identity column not allowed on table variables." for the identity column
"The column "XXX" cannot be modified because it is either a computed column or is the result of a UNION operator." for the computed column.
"Trying to pass a table-valued parameter with 2 column(s) where the corresponding user-defined table type requires 3 column(s)." in case I'm trying to pass a DataTable without one of the coulmns
Here is a code example with the issue-
SQL:
USE tempdb;
GO
IF TYPE_ID('dbo.UDT_stackoverflow') IS NOT NULL
BEGIN
SET NOEXEC ON;
END;
GO
CREATE TYPE dbo.UDT_StackOverflow AS TABLE
(
[ID] INT NOT NULL IDENTITY(1, 1),
PDay AS CONVERT(DATETIME, CONVERT(DATE, IDateTime))PERSISTED,
ServerID INT NOT NULL,
IDateTime DATETIME NOT NULL
);
GO
SET NOEXEC OFF;
GO
IF OBJECT_ID('dbo.USP_Bulk_SetStackOverflow') IS NULL
BEGIN
EXEC('CREATE PROCEDURE dbo.USP_Bulk_SetStackOverflow AS');
END;
GO
ALTER PROCEDURE dbo.USP_Bulk_SetStackOverflow @I_StackOverflow dbo.UDT_StackOverflow READONLY
AS
------------------------------------------------------------------------------------------------------
BEGIN
SET NOCOUNT ON;
------------------------------------- Main Execution Code -------------------------------------------
SELECT ID , PDay, ServerID, IDateTime FROM @I_StackOverflow ;
END;
GO
C#:
SqlDatabase db = new SqlDatabase(ConfigurationManager.ConnectionStrings["tempdb"].ConnectionString);
DbCommand dbCommand = db.GetStoredProcCommand("dbo.USP_Bulk_SetStackOverflow");
SqlParameter p = (SqlParameter)db.DbProviderFactory.CreateParameter();
p.SqlDbType = SqlDbType.Structured;
p.ParameterName = "@I_StackOverflow";
p.TypeName = "dbo.UDT_StackOverflow";
DataTable table = new DataTable();
table.Columns.Add(new DataColumn() { ColumnName = "ID", Unique = true, AutoIncrement = true, AllowDBNull = false, ReadOnly = true, DataType = typeof(int) });
table.Columns.Add(new DataColumn() { ColumnName = "PDay", DataType = typeof(DateTime) });
table.Columns.Add(new DataColumn() { ColumnName = "ServerID", DataType = typeof(int) });
table.Columns.Add(new DataColumn() { ColumnName = "IDateTime", DataType = typeof(DateTime) });
DataRow row = table.NewRow();
row["ServerID"] = 1;
row["IDateTime"] = DateTime.Now;
table.Rows.Add(row);
DataRow row2 = table.NewRow();
row2["ServerID"] = 2;
row2["IDateTime"] = DateTime.Now;
table.Rows.Add(row2);
p.Value = table;
dbCommand.Parameters.Add(p);
db.ExecuteNonQuery(dbCommand);