2012-05-22 9 views
43

Ich weiß, wie Sie das SQL in log4net/NLog/Trace-Fenster zur Laufzeit mit der show_sql Konfigurationsoption protokollieren.Wie kann ich NHibernate nur das SQL generieren lassen, ohne es auszuführen?

Was ich suche ist eine Möglichkeit, eine Query<T>() zu geben NHibernate abrufen die generierte SQL.

Ich habe die Persister-Klasse, die Treiber, verschiedene Interzeptoren und Ereignisse durchgesehen. Es gibt so viele Orte, an denen man sich umsehen kann, selbst eine Eingrenzung meiner Suche wäre sehr hilfreich.

+0

Was ich ist ein armer Mann Profiler der Art zu erreichen bin versucht. Ich möchte nur wissen, wie eine bestimmte linq-Abfrage aus einem Testcode ausgewertet wird. – hometoast

Antwort

84

Sie können die generierten SQL-Abfragen ohne Ausführung mit den folgenden Methoden erhalten:

Für die NHibernate.Linq Anfragen:

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; 
} 

Für Criteria Queries:

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(); 
} 

Für QueryOver Abfragen:

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

Für HQL-Abfragen:

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; 
} 
+0

Gibt es eine Möglichkeit, dies für HQL-Abfragen zu tun? –

+0

Meine Antwort mit HQL-Abfragen aktualisiert. – Gerard

+1

@Gerard Ich habe deine sehr nützliche Antwort aufgefrischt. Haben Sie eine Idee, ob dies für INSERTs - UPDATEs möglich ist? Siehe http://stackoverflow.com/questions/10786934/how-can-i-get-nhibernate-to-give-me-the-sql-it-wo- l-generate-for-an-sert-up- Danke Danke! –

1

Basierend auf der NHibernate Version 3.4 das Verfahren zum Linq Ausdruck ist:

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; 
     } 
+0

Gibt es sogar eine Möglichkeit, eine SQL-Zeichenfolge zu einem HQL oder zu einem Queryover zu konvertieren? – Franki1986

Verwandte Themen