복붙노트

[SQL] 어떻게 NHibernate에 단지 그것을 실행하지 않고 SQL을 생성 할 수 있습니다?

SQL

어떻게 NHibernate에 단지 그것을 실행하지 않고 SQL을 생성 할 수 있습니다?

나는 show_sql 구성 옵션을 사용하여 런타임에 log4net / NLog에 SQL / 추적 창을 로그인하는 방법을 알고있다.

내가 찾고주고 쿼리 () 자 NHibernate에 생성 된 SQL을 검색하는 방법입니다.

나는 Persister 클래스, 드라이버, 다른 인터셉터 및 이벤트를 통해 보았습니다. 에도 큰 도움이 될 것입니다 내 검색 범위를 좁혀 보면 너무 많은 장소가있다.

해결법

  1. ==============================

    1.다음과 같은 방법으로 실행하지 않고 생성 된 SQL 쿼리를 얻을 수 있습니다 :

    다음과 같은 방법으로 실행하지 않고 생성 된 SQL 쿼리를 얻을 수 있습니다 :

    NHibernate.Linq 쿼리 :

    public String GetGeneratedSql(System.Linq.IQueryable queryable, ISession session)
    {
        var sessionImp = (ISessionImplementor) session;
        var nhLinqExpression = new NhLinqExpression(queryable.Expression, sessionImp.Factory);
        var translatorFactory = new ASTQueryTranslatorFactory();
        var translators = translatorFactory.CreateQueryTranslators(nhLinqExpression, null, false, sessionImp.EnabledFilters, sessionImp.Factory);
    
        return translators[0].SQLString;
    }
    

    기준 쿼리 :

    public String GetGeneratedSql(ICriteria criteria)
    {
        var criteriaImpl = (CriteriaImpl) criteria;
        var sessionImpl = (SessionImpl) criteriaImpl.Session;
        var factory = (SessionFactoryImpl) sessionImpl.SessionFactory;
        var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
        var loader = new CriteriaLoader((IOuterJoinLoadable) factory.GetEntityPersister(implementors[0]), factory, criteriaImpl, implementors[0], sessionImpl.EnabledFilters);
    
        return loader.SqlString.ToString();
    }
    

    QueryOver 쿼리 :

    public String GetGeneratedSql(IQueryOver queryOver)
    {
        return GetGeneratedSql(queryOver.UnderlyingCriteria);
    }
    

    HQL 질의의 경우 :

    public String GetGeneratedSql(IQuery query, ISession session)
    {
        var sessionImp = (ISessionImplementor)session;
        var translatorFactory = new ASTQueryTranslatorFactory();
        var translators = translatorFactory.CreateQueryTranslators(query.QueryString, null, false, sessionImp.EnabledFilters, sessionImp.Factory);
    
        return translators[0].SQLString;
    }
    
  2. ==============================

    2.NHibernate에 5.2를 들어 경우에 당신이 (당신이 cmd.Parameters 모두 cmd.CommandText에서 SQL 및 제공된 매개 변수를 확인할 수 있도록) 실제 DbCommand 쿼리 준비보고 싶어 :

    NHibernate에 5.2를 들어 경우에 당신이 (당신이 cmd.Parameters 모두 cmd.CommandText에서 SQL 및 제공된 매개 변수를 확인할 수 있도록) 실제 DbCommand 쿼리 준비보고 싶어 :

    //For LINQ
    public IEnumerable<DbCommand> GetDbCommands<T>(IQueryable<T> query, ISession s)
    {
        return GetDbCommands(LinqBatchItem.Create(query), s);
    }
    
    //For HQL
    public IEnumerable<DbCommand> GetDbCommands(IQuery query, ISession s)
    {
        return GetDbCommands(new QueryBatchItem<object>(query), s);
    }
    
    //For QueryOver
    public IEnumerable<DbCommand> GetDbCommands(IQueryOver query, ISession s)
    {
        return GetDbCommands(query.RootCriteria, s);
    }
    
    //For Criteria
    public IEnumerable<DbCommand> GetDbCommands(ICriteria query, ISession s)
    {
        return GetDbCommands(new CriteriaBatchItem<object>(query), s);
    }
    
    //Adapted from Loader.PrepareQueryCommand
    private static IEnumerable<DbCommand> GetDbCommands(IQueryBatchItem item, ISession s)
    {
        var si = s.GetSessionImplementation();
        item.Init(si);
        var commands = item.GetCommands();
        foreach (var sqlCommand in commands)
        {
            var sqlString = sqlCommand.Query;
            sqlCommand.ResetParametersIndexesForTheCommand(0);
            var command = si.Batcher.PrepareQueryCommand(System.Data.CommandType.Text, sqlString, sqlCommand.ParameterTypes);
            RowSelection selection = sqlCommand.QueryParameters.RowSelection;
            if (selection != null && selection.Timeout != RowSelection.NoValue)
            {
                command.CommandTimeout = selection.Timeout;
            }
    
            sqlCommand.Bind(command, si);
    
            IDriver driver = si.Factory.ConnectionProvider.Driver;
            driver.RemoveUnusedCommandParameters(command, sqlString);
            driver.ExpandQueryParameters(command, sqlString, sqlCommand.ParameterTypes);
            yield return command;
        }
    }
    
  3. ==============================

    3.NHibernate에 버전 3.4을 기반으로 LINQ 표현하는 방법은 다음과 같습니다

    NHibernate에 버전 3.4을 기반으로 LINQ 표현하는 방법은 다음과 같습니다

    public String GetGeneratedSql(System.Linq.IQueryable queryable, ISession session)
          {
             var sessionImp = (ISessionImplementor)session;
             var nhLinqExpression = new NhLinqExpression(queryable.Expression,              
                                         sessionImp.Factory);
             var translatorFactory = new ASTQueryTranslatorFactory();
             var translators = translatorFactory.CreateQueryTranslators(nhLinqExpression.Key, nhLinqExpression, null, false,
                                                                    sessionImp.EnabledFilters, sessionImp.Factory);
    
             var sql = translators.First().SQLString;
             var formamttedSql = FormatStyle.Basic.Formatter.Format(sql);
             int i = 0;
             var map = ExpressionParameterVisitor.Visit(queryable.Expression, sessionImp.Factory).ToArray();
             formamttedSql = Regex.Replace(formamttedSql, @"\?", m => map[i++].Key.ToString().Replace('"', '\''));
    
             return formamttedSql;
          }
    
  4. ==============================

    4.다음은 NH 5.2 (상단의 HQL 부분이 해결되지 않는 투표를하게 나타났다 NH 4.0.4의 주요 변경)으로 HQL에서 SQL을 생성하는 방법을 수 있습니다 :

    다음은 NH 5.2 (상단의 HQL 부분이 해결되지 않는 투표를하게 나타났다 NH 4.0.4의 주요 변경)으로 HQL에서 SQL을 생성하는 방법을 수 있습니다 :

    public string HqlToSql(string hql, ISession session)
    {
        var sessionImp = (ISessionImplementor)session;
        var translatorFactory = new ASTQueryTranslatorFactory();
        var translators = translatorFactory.CreateQueryTranslators(new NHibernate.Hql.StringQueryExpression(hql),
             null, false, sessionImp.EnabledFilters, sessionImp.Factory);
        var hqlSqlGenerator = new HqlSqlGenerator(((QueryTranslatorImpl)translators[0]).SqlAST, sessionImp.Factory);
        hqlSqlGenerator.Generate();
        return hqlSqlGenerator.Sql.ToString();
    }
    
  5. from https://stackoverflow.com/questions/10704462/how-can-i-have-nhibernate-only-generate-the-sql-without-executing-it by cc-by-sa and MIT license