ストアド プロシージャに渡す前に、すべてのパラメーターに @ のプレフィックスが付けられます。つまり、foreach ループの領域外で、2 回目の反復から、ストアド プロシージャが呼び出されると、すべてのパラメーター名の前に @ が付けられ、2 回目の反復から例外メッセージが取得されます。
{"プロシージャまたは関数 UspUpdateProctorSignalByScheduleUserID に指定された引数が多すぎます。"}
以下に示すスニペットの部分的なコードを次に示します。
[WebMethod]
public static List<OnlineProctor> UpdateAllProctorStatus(ProctoringScheduledUserInfoList scheduledUsersList)
{
#region Outside of foreach loop parameter's name will be prefixed to @ from the second iteration of the loop
List<object> parameters = new List<object>();
parameters.Add(SqlHelper.BuildSqlParameter("Status", SqlDbType.VarChar, 10, "status", null, ParameterDirection.Output));
if (proctorStatus == "PAUSE")
parameters.Add(SqlHelper.BuildSqlParameter("ScheduleExtensionTime", SqlDbType.Int, sizeof(Int16), "ScheduleExtensionTime", scheduledUsersList.PauseTime));
parameters.Add(SqlHelper.BuildSqlParameter("ProctorSignal", SqlDbType.TinyInt, sizeof(Int16), "ProctorSignal", scheduledUsersList.ProctorSignal));
#endregion
foreach (Int64 scheduleUserID in scheduledUsersList.ScheduleUserID)
{
parameters.Add(SqlHelper.BuildSqlParameter("ScheduleDetailUserID", SqlDbType.BigInt, sizeof(Int64), "ScheduleDetailUserID", scheduleUserID));
proctoringUserListDT = SqlHelper.ExecuteDataTable(CommandType.StoredProcedure, "UspUpdateProctorSignalByScheduleUserID", parameters.ToArray(), false);
if (proctorStatus == "PAUSE")
parameters.RemoveAt(3);
else
parameters.RemoveAt(2);
}
}
実結果:
を。I 反復の場合
parameters | Count = 4
[0] {Status}
Value null
[1] {ScheduleExtensionTime}
Value 0
[2] {ProctorSignal}
Value 1
[3] {ScheduleDetailUserID}
Value 943417
declare @p1 varchar(10)
set @p1='S001'
exec UspUpdateProctorSignalByScheduleUserID @Status=@p1 output,@ScheduleExtensionTime=0,@ProctorSignal=1,@ScheduleDetailUserID=943417
select @p1
b. II 反復の場合
parameters | Count = 4
[0] {@Status}
Value "S001"
[1] {@ScheduleExtensionTime}
Value 0
[2] {@ProctorSignal}
Value 1
[3] {ScheduleDetailUserID}
Value 943419
declare @p1 varchar(10)
set @p1=NULL
exec UspUpdateProctorSignalByScheduleUserID @@Status=@p1 output,@@ScheduleExtensionTime=0,@@ProctorSignal=1,@ScheduleDetailUserID=943419
select @p1
期待される結果:
b. II 反復の場合
parameters | Count = 4
[0] {Status}
Value null
[1] {ScheduleExtensionTime}
Value 0
[2] {ProctorSignal}
Value 1
[3] {ScheduleDetailUserID}
Value 943419
declare @p1 varchar(10)
set @p1='S001'
exec UspUpdateProctorSignalByScheduleUserID @Status=@p1 output,@ScheduleExtensionTime=0,@ProctorSignal=1,@ScheduleDetailUserID=943419
select @p1
ここで、プロパティは 2 回目の反復以降に変更されます
> ParameterName = "@Status"
> ParameterNameFixed = "@Status"
> _parameterName = "@Status"
foreach ループ内で宣言および初期化すると、同じスニペットが完全に機能します。
しかし、foreach ループ内では、特定のインデックス 3 のリストif (proctorStatus == "PAUSE")を削除するかどうかを条件がチェックします。parameters.RemoveAt(3);
LINQorLambda演算子を使用して、つまり、ScheduleDetailUserIDループの各反復内で特定のオブジェクトを削除することによって、同じ条件を記述できますか?
SP で更新:
ALTER PROC [dbo].[UspUpdateProctorSignalByScheduleUserID]
(
@ScheduleDetailUserID BIGINT,
@ProctorSignal TINYINT,
@Status VARCHAR(5)='' OUTPUT,
@ScheduleExtensionTime INT=0
)
--WITH ENCRYPTION
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
/* ---#8*/
DECLARE @UserTestStatus TINYINT
SELECT @UserTestStatus = [Status]
FROM ScheduleUserDetail
WHERE ScheduleDetailUserID = @ScheduleDetailUserID
IF @UserTestStatus = 2 --#14
BEGIN
SET @Status='S004'
RETURN
END --#14
IF @UserTestStatus < 2 --#9
BEGIN
IF @ProctorSignal=2
BEGIN
UPDATE ScheduleUserDetail SET ProctorSignal=@ProctorSignal,ScheduleExtensionTime=(CASE WHEN ISNULL(@ScheduleExtensionTime,0)>0 THEN @ScheduleExtensionTime END), --#7
[Status]=@ProctorSignal
WHERE ScheduleDetailUserID=@ScheduleDetailUserID
SET @Status='S001'--Updated SuccessFully
SET @UserTestStatus = @ProctorSignal
END
ELSE
BEGIN
UPDATE ScheduleUserDetail SET ProctorSignal=@ProctorSignal,ScheduleExtensionTime=(CASE WHEN ISNULL(@ScheduleExtensionTime,0)>0 THEN @ScheduleExtensionTime END) --#7
WHERE ScheduleDetailUserID=@ScheduleDetailUserID
SET @Status='S001'--Updated SuccessFully
END
END
IF @Status='S001'
BEGIN
SELECT LoginName AS StudentName,@ProctorSignal AS ProctorSignal,
(
CASE WHEN @UserTestStatus = 2 AND @ProctorSignal=2 THEN 5 --Suspended #14
WHEN @UserTestStatus = 1 AND @ProctorSignal=1 THEN 6 --Paused #14
ELSE SUD.[Status]
END
) AS TestStatus --#10 --#11
FROM [User] U
INNER JOIN ScheduleUser SU ON SU.UserID=U.UserID
INNER JOIN ScheduleUserDetail SUD ON SUD.ScheduleDetailUserID=SU.ID
WHERE SU.ID=@ScheduleDetailUserID AND U.IsDeleted=0 AND SU.IsDeleted=0
END
END TRY
BEGIN CATCH
SET @Status='S002'--Update Failed
DECLARE @ErrorDetail AS VARCHAR(MAX)
SET @Errordetail ='EXEC dbo.UspUpdateProctorSignalByScheduleUserID @ScheduleDetailUserID='+CAST(ISNULL(@ScheduleDetailUserID,'') AS NVARCHAR(MAX))+',@ProctorSignal='+CAST(ISNULL(@ProctorSignal,'') AS NVARCHAR(MAX))+',@Status='+CAST(ISNULL(@Status,'') AS NVARCHAR(MAX))+',@ScheduleExtensionTime='+CAST(ISNULL(@ScheduleExtensionTime,'') AS NVARCHAR(MAX))
EXEC [GenerateErrorHandling] @ErrorDetail
DECLARE @Exception AS NVARCHAR(MAX)
SET @Exception=ERROR_MESSAGE() +'-> '+ @ErrorDetail
RAISERROR (@Exception, 16, 1)
END CATCH
SET NOCOUNT OFF;
END