Actually, my scenario is bit different than mentioned here. I have asked other question. But as I am not getting solution there, I decided to change the approach.
I have a SqlConnection
object accessible to my code. All other ADO.NET objects like SqlCommand
, SqlParameter
etc are not accessible to me. These other objects are consumed by Dapper Extensions ORM.
My application executes SQL queries using SqlConnection
object and Dapper Extensions method. SQL query is auto generated by Dapper Extensions; generated query is not accessible to me. I want to log this SQL query.
I already have my logging module in place and the only thing I need is the last SQL query executed by connection object.
How to get last executed SQL query by SqlConnection
?
Following does not work because SqlCommand
is not accessible.
If I get underlying SqlCommand
, I can build the query from it using the code below; unfortunately, it is not accessible to me.
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;
}
An approach that I've used in the past, when I didn't want to rely upon any external tools (or when the tools were lacking, like when working with Access) is to use database connection and command "wrapper" classes so that I can add logging to any of their methods or properties.
To use it, you pass whatever connection you want to use into the WrappedDbConnection's constructor -
(Note: When the WrappedDbConnection instance's Dispose method is called, that will be passed onto the underlying connection and so you don't need a "using" for the WrappedDbConnection and a separate "using" for your connection - you only need one "using", as shown above).
The two classes that you need are defined below.
Note that there are Console.WriteLine calls in the methods "ExecuteNonQuery", "ExecuteReader", "ExecuteReader" and "ExecuteScalar" that will write out what query is about to be executed. You may want to change this for your requirements to write out the query after it's completed or you might want to use a different output that Console.Writeline but those should be simple enough changes to make.