Practical Query Tagging in EF Core
What is query tags in EF Core?
It’s introduced in EF Core 2.2. This feature helps correlate LINQ queries in code with generated SQL queries captured in logs. You annotate a LINQ query using the new
TagWith()
method.
var publishedBlogPosts = dbContext.BlogPosts
.Where(b => b.PublishedAt != null)
.TagWith("Getting published blog posts")
.ToList();
When EF generates the SQL with TagWith
method, it also includes the tag as a comment in the query; as a result, debugging and profiling queries might be easier.
-- Getting published blog postsSELECT [b].[BlogPostId], [b].[Content], [b].[PublishedAt], [b].[Title]
FROM [BlogPosts] AS [b]
WHERE [b].[PublishedAt] IS NOT NULL
How to make it more practical?
Debugging and profiling are all about having more information. We can easily access member name, line of code and source file with caller information attributes.
Now take a look to my extension method:
It retrieves method name, file path and line number from the compiler and apply it on any IQueryable<T>
.
Usage Example:
var publishedBlogPosts = dbContext.BlogPosts
.Where(b => b.PublishedAt != null)
.TagWithSource("Getting published blog posts")
.ToList();
The generated SQL will be something like this:
-- Getting published blog posts
-- Main - D:\Projects\Sample1\Program.cs:17SELECT [b].[BlogPostId], [b].[Content], [b].[PublishedAt], [b].[Title]
FROM [BlogPosts] AS [b]
WHERE [b].[PublishedAt] IS NOT NULL
There is some limitation for this practice, for example on situations like inheriting from BaseRepository
you’ll get information about the base class, not the derived class.
Conclusion
Query tagging is a nice feature from EF Core, combining it with caller information is excellent for debugging.