In a previous post, I demonstrated a bit of code that uses Reflection to retrieve a proper materialized trace string from Entity Framework 1.1. The 2.0 preview release of EF broke that code, though.
The code is pretty easy to fix. The .NET team only changed the structure of the private/protected members slightly. The one thing that was changed as the QueryCompilationContextFactory. It now is stored within a private member named “Dependencies” of type “DatabaseDependencies” which has the QueryCompilationContextFactory as a member. Without further adieu, here’s the code updated to support EF 2.0.
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 PropertyInfo DatabaseDependenciesProperty = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); /// <summary> /// Retrieve trace string for IQueryable /// </summary> /// <param name="query"></param> /// <returns></returns> public string GetTraceString<T>(IQueryable<T> query) { var str = query.ToString(); var provider = query.Provider; var fields = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields; var properties = typeof(EntityQueryProvider).GetTypeInfo().DeclaredProperties; try { var queryCompiler = 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 databaseDependencies = (DatabaseDependencies)DatabaseDependenciesProperty.GetValue(database); var queryCompilationContextFactory = databaseDependencies.QueryCompilationContextFactory; var queryCompilationContext = queryCompilationContextFactory.Create(false); var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor(); modelVisitor.CreateQueryExecutor<T>(queryModel); var sql = modelVisitor.Queries.First().ToString(); return sql; } catch (Exception ex) { Console.WriteLine(ex); throw ex; } }
One thought on “Entity Framework Core 2.0 Trace Strings”