0

我正在尝试将用户定义的错误从一个存储过程引发到 ac# 代码。我有一个将员工分配给用户的存储过程,例如,如果您已经将员工分配给用户 1,并且您尝试再次执行相同的操作,则存储过程应该引发错误,提示“此关联已存在”并返回代码,例如 1 和错误描述。问题在于,在 c 中,锐利没有经过 catch 部分。这是代码:

public bool InsertUser(Guid userId, string[][] IDs, AppParams myParams)
{
    bool flag = false;
    SqlTransaction transaction = null;

    using (var dbConn = new SqlConnection(this.ConnectionString))
    {
        using (var cmd = new SqlCommand())
        {
            try
            {
                dbConn.Open();
                cmd.Connection = dbConn;
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "InsertUser";

                transaction = dbConn.BeginTransaction();
                cmd.Transaction = transaction;

                for (int i = 0; i < IDs.Length; i++)
                {
                    flag = false;
                    cmd.Parameters.Clear();

                    cmd.Parameters.AddWithValue("@UserId", userId);
                    cmd.Parameters.AddWithValue("@EmployeeId", IDs[i][0]);
                    cmd.Parameters.AddWithValue("@CompanyId", myParams.ApplicationId);
                    cmd.Parameters.AddWithValue("@ModifiedUserId", myParams.User.UserId);

                    //add output parameter
                    cmd.Parameters.Add("@ID", SqlDbType.Int, 4);
                    cmd.Parameters["@ID"].Direction = ParameterDirection.Output;
                    cmd.Parameters.Add("@ReturnValue", SqlDbType.Int, 4);
                    cmd.Parameters["@ReturnValue"].Direction = ParameterDirection.ReturnValue;
                    cmd.Parameters.Add("@ErrorMsg", SqlDbType.VarChar, 300);
                    cmd.Parameters["@ErrorMsg"].Direction = ParameterDirection.Output;

                    cmd.ExecuteNonQuery();

                    var returnValue = Convert.ToInt32(cmd.Parameters["@ReturnValue"].Value);
                    flag = returnValue.Equals(0);

                    if (!flag)
                    {                                                                
                        if (cmd.Parameters["@ErrorMsg"].Value != DBNull.Value)
                        {
                            this.ErrorModel.HasError = true;
                            this.ErrorModel.ErrorMessage = cmd.Parameters["@ErrorMsg"].Value.ToString();
                        }

                        transaction.Rollback();                     
                        return false;                                
                    }
                }
                transaction.Commit();           
            }

            catch (SqlException sqlex)
            {               
                this.ErrorModel.HasError = true;
                this.ErrorModel.ErrorMessage = sqlex.Message;
            }
            catch (Exception ex)
            {           
                this.ErrorModel.HasError = true;
                this.ErrorModel.ErrorMessage = ex.Message;
            }           
        }
    }
    return flag;
}

难道我做错了什么?

这是我的 SQL 代码:

ALTER PROCEDURE [dbo].[InsertUser]
(
    @UserId             uniqueidentifier,
    @EmployeeId         int,
    @CompanyId          uniqueidentifier,
    @SystemStatusId     int = 1,
    @ModifiedByUserId   uniqueidentifier,
    @ID                 int output,
    @ErrorMsg           nvarchar(300) = NULL output
)
AS
BEGIN

    DECLARE @ReturnVal int

    SET NOCOUNT ON;

    SET @ReturnVal = 0;
    SET @ErrorMsg = null;

    --  check for existing combination
    IF EXISTS(SELECT 1 FROM [dbo].[UserRel]
               WHERE [UserId] = @UserId 
                 AND [EmployeeId] = @EmployeeId
                 AND [CompanyId] = @CompanyId
                 AND [SystemStatusId] = 1)
    BEGIN
            SET @ReturnVal = 1;
            SET @ErrorMsg = 'Item already Exist in Database'            
            RAISERROR @ErrorMsg, 0, 0
            GOTO ProcedureExit;
    END

    -- Insert statement
    INSERT [dbo].[UserRel]
    (
        [UserId],
        [EmployeeId],
        [CompanyId],
        [SystemStatusId],
        [ModifiedByUserId],
        [ModifiedDate]
    )
    VALUES
    (
        @UserId,
        @EmployeeId,
        @CompanyId,
        @SystemStatusId,
        @ModifiedByUserId,
        sysdatetimeoffset()
    )

    IF( @@ERROR <> 0 )
        BEGIN
            SET @ReturnVal = 2;
            SET @ErrorMsg = 'Failed to INSERT [dbo].[InsertUser]'
            GOTO ProcedureExit;
        END
    ELSE
        SET @ID = SCOPE_IDENTITY();

ProcedureExit:    
        RETURN @ReturnVal;

END
4

1 回答 1

2

问题在于,在 c 中,锐利没有经过 catch 部分。

因为在 C# 中,也不例外。您只需检查存储过程的返回值,然后决定回滚和return false;. 如果你想要一个例外:throw一个例外。

或者,如果 SQL 发出raiserror严重性为 16 或更高的 a,则会自动观察到异常。

顺便说一句,在真正异常的情况下,您的交易是否正确终止尚不清楚。我建议将回滚代码移到catch块中。由于无论您捕获哪个异常,您都会执行完全相同的操作,因此该catch (SqlException sqlex)块没有任何好处 - 所以您不妨删除它。

于 2013-10-01T19:48:17.823 回答