如何通过 SqlConnection 获取上次执行的 SQL 查询?

How to get last executed SQL query by SqlConnection?

我的代码可以访问一个 SqlConnection 对象。我无法访问所有其他 ADO.NET 对象,例如 SqlCommandSqlParameter 等。这些其他对象由 Dapper Extensions ORM 使用。

我的应用程序使用 SqlConnection 对象和 Dapper Extensions 方法执行 SQL 查询。 SQL 查询由 Dapper Extensions 自动生成;我无法访问生成的查询。我想记录此 SQL 查询。

我已经有了我的日志记录模块,我唯一需要的是连接对象执行的最后一个 SQL 查询。

如何获取 SqlConnection 最后执行的 SQL 查询?

以下内容不起作用,因为 SqlCommand 无法访问。

如果我获得底层 SqlCommand,我可以使用下面的代码从中构建查询;不幸的是,我无法访问它。

public string GetCommandLogString(IDbCommand command)
{
    string outputText;
    if(command.Parameters.Count == 0)
    {
        outputText = command.CommandText;
    }
    else
    {
        StringBuilder output = new StringBuilder();
        output.Append(command.CommandText);
        output.Append("; ");

        IDataParameter objIDataParameter;
        int parameterCount = command.Parameters.Count;
        for(int i = 0; i < parameterCount; i++)
        {
            objIDataParameter = (IDataParameter)command.Parameters[i];
            output.Append(string.Format("{0} = '{1}'", objIDataParameter.ParameterName, objIDataParameter.Value));

            if(i + 1 < parameterCount)
            {
                output.Append(", ");
            }
        }
        outputText = output.ToString();
    }
    return outputText;
}

我过去使用过的一种方法,当我不想依赖任何外部工具时(或者当缺少工具时,比如使用 MS Access 时)是使用数据库连接和命令“包装器”类 这样我就可以将日志记录添加到它们的任何方法或属性中。

要使用它,您将要使用的任何连接传递到 WrappedDbConnection 的构造函数中,如下所示:

using (var conn = new WrappedDbConnection(GetMyConnection()))
{
    // Do work using Dapper here against "conn"
}

(注意:当调用 WrappedDbConnection 实例的 Dispose 方法时,它将被传递到底层连接,因此您不需要 using WrappedDbConnection 和一个单独的 using 用于您的连接 - 您只需要一个 using,如上所示)。

下面定义了你需要的两个类。

请注意,方法 ExecuteNonQueryExecuteReaderExecuteReaderExecuteScalar 中有 Console.WriteLine 次调用,它们将写出查询将要执行的操作被执行。您可能希望根据您的要求更改此设置以在 完成 后写出查询,或者您可能希望使用 Console.Writeline 不同的输出,但这些更改应该足够简单使.

public class WrappedDbConnection : IDbConnection
{
    private readonly IDbConnection _conn;
    public WrappedDbConnection(IDbConnection connection)
    {
        if (connection == null)
            throw new ArgumentNullException(nameof(connection));

        _conn = connection;
    }

    public string ConnectionString
    {
        get { return _conn.ConnectionString; }
        set { _conn.ConnectionString = value; }
    }

    public int ConnectionTimeout
    {
        get { return _conn.ConnectionTimeout; }
    }

    public string Database
    {
        get { return _conn.Database; }
    }

    public ConnectionState State
    {
        get { return _conn.State; }
    }

    public IDbTransaction BeginTransaction()
    {
        return _conn.BeginTransaction();
    }

    public IDbTransaction BeginTransaction(IsolationLevel il)
    {
        return _conn.BeginTransaction(il);
    }

    public void ChangeDatabase(string databaseName)
    {
        _conn.ChangeDatabase(databaseName);
    }

    public void Close()
    {
        _conn.Close();
    }

    public IDbCommand CreateCommand()
    {
        return new WrappedDbCommand(_conn.CreateCommand());
    }

    public void Dispose()
    {
        _conn.Dispose();
    }

    public void Open()
    {
        _conn.Open();
    }
}

public class WrappedDbCommand : IDbCommand
{
    private readonly IDbCommand _cmd;
    public WrappedDbCommand(IDbCommand command)
    {
        if (command == null)
            throw new ArgumentNullException(nameof(command));

        _cmd = command;
    }

    public string CommandText
    {
        get { return _cmd.CommandText; }
        set { _cmd.CommandText = value; }
    }

    public int CommandTimeout
    {
        get { return _cmd.CommandTimeout; }
        set { _cmd.CommandTimeout = value; }
    }

    public CommandType CommandType
    {
        get { return _cmd.CommandType; }
        set { _cmd.CommandType = value; }
    }

    public IDbConnection Connection
    {
        get { return _cmd.Connection; }
        set { _cmd.Connection = value; }
    }

    public IDataParameterCollection Parameters
    {
        get { return _cmd.Parameters; }
    }

    public IDbTransaction Transaction
    {
        get { return _cmd.Transaction; }
        set { _cmd.Transaction = value; }
    }

    public UpdateRowSource UpdatedRowSource
    {
        get { return _cmd.UpdatedRowSource; }
        set { _cmd.UpdatedRowSource = value; }
    }

    public void Cancel()
    {
        _cmd.Cancel();
    }

    public IDbDataParameter CreateParameter()
    {
        return _cmd.CreateParameter();
    }

    public void Dispose()
    {
        _cmd.Dispose();
    }

    public int ExecuteNonQuery()
    {
        Console.WriteLine($"[ExecuteNonQuery] {_cmd.CommandText}");
        return _cmd.ExecuteNonQuery();
    }

    public IDataReader ExecuteReader()
    {
        Console.WriteLine($"[ExecuteReader] {_cmd.CommandText}");
        return _cmd.ExecuteReader();
    }

    public IDataReader ExecuteReader(CommandBehavior behavior)
    {
        Console.WriteLine($"[ExecuteReader({behavior})] {_cmd.CommandText}");
        return _cmd.ExecuteReader();
    }

    public object ExecuteScalar()
    {
        Console.WriteLine($"[ExecuteScalar] {_cmd.CommandText}");
        return _cmd.ExecuteScalar();
    }

    public void Prepare()
    {
        _cmd.Prepare();
    }
}