将值传递给表值参数时忽略标识列

本文关键字:标识 参数 值参 值传 | 更新日期: 2023-09-27 18:07:40

我正在尝试将值传递给存储过程的表值参数,如下所示:

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());

但是问题是表值参数@InfoValues有一个额外的列是identity。我在存储过程的逻辑中使用该列。但是在c#中,它抛出了3列而不是@InfoValues中的2列的异常。我如何通过忽略这个表值参数中的标识列来传递值?

我尝试使用临时表作为这样的解决方案:

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

这个方法有效吗?

将值传递给表值参数时忽略标识列

我当然不能测试这个,但它至少可以解析。下面是一个使用OUTPUT代替循环的例子。这里假设已经定义了一些变量,并且您接收到@InfoValues作为表值参数。

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