从存储过程获取日志信息消息并同时处理异常

时间:2017-12-17 12:56:00

标签: sql sql-server

基本上我在字典中迭代一些项目,我试图在C#中使用TransactionScope从数据库中删除一些记录。我调用包含在TransactionScope内的存储过程。现在,当我的存储过程正在执行时,我正在对我的主存储过程中的其他存储过程进行多次调用。

当我解雇存储过程时,我使用严重级为10的Raiserror方法发送进度日志。

到目前为止一切都很好。它从存储过程发送所有raiserror消息。

我的问题是,如果存储过程中发生任何异常,那么它将进入存储过程内的catch方法。但是在C#方面,它并没有进入catch,而是将其视为正常流程,并继续下一个要删除的集合项目。

在C#端,我使用的是SqlInfoMessageEventHandler,它会触发我写的SqlInfoMessage。我想我在实施这个活动时犯了错误。

现在当我评论SqlInfoMessageEventHandler时,C#中的catch工作正常,它会按预期回滚所有更改。

我的代码如下。

public void Purge(string keyName, string[] keyValues, ILog logger)
{
    try
    {
       currentKeyName = keyName;

       for (var i = 0; i < keyValues.Length; i++)
       {
                currentKeyValue = keyValues[i];                    

                using (adoConnection = new SqlConnection())
                {
                    using (SqlCommand adoCommand = new SqlCommand())
                    {
                        adoCommand.CommandText = "procName";
                        adoCommand.CommandType = CommandType.StoredProcedure;
                        // Set up the parameters to be substituted into the SQL
                        // if app number then set the currentKeyValue and set empty for othe params                    

                        SqlParameter[] sqlParam = new SqlParameter[]
                        {
                            //fill up values for all params
                        };

                        adoCommand.Parameters.AddRange(sqlParam);

                        adoConnection.ConnectionString = connectionString;
                        adoConnection.InfoMessage += new SqlInfoMessageEventHandler(SQLInfoMessage);
                        adoConnection.FireInfoMessageEventOnUserErrors = true;
                        adoConnection.Open();

                        adoCommand.Connection = adoConnection;

                        logger.Info(String.Format("-------------------------------------------------------------------------------------------------------"));

                        logger.Info(String.Format("started for {0}: {1}", currentKeyName, currentKeyValue));
                        adoCommand.ExecuteNonQuery();
                        logger.Info(String.Format("finished successfully for {0}: {1}", currentKeyName, currentKeyValue));

                        logger.Info(String.Format("-------------------------------------------------------------------------------------------------------"));

                    }
                }
            }
        }
        catch (SqlException ex)
        {                
            if (logger.IsErrorEnabled) logger.Error(FormatSqlExceptionMessage(ex));                
    }
    catch (Exception ex)
    {
        if (logger.IsErrorEnabled) 
            logger.Error("Application Error.", ex);
    }
    finally
    {
        if (logger.IsDebugEnabled) 
            logger.Debug(String.Format("Closing Connection for: {0}", currentKeyValue));
    }
}

// Sql info method 
private void SQLInfoMessage(object sender, SqlInfoMessageEventArgs args)
{
    sleepTime = 100;

    if (args.Errors.Count > 0)
    {
        foreach (SqlError info in args.Errors)
        {
            if (info.Class > 9) // Severity
            {                        
                if (logger.IsErrorEnabled) 
                    logger.Error(String.Format("SQL: {0}", info.Message));
            }
            else
            {
                if (logger.IsInfoEnabled) 
                    logger.Info(String.Format("SQL: {0}", info.Message));
            }
        }
    }
    else
    {
        if (logger.IsInfoEnabled) 
            logger.Info(String.Format("SQL: {0}", args.Message));
    }
}

// TransactionScope Method 
foreach (KeyValuePair<string, List<string>> purgeRecord in purgeDictionary)
{
    foreach (string keyValue in purgeRecord.Value)
    {
        try
        {
            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
            {
                Purge(purgeRecord.Key, new string[] { keyValue }, Logger);
                transactionScope.Complete();
            }
        }
        catch (SqlException ex)
        {
            Logger.Error("Error occurred In InitiatePurgePendingProcess()" + ex.Message + ex.InnerException);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

如果要引发SqlException,请将FireInfoMessageEventOnUserErrors更改为false(默认值)。如果指定了true,则不会引发SqlException,而是使用错误调用消息处理程序。

adoConnection.FireInfoMessageEventOnUserErrors = false;