Search code examples
c#.netsql-serverdatabasetable-valued-parameters

Ignoring identity column when passing value to a table-valued parameter


I am trying to pass values to a table-valued parameter of a stored procedure like this:

DataTable Entries = new DataTable();
Entries.Columns.Add("InfoID", typeof (int));
Entries.Columns.Add("InfoValue", typeof (string));
foreach(FormInfoValue entry in FormEntries) {
    Entries.Rows.Add(entry.InfoID, entry.InfoValue);
}
DataSet res = ExecuteStoredProcedure("SaveData", new SqlParameter[] {
    new SqlParameter() {
        DbType = DbType.String, ParameterName = "@FormID", Value = FormID
    },
    new SqlParameter() {
        SqlDbType = SqlDbType.Structured, ParameterName = "@InfoValues", Value = Entries
    },
    new SqlParameter() {
        DbType = DbType.Int32, ParameterName = "@UserID", Value = Security.SessionControl.GetSession().UserID
    }
});
return int.Parse(res.Tables[0].Rows[0][0].ToString());

But the problem is that the Table-valued parameter @InfoValues has one extra column that is identity. I am using that column in my logic in stored procedure. But at C# its throwing exception of having 3 columns instead of 2 in @InfoValues. How can I pass values by ignoring identity column in this table-valued parameter?

UPDATE

I tried to use a temp table as a solution like this:

DECLARE @FormData TABLE (
    ID INT IDENTITY(1,1) NOT NULL,
    InfoID INT NULL,
    InfoValue NVARCHAR(MAX) NULL
    )
INSERT INTO @FormData(InfoID,InfoValue) SELECT [InfoID],[InfoValue] FROM @InfoValues
        WHILE (1 = 1)
        BEGIN
            EXEC [dbo].OpenKeys
            SELECT TOP 1 @iid = [ID], @id = InfoID, @value = InfoValue FROM @FormData WHERE [ID] > @iid ORDER BY [ID]
            -- Exit loop if no more info values
            IF @@ROWCOUNT = 0 BREAK;

            INSERT INTO [InfoValues]([InfoID],[Value],[UserID],[DateAdded],[DateUpdated]) 
            VALUES(@id,[dbo].ENCRYPTDATA(@value),@UserID,GETDATE(), GETDATE()); 
            SET @retID = SCOPE_IDENTITY();
            INSERT INTO EVMap(EntryID, ValueID) VALUES(@EntryID, @retID)
        END

Is this approach efficient?


Solution

  • I of course can't test this but it at least parses. Here is an example of how this might look using OUTPUT instead of looping. This assume that some of the variable are already defined and you receive @InfoValues as a table valued parameter.

    EXEC [dbo].OpenKeys
    
    INSERT INTO [InfoValues]
    (
        [InfoID]
        , [Value]
        , [UserID]
        , [DateAdded]
        , [DateUpdated]
    ) 
    OUTPUT @EntryID      -- I assume this is set somewhere else in your code
        , INSERTED.RetID -- or whatever column is your identity in InfoValues
    INTO EVMap(EntryID, ValueID)
    SELECT InfoID
        , [dbo].ENCRYPTDATA(InfoValue)
        , @UserID -- I assume this is set somewhere else in your code
        , GETDATE()
        , GETDATE()
    FROM @InfoValues