> 백엔드 개발 > C++ > Entity Framework Core IQueryable에서 SQL 코드를 검색하는 방법은 무엇입니까?

Entity Framework Core IQueryable에서 SQL 코드를 검색하는 방법은 무엇입니까?

Mary-Kate Olsen
풀어 주다: 2025-01-02 17:11:38
원래의
611명이 탐색했습니다.

How to Retrieve SQL Code from an Entity Framework Core IQueryable?

Entity Framework Core IQueryable에서 SQL 코드 가져오기

개발자에게 IQueryable 개체에 의해 생성된 SQL 코드를 제공하는 Entity Framework Core의 ToTraceString 메서드는, 최신 버전에서는 사용할 수 없습니다. 이 문서에서는 사용 중인 버전에 따라 Entity Framework Core에서 SQL 코드를 검색하는 대체 방법을 살펴봅니다.

EF Core 5/6(Net 5/6)

EF Core 5 및 6 (Net 5 및 6), ToQueryString 메소드를 사용하여 쿼리에 대한 SQL 코드를 얻을 수 있습니다:

var query = _context.Widgets.Where(w => w.IsReal && w.Id == 42);  
var sql = query.ToQueryString();
로그인 후 복사

Core 2.1.2

이전 버전의 Net Core의 경우 사용자 지정 확장 방법을 사용할 수 있습니다.

using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Query.Expressions;
using Microsoft.EntityFrameworkCore.Query.Sql;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

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 FieldInfo QueryModelGeneratorField = typeof(QueryCompiler).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryModelGenerator");
        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)
        {
            var queryCompiler = (QueryCompiler) QueryCompilerField.GetValue(query.Provider);
            var queryModelGenerator = (QueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler);
            var queryModel = queryModelGenerator.ParseQuery(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;
        }
    }
로그인 후 복사

EF Core 3.0

EF Core 3.0에서는 다음 확장을 사용할 수 있습니다. 다음 방법을 사용할 수 있습니다:

        public static string ToSql<TEntity>(this IQueryable<TEntity> query)
        {
            using var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
            var enumeratorType = enumerator.GetType();
            var selectFieldInfo = enumeratorType.GetField(&quot;_selectExpression&quot;, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($&quot;cannot find field _selectExpression on type {enumeratorType.Name}&quot;);
            var sqlGeneratorFieldInfo = enumeratorType.GetField(&quot;_querySqlGeneratorFactory&quot;, BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($&quot;cannot find field _querySqlGeneratorFactory on type {enumeratorType.Name}&quot;);
            var selectExpression = selectFieldInfo.GetValue(enumerator) as SelectExpression ?? throw new InvalidOperationException($&quot;could not get SelectExpression&quot;);
            var factory = sqlGeneratorFieldInfo.GetValue(enumerator) as IQuerySqlGeneratorFactory ?? throw new InvalidOperationException($&quot;could not get IQuerySqlGeneratorFactory&quot;);
            var sqlGenerator = factory.Create();
            var command = sqlGenerator.GetCommand(selectExpression);
            var sql = command.CommandText;
            return sql;
        }
로그인 후 복사

EF Core 3.1

마지막으로 EF Core 3.1에서는 다음 확장 메서드를 사용하여 SQL 코드를 얻을 수 있습니다.

using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Query;

public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
    using var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
    var relationalCommandCache = enumerator.Private(&quot;_relationalCommandCache&quot;);
    var selectExpression = relationalCommandCache.Private<SelectExpression>(&quot;_selectExpression&quot;);
    var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>(&quot;_querySqlGeneratorFactory&quot;);

    var sqlGenerator = factory.Create();
    var command = sqlGenerator.GetCommand(selectExpression);

    string sql = command.CommandText;
    return sql;
}

private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
private static T Private<T>(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
로그인 후 복사

Entity Framework Core에서 ToTraceString 노출과 관련된 기본 문제는 다음을 통해 해결되었습니다. EF 팀에서 발생했으며 향후 릴리스에서 해결될 것으로 예상됩니다.

위 내용은 Entity Framework Core IQueryable에서 SQL 코드를 검색하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿