Edit

Query tags

Query tags help correlate LINQ queries in code with generated SQL queries captured in logs. You annotate a LINQ query using the new TagWith() method:

Tip

You can view this article's sample on GitHub.

var myLocation = new Point(1, 2);
var nearestPeople = await (from f in context.People.TagWith("This is my spatial query!")
                     orderby f.Location.Distance(myLocation) descending
                     select f).Take(5).ToListAsync();

This LINQ query is translated to the following SQL statement:

-- This is my spatial query!

SELECT TOP(@__p_1) [p].[Id], [p].[Location]
FROM [People] AS [p]
ORDER BY [p].[Location].STDistance(@__myLocation_0) DESC

It's possible to call TagWith() many times on the same query. Query tags are cumulative. For example, given the following methods:

private static IQueryable<Person> GetNearestPeople(SpatialContext context, Point myLocation)
    => from f in context.People.TagWith("GetNearestPeople")
       orderby f.Location.Distance(myLocation) descending
       select f;

private static IQueryable<T> Limit<T>(IQueryable<T> source, int limit) => source.TagWith("Limit").Take(limit);

The following query:

var results = await Limit(GetNearestPeople(context, new Point(1, 2)), 25).ToListAsync();

Translates to:

-- GetNearestPeople
-- Limit

SELECT TOP(@__p_1) [p].[Id], [p].[Location]
FROM [People] AS [p]
ORDER BY [p].[Location].STDistance(@__myLocation_0) DESC

It's also possible to use multi-line strings as query tags. For example:

            var results = await Limit(GetNearestPeople(context, new Point(1, 2)), 25).TagWith(
                @"This is a multi-line
string").ToListAsync();

Produces the following SQL:

-- GetNearestPeople
-- Limit
-- This is a multi-line
-- string

SELECT TOP(@__p_1) [p].[Id], [p].[Location]
FROM [People] AS [p]
ORDER BY [p].[Location].STDistance(@__myLocation_0) DESC

Tagging with file name and line number

Queries can be automatically tagged with the file name and line number where the LINQ query is defined in source code. This is done using the TagWithCallSite method:

var myLocation = new Point(1, 2);
var closestPeople = await (from f in context.People.TagWithCallSite()
                     orderby f.Location.Distance(myLocation) descending
                     select f).Take(5).ToListAsync();

This query translates to (the actual line number will reflect where the query is defined in the source file):

-- file: C:\Work\EntityFramework.Docs\samples\Program.cs:23

SELECT TOP(@__p_1) [p].[Id], [p].[Location]
FROM [People] AS [p]
ORDER BY [p].[Location].STDistance(@__myLocation_0) DESC

Known limitations

Query tags aren't parameterizable: EF Core always treats query tags in the LINQ query as string literals that are included in the generated SQL. Compiled queries that take query tags as parameters aren't allowed.