2

我正在使用 NHibernate 将一些非常简单的实体映射到三个表。

我的程序需要有一种模式,它输出将执行以插入或更新这些表的 SQL,以便可以将 SQL 保存到脚本文件中,以便以后手动执行。

这类似于这个问题(有一个非常好的答案):我怎样才能让 NHibernate 只生成 SQL 而不执行它?

只有那个问题是关于 SELECT 的,除了 INSERT / UPDATE,我需要同样的问题。这也需要是动态的,因为它取决于用户选项。我的意思是,当我的程序执行时:

        session.Save(entity);

有时我需要它来访问数据库,有时我需要它来输出它将执行的 SQL。

这是可能吗?

4

3 回答 3

1

这是不可能的,因为这是拥有像 NHibernate 这样的 ORM 的主要目的,但如果您想检查 Nhibernate 生成的查询,那么出于测试目的,请在 app.config 中使用此记录器,

<logger name="NHibernate.SQL">
  <level value="ALL" />
  <appender-ref ref="NHibernateRollingLogFileAppender" />
</logger>

然后,当您启动项目时,它应该生成 logfile_nhibernate.txt,您将看到所有生成的查询。

于 2015-04-01T20:57:22.863 回答
0

不幸的是,这是不可能的。

于 2012-07-16T13:02:43.050 回答
0

如果您想很难做到这一点,请查看下面的代码。

public IDbCommand CreateInsertCommand(object entity)
{
    var entityTuplizer = GetTuplizer(_sessionMetadata.SessionImplementor);
    var values = entityTuplizer.GetPropertyValuesToInsert(entity, new Dictionary<object, object>(), _sessionMetadata.SessionImplementor);

    var notNull = GetPropertiesToInsert(values);
    var sql = GenerateInsertString(true, notNull);
    var insertCommand = _sessionMetadata.Batcher.Generate(sql.CommandType, sql.Text, sql.ParameterTypes);

    Dehydrate(null, values, notNull, _propertyColumnInsertable, 0, insertCommand, _sessionMetadata.SessionImplementor);
    InfraUtil.FixupGuessedType(insertCommand);

    return insertCommand;
}

更多代码可指导您找到可行的解决方案

public class SessionMetadata
{
    private static readonly Type KeyType = typeof(ActiveRecordBase);

    private ISessionFactoryHolder _sessionFactoryHolder;
    private ISessionFactory _sessionFactory;
    private ISessionFactoryImplementor _sessionFactoryImplementor;
    private Configuration _configuration;
    private ISession _currentSession;
    private ISessionImplementor _sessionImplementor;
    private DriverBase _driver;
    private NonBatchingBatcher _batcher;
    private IMapping _mapping;

    public ISessionFactoryHolder SessionFactoryHolder
    {
        get { return _sessionFactoryHolder ?? (_sessionFactoryHolder = ActiveRecordMediator.GetSessionFactoryHolder()); }
    }

    public ISessionFactory SessionFactory
    {
        get { return _sessionFactory ?? (_sessionFactory = SessionFactoryHolder.GetSessionFactory(KeyType)); }
    }

    public ISessionFactoryImplementor SessionFactoryImplementor
    {
        get { return _sessionFactoryImplementor ?? (_sessionFactoryImplementor = (ISessionFactoryImplementor)SessionFactory); }
    }

    public DriverBase Driver
    {
        get { return _driver ?? (_driver = (DriverBase)SessionFactoryImplementor.ConnectionProvider.Driver); }
    }

    public NonBatchingBatcher Batcher
    {
        get { return _batcher ?? (_batcher = (NonBatchingBatcher)SessionImplementor.Batcher); }
    }

    public Configuration Configuration
    {
        get { return _configuration ?? (_configuration = SessionFactoryHolder.GetConfiguration(KeyType)); }
    }

    public ISession CurrentSession
    {
        get { return _currentSession ?? (_currentSession = SessionScope.Current.GetSession(SessionFactory)); }
    }

    public ISessionImplementor SessionImplementor
    {
        get { return _sessionImplementor ?? (_sessionImplementor = CurrentSession.GetSessionImplementation()); }
    }

    public IMapping Mapping
    {
        get { return _mapping ?? (_mapping = SessionFactoryImplementor); }
    }
}

public class EntityMetadata
{
    private readonly SessionMetadata _sessionMetadata;
    private readonly Type _entityType;
    private PersistentClass _persistentClass;
    private IEntityPersister _entityPersister;

    public EntityMetadata(Type entityType, SessionMetadata sessionMetadata)
    {
        _sessionMetadata = sessionMetadata;
        _entityType = entityType;
    }

    public SessionMetadata SessionMetadata
    {
        get { return _sessionMetadata; }
    }

    public PersistentClass PersistentClass
    {
        get { return _persistentClass ?? (_persistentClass = SessionMetadata.Configuration.GetClassMapping(_entityType)); }
    }

    public IEntityPersister EntityPersister
    {
        get { return _entityPersister ?? (_entityPersister = SessionMetadata.SessionFactoryImplementor.GetEntityPersister(PersistentClass.EntityName)); }
    }
}

public class ExtractSql: SingleTableEntityPersister
{
    private readonly SessionMetadata _sessionMetadata;
    private readonly EntityMetadata _entityMetadata;
    private readonly IEntityPersister _entityPersister;
    private readonly bool[][] _propertyColumnInsertable;
    private readonly bool[][] _propertyColumnUpdateable;

    public ExtractSql(EntityMetadata entityMetadata)
        : base(entityMetadata.PersistentClass, null, entityMetadata.SessionMetadata.SessionFactoryImplementor, entityMetadata.SessionMetadata.Mapping)
    {
        if (entityMetadata == null) throw new ArgumentNullException("entityMetadata");
        _sessionMetadata = entityMetadata.SessionMetadata;
        _entityMetadata = entityMetadata;

        _entityPersister = _entityMetadata.EntityPersister;

        var hydrateSpan = _entityPersister.EntityMetamodel.PropertySpan;
        _propertyColumnUpdateable = new bool[hydrateSpan][];
        _propertyColumnInsertable = new bool[hydrateSpan][];

        var i = 0;
        foreach (var prop in _entityMetadata.PersistentClass.PropertyClosureIterator)
        {
            _propertyColumnInsertable[i] = prop.Value.ColumnInsertability;
            _propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability;

            i++;
        }
    }

    protected override bool UseDynamicUpdate
    {
        get { return true; }
    }

    protected override bool UseDynamicInsert
    {
        get { return true; }
    }

    public IDbCommand CreateInsertCommand(object entity)
    {
        var entityTuplizer = GetTuplizer(_sessionMetadata.SessionImplementor);
        var values = entityTuplizer.GetPropertyValuesToInsert(entity, new Dictionary<object, object>(), _sessionMetadata.SessionImplementor);

        var notNull = GetPropertiesToInsert(values);
        var sql = GenerateInsertString(true, notNull);
        var insertCommand = _sessionMetadata.Batcher.Generate(sql.CommandType, sql.Text, sql.ParameterTypes);

        Dehydrate(null, values, notNull, _propertyColumnInsertable, 0, insertCommand, _sessionMetadata.SessionImplementor);
        InfraUtil.FixupGuessedType(insertCommand);

        return insertCommand;
    }
}
于 2016-10-08T23:38:20.430 回答