Reputation: 814
I have implemented Entity Framework Logging according to the guideline from here. However, it only logs when there is no exception!!! I created an system.FormatException: Input string was not in a correct format.
by assigning more than allowed characters. My code is:
Databasecontext context=new DatabaseContext();
TableCity tbCity;
var logger = new MyLogger();
context.Database.Log = l => logger.Log("Table-tableNews", l);
tbCity.City ="sdkjfaksdjfsdjfjasdfjsdjfjdfjdjfjasdfjlasdjfljdfjdadsfdf";//varchar(25) in dbase
.......... //code removed for clarity
context.TableName.Add(tbCity);
try{
context.SaveChanges();
}
catch(Exception ex)
{}
My Log method
public void Log(string component, string messages)
{
//contents here, which works as desired
}
Do I need to implement differently to log exceptions?
Upvotes: 1
Views: 1035
Reputation: 29720
If you would have scrolled down on the link you mentioned you would have come across the IDbCommandInterceptor
interface. It is much more feature rich and it can tell whether the query was executed with succes or with a failure.
An example implementation could be:
public class LogDbCommandInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
interceptionContext.SetUserState("start", DateTime.Now);
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
Console.WriteLine($"sql command: {command.CommandText}, hasFailed: {HasFailed(interceptionContext)}, duration: {CalculateDuration(interceptionContext)}");
Console.WriteLine($"parameters: {FormatParams(command.Parameters)}, exception: {interceptionContext.Exception?.Message}");
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
interceptionContext.SetUserState("start", DateTime.Now);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
Console.WriteLine($"sql command: {command.CommandText}, hasFailed: {HasFailed(interceptionContext)}, duration: {CalculateDuration(interceptionContext)}");
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
interceptionContext.SetUserState("start", DateTime.Now);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
Console.WriteLine($"sql command: {command.CommandText}, hasFailed: {HasFailed(interceptionContext)}, duration: {CalculateDuration(interceptionContext)}");
}
private static double CalculateDuration<T>(DbCommandInterceptionContext<T> context)
{
return (DateTime.Now - (DateTime)context.FindUserState("start")).TotalMilliseconds;
}
private static bool HasFailed<T>(DbCommandInterceptionContext<T> context)
{
return context.OriginalException != null || (context.IsAsync && context.TaskStatus != TaskStatus.RanToCompletion);
}
private static string FormatParams(ICollection dbParameterCollection)
{
if (dbParameterCollection.Count == 0)
return string.Empty;
var parameterDescriptor = new StringBuilder();
foreach (SqlParameter parameter in dbParameterCollection)
{
parameterDescriptor.AppendFormat("{0} {1}: {2}, ", parameter.DbType, parameter.ParameterName, parameter.Value);
}
return parameterDescriptor.ToString().TrimEnd(' ', ',');
}
}
where Console.WriteLine
can be replaced of course with your own logger.
As you can see you can read an exception using the OriginalException property. The other properties of interest are listened here.
A short guide to registering your implementation can be found here as well:
Registering Interceptors Once a class that implements one or more of the interception interfaces has been created it can be registered with EF using the DbInterception class
Interceptors can also be registered at the app-domain level using the DbConfiguration code-based configuration
You can also configure interceptor using the app.config file
Upvotes: 2