I did this by creating a wrapper class around an ObjectContext and using that wrapper instead of the original context. Here is an example of a context wrapper:
public partial class LoggedContext : MyContext { public LoggedContext() : this("name=MyEntities")
I also have a static class that defines a trace output method and has a static method to initialize the trace. Here:
public static class EFTracingExtensions { private static ILogger _logger; public static void InitSqlTracing(ILogger logger) { _logger = logger; EFTracingProviderConfiguration.RegisterProvider(); if (logger.IsLoggingEnabled()) // Don't add logging hooks if logging isn't enabled { EFTracingProviderConfiguration.LogAction = new Action<CommandExecutionEventArgs>(AppendSqlLog); } } private static void AppendSqlLog(CommandExecutionEventArgs e) { if (e.Status != CommandExecutionStatus.Executing) // we only care about Finished and Failed { StringBuilder msg = new StringBuilder(e.ToTraceString().TrimEnd()); msg.Append(Environment.NewLine); if (e.Result is SqlDataReader) { int rows = ((SqlDataReader)e.Result).HasRows ? ((SqlDataReader)e.Result).RecordsAffected : 0; msg.AppendFormat("*** {0} rows affected", rows); } else if (e.Result is int) { msg.AppendFormat("*** result: {0}", e.Result); } else { msg.AppendFormat("*** finished, result: {0}", e.Result); } msg.Append(Environment.NewLine); msg.AppendFormat(" [{0}] [{1}] in {2} seconds", e.Method, e.Status, e.Duration); _logger.Log(msg.ToString(), LoggerCategories.SQL); } } }
ILogger is the logging interface that I use. You need to substitute your own interface / methods.
The InitSqlTracing method runs once when my program starts, and then the LoggedContext class is used to register all the SQL generated by the Entity Framework.
Putting it all together with your sample code:
EFTracingExtensions.InitSqlTracing(logger); // only call this once using (var context = new LoggedContext()) { var a = from data in context.Projects select data; }
source share