2010-07-20 7 views
9

Je sais que vous pouvez afficher le code SQL généré par NHibernate en le connectant à log4net ou en le redirigeant vers la console (option "show_sql"), mais est-il possible d'obtenir le code généré lors de l'exécution? Ce que je voudrais être capable de faire est de prendre un objet ICriteria (ou IQuery) et de vider le SQL généré à l'écran ou au journal personnalisé (pas log4net). Quelque chose comme ...Comment obtenir du code généré par NHibernate dans le code lors de l'exécution?

var sql = criteria.GetGeneratedSql() // Wishful thinking 

Est-ce que quelque chose comme ceci peut être fait?


EDIT: Merci à excellente trouvaille de DanP d'une classe "Hibernate Criteria to SQL Translation" pour Java, je pris une première fissure au portage de ce NHibernate. Semble fonctionner pour les cas simples, mais pourrait certainement utiliser une certaine amélioration (c.-à-gestion des erreurs, etc.)

using NHibernate.Engine; 
using NHibernate.Hql.Ast.ANTLR; 
using NHibernate.Impl; 
using NHibernate.Loader; 
using NHibernate.Loader.Criteria; 
using NHibernate.Persister.Entity; 

public class HibernateHqlAndCriteriaToSqlTranslator 
{ 
    public HibernateHqlAndCriteriaToSqlTranslator() { } 

    public ISessionFactory SessionFactory { get; set; } 

    public string ToSql(ICriteria criteria) 
    { 
     var c = (CriteriaImpl) criteria; 
     var s = (SessionImpl)c.Session; 
     var factory = (ISessionFactoryImplementor)s.SessionFactory; 
     String[] implementors = factory.GetImplementors(c.EntityOrClassName); 
     var loader = new CriteriaLoader(
      (IOuterJoinLoadable)factory.GetEntityPersister(implementors[0]), 
      factory, 
      c, 
      implementors[0], 
      s.EnabledFilters); 

     return ((OuterJoinLoader)loader).SqlString.ToString(); 
    } 

    public string ToSql(string hqlQueryText) 
    { 
     if (!String.IsNullOrEmpty(hqlQueryText)) 
     { 
      var translatorFactory = new ASTQueryTranslatorFactory(); 
      var factory = (ISessionFactoryImplementor) this.SessionFactory; 
      var translator = translatorFactory.CreateQueryTranslator(
       hqlQueryText, 
       hqlQueryText, 
       new Dictionary<String, IFilter>(), 
       factory); 
      translator.Compile(new Dictionary<String, String>(), false); 
      return translator.SQLString; 
     } 

     return null; 
    } 
} 
+1

http: //stackoverflow.com/questions/10704462/how-can-i-have-nhibernate-only-generate-the-sql-without-executing-it –

Répondre

5

Voici un article décrivant comment obtenir le sql sous-jacent à partir de hql ou de critères dans Hibernate; J'imagine d'utiliser le portage de cette NHibernate ne serait pas trop difficile:

http://narcanti.keyboardsamurais.de/hibernate-criteria-to-sql-translation.html

+0

super trouvaille, j'ai cherché une solution soignée .... maintenant je n'ai qu'à porter ce à NHibernate – Jaguar

+0

@Jaguar: d'accord, c'est assez lisse ... Je peux juste vous emballer à un port;) – DanP

+0

@DanP Très cool. Je ne peux pas croire que quelque chose comme ça n'est pas "intégré" – WayneC

0

Dans le passé, j'ai pu voir le code généré et envoyé à SQL par mise en veille prolongée via le Générateur de profils SQL outil. Selon vos objectifs, il peut être en mesure de fournir ce dont vous avez besoin.

2

Avec NHibernate 3.2, cela semble fonctionner pour obtenir le SQL d'une requête HQL:

private string GetSQL(string hql) 
{ 
    using (var iSession = ...) 
    { 
     var session = (NHibernate.Engine.ISessionImplementor)iSession; 
     var sf = (NHibernate.Engine.ISessionFactoryImplementor)iSession.SessionFactory; 

     var sql = new NHibernate.Engine.Query.HQLStringQueryPlan(hql, true, session.EnabledFilters, sf); 

     return string.Join(";", sql.SqlStrings); 
    } 
} 
Questions connexes