Quick tip: how to programmatically monitor the SQL statements your Entity Framework LINQ queries generate
Posted: (EET/GMT+2)
Sometimes, developers ask me, what is the easiest way to monitor the SQL statements generated by your LINQ queries against your Entity Framework data model. If the backend database is SQL Server (as it often is), then I think SQL Server's Profiler is the easiest way to do this.
Although it draws a little on the database's power, usually running a profiling session for just a couple of minutes in a well-selected spot can give you valuable insight into the SQL queries that the database executes. And of course, if you happen to have SQL Server Profiler on your own development machine, nothing stops you from keeping the profiler running extensively.
Sometimes however, you'd like to know the SQL statement generated by a single LINQ query, and not a set of queries. In this case, you can ask for the SQL statement in code, like this:
using System.Data.Objects; ... string sql = ((ObjectQuery)myLinqQueryResultsObject).ToTraceString();
Here, I'm casting the resulting LINQ object to a class of type ObjectQuery, and then calling the ToTraceString method. Although this is a single-liner, I'd personally prefer an easier approach. But then again, once you know what to ask, the rest is easy.
Here's a complete example of a LINQ query:
NorthwindEntities entities = new NorthwindEntities();
var ordersAndLines = from o in entities.Orders
join d in entities.Order_Details on o.OrderID equals d.OrderID
join p in entities.Products on d.ProductID equals p.ProductID
where o.CustomerID == "ALFKI" & p.ProductID > 30
orderby o.OrderID
select new { OrderId = o.OrderID, Date = o.OrderDate,
OrderLines = o.Order_Details.Count };
And, after the ToTraceString method has been called on "ordersAndLines", the resulting SQL statement is:
SELECT [Project1].[OrderID] AS [OrderID], [Project1].[OrderDate] AS [OrderDate], [Project1].[C1] AS [C1] FROM ( SELECT [Filter1].[OrderID1] AS [OrderID], [Filter1].[OrderDate] AS [OrderDate], (SELECT COUNT(1) AS [A1] FROM [dbo].[Order Details] AS [Extent4] WHERE [Filter1].[OrderID1] = [Extent4].[OrderID]) AS [C1] FROM (SELECT [Extent1].[OrderID] AS [OrderID1], [Extent1].[OrderDate] AS [OrderDate], [Extent2].[ProductID] AS [ProductID] FROM [dbo].[Orders] AS [Extent1] INNER JOIN [dbo].[Order Details] AS [Extent2] ON [Extent1].[OrderID] = [Extent2].[OrderID] WHERE N'ALFKI' = [Extent1].[CustomerID] ) AS [Filter1] INNER JOIN [dbo].[Products] AS [Extent3] ON [Filter1].[ProductID] = [Extent3].[ProductID] WHERE [Extent3].[ProductID] > 30 ) AS [Project1] ORDER BY [Project1].[OrderID] ASC
Happy hacking!