I know you can view the NHibernate generated SQL by hooking it up to log4net or piping it out to the console ("show_sql" option), but is there any way to obtain the generated SQL in code at runtime?
What I would like to be able to do is take an ICriteria object (or IQuery) and dump the generated SQL to the screen or custom log (not log4net). Something like...
var sql = criteria.GetGeneratedSql() // Wishful thinking
Can something like this be done?
EDIT: Thanks to DanP's excellent find of a "Hibernate Criteria to SQL Translation" class for Java, I took a first crack at porting this to NHibernate. Seems to work for simple cases, but definitely could use some improvement (i.e. error handling, 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;
}
}