2016-05-30 79 views
4

我正在使用實體框架7核心RC2,我需要查看正在生成的SQL代碼。在實體框架的早期版本,我可以使用以下方法:從EF7查詢中獲取SQL代碼

String sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString(); 

如果查詢是一個IQueryable對象......但ToTraceString不提供EF7。

如何在EF7中做類似的事情?

+2

[如何使用實體框架7登錄查詢?(HTTP的可能重複: //stackoverflow.com/questions/26747837/how-to-log-queries-using-entity-framework-7) –

+0

你可以試試這個:http://rion.io/2016/10/19/accessing-entity-框架 - 核心查詢,這背後的幕後,在-ASP網核心/。 – mikebridge

回答

2

由於EF 7被重命名爲Entity Framework Core,因此我將總結EF Core的選項。

有從IQueryable<>登錄SQL語句的方法3:

  • 使用內置或自定義日誌。使用您選擇的記錄器或.NET Core中的內置記錄器記錄正在執行的查詢,如this tutorial中所述。使用輪廓儀。使用像MiniProfiler這樣的SQL Profiler來監視正在執行的查詢。
  • 使用瘋狂的反射代碼。您可以實現一些類似於舊方法的自定義反射代碼來執行相同的基本概念。

這裏是瘋狂的反射代碼(擴展方法):

public static class QueryableExtensions 
{ 
    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; 
    } 
} 

添加此擴展方法來你的代碼後,您可以使用方法如下:

// Build a query using Entity Framework 
var query = _context.Widgets.Where(w => w.IsReal && w.Id == 42); 
// Get the generated SQL 
var sql = query.ToSql(); 

推薦: http://rion.io/2016/10/19/accessing-entity-framework-core-queries-behind-the-scenes-in-asp-net-core/https://gist.github.com/rionmonster/2c59f449e67edf8cd6164e9fe66c545a

0

作爲公共服務:

var someQuery = (
    from projects in _context.projects 
    join issues in _context.issues on projects.Id equals issues.ProjectId into tmpMapp 
    from issues in tmpMapp.DefaultIfEmpty() 
    select issues 
) //.ToList() 
; 

// string sql = someQuery.ToString(); 
// string sql = Microsoft.EntityFrameworkCore.IQueryableExtensions.ToSql(someQuery); 
// string sql = Microsoft.EntityFrameworkCore.IQueryableExtensions1.ToSql(someQuery); 
// using Microsoft.EntityFrameworkCore; 
string sql = someQuery.ToSql(); 
System.Console.WriteLine(sql); 

,然後將這些擴展方法(IQueryableExtensions1用於.NET 1.0的核心,IQueryableExtensions用於.NET核2.0):

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; 


namespace Microsoft.EntityFrameworkCore 
{ 

    // https://stackoverflow.com/questions/1412863/how-do-i-view-the-sql-generated-by-the-entity-framework 
    // http://rion.io/2016/10/19/accessing-entity-framework-core-queries-behind-the-scenes-in-asp-net-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 PropertyInfo DatabaseDependenciesField = 
      typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); 

     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 = (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) DatabaseDependenciesField.GetValue(database); 
      var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false); 
      var modelVisitor = (RelationalQueryModelVisitor) queryCompilationContext.CreateQueryModelVisitor(); 
      modelVisitor.CreateQueryExecutor<TEntity>(queryModel); 
      var sql = modelVisitor.Queries.First().ToString(); 

      return sql; 
     } 
    } 



    public class IQueryableExtensions1 
    { 
     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>(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; 
     } 


    } 


}