34

I used to use the context.Log for tracing LINQ to SQL generated SQL Statements as shown in Sql Server Query Visualizer – Cannot see generated SQL Query

context.Log = new OutputWindowWriter();

For EF, is there anything similar and easy like the above approach?

LCJ
  • 22,196
  • 67
  • 260
  • 418

6 Answers6

30

In general you can hook up the built-in tracer or any logger by simple

context.Database.Log = msg => Trace.WriteLine(msg);

in the DbContext constructor. See more in MSDN. Some other approaches from MS are here (all based on DataContext.Log property).

Talking about the Clutch solution mentioned by Nate, it doesn't work with EF v6 (see this bug-report).

REFERENCES

  1. Logging and Intercepting Database Operations (EF6 Onwards)
  2. Logging and Intercepting Database Operations

Alex Klaus
  • 8,168
  • 8
  • 71
  • 87
  • im having an issue where update throws an exception and the sql it's trying to execute does not make it into the log.. – Sonic Soul Jun 23 '17 at 15:05
  • 6
    How can this the accepted answer, for a question referring Entity Framework 4.0, and all is mention here only works in EF 6? – edc65 Sep 13 '18 at 14:56
14

The Clutch.Diagnostics.EntityFramework (available in NuGet) works perfectly for me, and it's simpler than the EFTracingProvider.

UPDATE for EF 6:

Starting with Entity Framework 6, anytime Entity Framework sends a command to the database this command can be intercepted by application code. This is most commonly used for logging SQL, but can also be used to modify or abort the command.

Specifically, EF includes:
* A Log property for the context similar to DataContext.Log in LINQ to SQL.
* A mechanism to customize the content and formatting of the output sent to the log.
* Low-level building blocks for interception giving greater control/flexibility.

See http://msdn.microsoft.com/en-US/data/dn469464

Nate Cook
  • 8,395
  • 5
  • 46
  • 37
  • 1
    Wow, yeah, that was so much easier. Also no changes required to the rest of your source at all, which is nice. Good find! – Tim Perry Jun 25 '13 at 16:35
  • OK, so maybe I am dumb, but how to use Clutch Diagnostics? I tried the suggestion from http://girl-programmer.blogspot.de/2013/03/logging-and-tracing-sql-queries-using.html, and it didn't work for me :( More info in http://stackoverflow.com/questions/20995098/how-to-use-clutch-for-debugging-sql-statements-executed-by-the-entity-framework. – Rumi P. Jan 08 '14 at 12:14
  • It seems, Clutch doesn't work with EF 6. See https://github.com/Kukkimonsuta/Clutch/issues/4 – Alex Klaus Jun 02 '14 at 03:40
6

The EF Tracing Provider can output all SQL statements executed as traces. You can also use it to add your own logging if you want. Here's some code you could put in the constructor of your context class (this is for a DBContext, but the tweak to use ObjectContext should be pretty apparent):

// enable logging all queries executed by EF
var cx = ((IObjectContextAdapter)this).ObjectContext; // change to var cx = this; if using ObjectContext.
cx.EnableTracing();
cx.Connection.GetTracingConnections().ToList().ForEach(
    c =>
    {
        c.CommandExecuting += (s, e) => Log(e);
        c.CommandFailed += (s, e) => Log(e);
        c.CommandFinished += (s, e) => Log(e);
    });
Jonathan Rupp
  • 15,522
  • 5
  • 45
  • 61
2

Lots of solutions to this, but simplest in code is just call ToString() on the IQueryable of the LINQ statement.

var query = db.Employees.Where(x => x.ID = 1); //query will be an IQueryable object
var  sql = query.ToString();

This is only in EF4.1 on (previously calling ToTraceString on the ObjectQuery was the way to achieve this).

Judo
  • 5,167
  • 3
  • 24
  • 34
2

Expanding on Nate's answer for EF6, the NLogCommandInterceptor seen in Logging and Intercepting Database Operations only shows the CommandText.

If there was some particular parameter value that caused that commandText to fail, the parameters values aren't emitted to the log. In my case I wanted to log what values were causing Foreign Key violations.

This can be improved by altering NLogCommandInterceptor's LogIfError method like thus

private void LogIfError<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{
    if (interceptionContext.Exception != null)
    {
        var commandDumper = new DbCommandDumper(command);
        Log.Warn(Command failed:\r\n{0}", commandDumper.GetLogDump());
        // Exception will get logged further up the stack
    }
}

where the DbCommandDumper class reconstructs the DbCommand into TSQL that can be replayed into a test database.

fiat
  • 15,501
  • 9
  • 81
  • 103
  • For those seeking the "modern" (2017+ / asp.net core) way of doing things: This comment by fiat is what you are looking for. – XDS Jun 21 '17 at 10:34
  • Addendum: For those that want to dwelve deeper read this https://blog.oneunicorn.com/2013/05/14/ef6-sql-logging-part-3-interception-building-blocks/ – XDS Jun 21 '17 at 10:40
1

I believe you can use ToTraceString method of the ObjectQuery instance you have. Another approach would be to look at the IntelliTrace of Visual Studion as it logs SQL going out of your project.

Alexander Efimov
  • 2,685
  • 3
  • 18
  • 22