在标准执行之前,从NHibernate标准获取SQL查询

时间:2012-03-14 11:58:14

标签: c# sql nhibernate

我有一个NHibernate标准,我需要从中获取SQL查询。我尝试了here的各种方法。但是,我得到的查询中没有参数(它有'?'代替它,就像在herehere上提到的那样)。此外,至少有一件不起作用的是criteria.setMaxResults(n)。

我也尝试过NHibernate拦截器。但是,我在OnPrepareStatement(sql)中获得的查询也没有参数。有没有其他方法从标准中获取SQL查询?

PS: - 标准是首先创建的,因为它更容易与它们一起工作以满足复杂的业务需求。但是,我需要进行数据导出,这通过标准非常慢。我试图从标准中获取查询,然后从中进行bcp导出。

3 个答案:

答案 0 :(得分:2)

使用记录器,在执行代码之前配置

var sqlLogger = (Logger)LogManager.GetRepository().GetLogger("NHibernate.SQL");
_sqlappender = new NhSqlAppender();
sqlLogger.AddAppender(_sqlappender);
if (!sqlLogger.IsEnabledFor(Level.Debug))
    sqlLogger.Level = Level.Debug;

class NhSqlAppender : AppenderSkeleton
{
    private List<string> queries = new List<string>(1000);

    public IList<string> Queries
    {
        get { return queries; }
    }

    protected override void Append(LoggingEvent loggingEvent)
    {
        queries.Add(loggingEvent.RenderedMessage);
    }
}

如何注入非执行连接

class FakeConnectionFactory : DriverConnectionProvider
{
    public override IDbConnection GetConnection()
    {
        return new FakeConnection(base.GetConnection());
    }
}

class FakeConnection : DbConnection
{
    private IDbConnection _connection;

    public FakeConnection(IDbConnection connection)
    {
        _connection = connection;
    }

    ...

    protected override DbCommand CreateDbCommand()
    {
        return new FakeCommand(_connection.CreateCommand());
    }
}

class FakeCommand : DbCommand
{
    private IDbCommand iDbCommand;

    public FakeCommand(IDbCommand iDbCommand)
    {
        this.iDbCommand = iDbCommand;
    }

    ...

    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
        return EmptyDataReader();
    }

    public override int ExecuteNonQuery()
    {
        return 0;
    }

    public override object ExecuteScalar()
    {
        return 0;
    }
}

答案 1 :(得分:1)

要自己回答这个问题,我认为不可能获得包含所有参数的完整查询,因为参数会被添加到所有地方。此外,还有一些技术存在其他问题,例如在使用条件连接walker的情况下,setMaxResults不起作用,并且在nhibernate中受到重大更改。

答案 2 :(得分:1)

我认为这种扩展方法将满足您的需求

  public static String ToSql(this ICriteria criteria)
    {
        var criteriaImpl = criteria as CriteriaImpl;
        var sessionImpl = criteriaImpl.Session;
        var factory = sessionImpl.Factory;
        var implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
        var loader = new CriteriaLoader(factory.GetEntityPersister(implementors[0]) as IOuterJoinLoadable, factory, criteriaImpl, implementors[0], sessionImpl.EnabledFilters);

        return loader.SqlString.ToString();
    }