C#将SQL Server消息输出到文本文件

时间:2015-07-27 19:55:52

标签: c# sql sql-server

我是C#的新手,所以请耐心等待,因为我继承了一个我试图调整的脚本。

我想让SQL PRINT / RAISERROR语句的输出显示在已在脚本的另一部分中声明的日志文件中。

这是我打电话的方法:

public void ProcessData(string StoredProcedure, int StartDate, int EndDate, string Directory, string LogFileNameAndPath)
    {
        SqlConnection sqlConnection = null;
        SqlCommand sqlCommand = null;
        SqlParameter sqlParameter = null;
       // String outputText = null;

        try
        {
            sqlConnection = new SqlConnection(_ConnectionString);
            sqlConnection.Open();

            sqlCommand = new SqlCommand();
            sqlCommand.CommandType = CommandType.StoredProcedure;
            sqlCommand.CommandText = StoredProcedure;
            sqlCommand.Connection = sqlConnection;
            sqlCommand.CommandTimeout = 0;

            sqlParameter = new SqlParameter("@StartDt", SqlDbType.Int);
            sqlParameter.Value = StartDate;
            sqlCommand.Parameters.Add(sqlParameter);

            sqlParameter = new SqlParameter("@EndDt", SqlDbType.Int);
            sqlParameter.Value = EndDate;
            sqlCommand.Parameters.Add(sqlParameter);

            sqlParameter = new SqlParameter("@stringDirs", SqlDbType.VarChar);
            sqlParameter.Value = Directory;
            sqlCommand.Parameters.Add(sqlParameter);

            sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(OnInfoMessage);
            sqlCommand.ExecuteNonQuery();

        }
        catch (SqlException sqlEx)
        {
            throw sqlEx;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.ToString());
        }
        finally
        {
            if (sqlConnection != null)
            {
                if (sqlConnection.State != ConnectionState.Closed)
                {
                    sqlConnection.Close();
                }
            }
        }
    }

这是信息处理程序方法:

    public void OnInfoMessage(object sender, SqlInfoMessageEventArgs args)//, String LogFileNameAndPath)
    {
        foreach (SqlError err in args.Errors)
        {

            //File.AppendAllText(LogFileNameAndPath, err.Message);
            Console.WriteLine("{0}", err.Message);
            //return err.Message;
          //"The {0} has received a severity {1}, state {2} error number {3}\n" +
         // "on line {4} of procedure {5} on server {6}:\n{7}",
         //  err.Source, err.Class, err.State, err.Number, err.LineNumber,
         //  err.Procedure, err.Server, err.Message);
        }
    }

我想通过" File.AppendAllText(LogFileNameAndPath,err.Message)"将其写入LogFileNameAndPath变量,而不是输出到控制台。但是,我通过网络查看了很多帖子,NOBODY提供了解决方案。有没有办法做到这一点?请善待。谢谢!

=============================================== ============================

[ADDED 2015-07-27 1606 EDT] 如果我改变了这一行:

sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(OnInfoMessage);

...到......

sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(OnInfoMessage(LogFileNameAndPath));

......无法编译。 如何将此方法传递给方法?

以下是新方法:

    public void OnInfoMessage(object sender, SqlInfoMessageEventArgs args, String LogFileNameAndPath)
    {
        foreach (SqlError err in args.Errors)
        {

            File.AppendAllText(@LogFileNameAndPath, err.Message);
            //Console.WriteLine("{0}", err.Message);
          }
    }

3 个答案:

答案 0 :(得分:2)

虽然直接写入文件可能对您有用(请参阅@ FirebladeDan的答案),但强烈建议您使用现有的日志记录库以提高性能。

Log4Net是一个常见的建议,this link应该是一个很好的开始。 Log4Net有一些很好的功能可以帮助您,例如通过App.Config / Web.Config文件在运行时配置日志记录的功能,这样您就可以根据配置更改日志记录级别(详细程度)而无需重新编译。

希望这能让你走上正确的道路,祝你好运!

编辑:

根据您更新的声明,此选项可能就是您所需要的。

// use a variable to store the path.
private string logFileNameAndPath;

public void ProcessData(string StoredProcedure, int StartDate, int EndDate, string Directory, string LogFileNameAndPath)
{
   // Store the parameter that was passed in as the variable.
   this.logFileNameAndPath = LogFileNameAndPath;
   /* Do query setup work here*/
   sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(OnInfoMessage);
   sqlCommand.ExecuteNonQuery();
}

public void OnInfoMessage(object sender, SqlInfoMessageEventArgs args)
{
    foreach (SqlError err in args.Errors)
    {
        // Use the variable to indicate where to log to.
        File.AppendAllText(this.logFileNameAndPath, err.Message);
    }
}

希望这有助于您跨越终点。

答案 1 :(得分:1)

File.AppendAllText(@"pathgoeshere", err.Message);

补充:以下是如何使用AppConfig中的密钥获取值

String LogFileNameandPath = ConfigurationManager.AppSettings["keynamegoeshere"]);

将LogFileName和Path传递给您的方法**不要忘记添加引用

答案 2 :(得分:0)

您应该将日志文件名定义在别处,并在事件处理程序中可见,而不是尝试将日志文件名传递给事件处理程序。例如:

public class SqlHandler
{
    private readonly string m_LogFileNameAndPath = @"C:\log.txt";
    // or get it from AppConfig, as noted by FirebladeDan

    public void ProcessData() { /*...*/ }

    public void OnInfoMessage(object sender, SqlInfoMessageEventArgs args)
    {
        foreach(var err in args.Errors)
        {
            File.AppendAllText(m_LogFileNameAndPath, err.Message);
        }
    }
}

还值得注意的是,您仍然可以使用自定义文件的日志库(Log4Net,NLog等),告诉库要登录哪个文件。