Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Resolve the SQL being executed behind the scenes in Entity Framework Core
public static class IQueryableExtensions
{
private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");
private static readonly PropertyInfo NodeTypeProviderField = QueryCompilerTypeInfo.DeclaredProperties.Single(x => x.Name == "NodeTypeProvider");
private static readonly MethodInfo CreateQueryParserMethod = QueryCompilerTypeInfo.DeclaredMethods.First(x => x.Name == "CreateQueryParser");
private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
private static readonly FieldInfo QueryCompilationContextFactoryField = typeof(Database).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompilationContextFactory");
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
{
throw new ArgumentException("Invalid query");
}
var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider);
var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler);
var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
var queryModel = parser.GetParsedQuery(query.Expression);
var database = DataBaseField.GetValue(queryCompiler);
var queryCompilationContextFactory = (IQueryCompilationContextFactory)QueryCompilationContextFactoryField.GetValue(database);
var queryCompilationContext = queryCompilationContextFactory.Create(false);
var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
var sql = modelVisitor.Queries.First().ToString();
return sql;
}
}

QueryCompilerTypeInfo not supproted at ASP.NET CORE application with build core1.1 version. Mb exist library where containst QueryCompilerTypeInfo class ?

Owner

rionmonster commented Apr 10, 2017

Hmmm.

I currently have this working as expected using EF Core 1.1.1 and building without any compilation errors.

Ensure that you have all of the following using statements added:

using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using System.Reflection;
using System.Linq;

Yes, i'm use this using statements but its not worked.
Mb you using specific package version EFCore or another?

using System;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Remotion.Linq.Parsing.Structure;

Core version 1.1

screen

raykrow commented Apr 14, 2017

Really appreciate this, I'm using Azure making profiling a pain so this was much needed. Could you please elaborate on the condition to throw an exception.

if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
{
    throw new ArgumentException("Invalid query");
}

When I ran this it threw the exception. Naturally I commented it out and tried again just to see. To my surprise it worked, still produced the sql. Why is it required here that my query be of either type EntityQueryable<TEntity> or InternalDbSet<TEntity>? Becuase my code tripped this logic and still worked I'm very curious.

Hi
It's work fine, but doesn't log my included relations. How i can solve this?

Thanks

zuosc commented Oct 26, 2017

Hi~

It's work fine, but when I use 'indexof' in ef,it seems not correct?

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment