【问题标题】:How can i get NHibernate to give me the SQL it would generate for an insert / update instead of executing it?我怎样才能让 NHibernate 给我它会为插入/更新而不是执行它生成的 SQL?
【发布时间】:2022-02-17 01:47:15
【问题描述】:

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

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

这类似于这个问题(有一个非常好的答案):How can I have NHibernate only generate the SQL without executing it?

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

        session.Save(entity);

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

这可能吗?

【问题讨论】:

  • 当您想稍后使用生成的 SQL 时,使用 ORM 有什么意义?
  • 一方面,ORM 是独立于数据库的,因此它会根据数据库 - 映射生成不同的 SQL。另外,正如我所说,有时程序需要更新数据库,在这种情况下,我很享受 ORM 的抽象和生产力。
  • 请注意,nhibernate 缓存将完全被愚弄。如果这很重要,您可以实现自己的连接提供程序并覆盖 ExceuteUpdate 以发出 sql 而不是发送它

标签: c# nhibernate fluent-nhibernate


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    很遗憾,这是不可能的。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2023-04-05
        • 2021-05-27
        • 2012-08-27
        • 1970-01-01
        • 2020-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多