如何使用 NHibernate 更新数据库中的版本列

How update version column in DB with NHibernate

现在:

//banan get in previous session and banan.VersionObject = 1
using (var session = factorySession.OpenSession())
          {
              banan.Name = "diffrent";
              session.Update(banan);
              session.Flush();//exception if version not equal 1
          }
//banan.VersionObject still equals 1

我的 hbm 配置:

<class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.FatherBanan, LittleNHibernateProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="FatherBanan">
    <cache region="FatherBanan" usage="read-write" />
    <id name="Id" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="increment" />
    </id>
    <version generated="always" name="VersionObject" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
      <column name="VersionObject" not-null="true" default="1" />
    </version>
    <any id-type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" meta-type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="WifeBanan">
      <meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan, LittleNHibernateProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <meta-value value="FatherBanan" class="LittleNHibernateProject.Model.FatherBanan, LittleNHibernateProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <column name="Banan_Type" />
      <column name="Banan_Id" />
    </any>
    <property name="Name" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Name" />
    </property>
    <property name="Variety" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Variety" />
    </property>
  </class>

我看到两条路径:

  1. 在数据库中使用触发器。但我不想为所有实体创建触发器手册。

  2. 代码如下:

using (var session = factorySession.OpenSession())
          {
              banan.Name = "diffrent";
              session.Update(banan);
              session.Flush();//exception if version change

              banan.VersionObject = banan.VersionObject + 1;
              session.Update(banan);
              session.Flush();
          }

这(2 条路径)看起来像是不好的做法。 任何建议,实践?或者我的 config.hbm 不正确?

是的,我在数据库中的所有 table 上创建了触发器。

            var factory = new DbConfigurationFactory();
            var factorySession = factory.CreateFactory();

            var allClasses = factorySession.GetAllClassMetadata();

            //ReCreate triggers in database
            foreach (var metadata in allClasses)
            {
                var tableName = (metadata.Value as NHibernate.Persister.Entity.AbstractEntityPersister).TableName;

                using (var session = factorySession.OpenSession())
                {
                    var commandText = $@"
DROP TRIGGER IF EXISTS {tableName}trigger ON public.{tableName};

CREATE TRIGGER {tableName}trigger
    BEFORE UPDATE ON public.{tableName}
FOR EACH ROW EXECUTE PROCEDURE update_version_func();
";
                    var command = session.Connection.CreateCommand();
                    command.CommandText = commandText;
                    command.ExecuteNonQuery();
                }
            }

这项工作:

            FatherBanan banan = null;
            FatherBanan banan2 = null;
            using (var session = factorySession.OpenSession())
            {
                banan = session.Get<FatherBanan>((long)4);
                //banan.VersionObject = 1
            }

            using (var session = factorySession.OpenSession())
            {
                banan2 = session.Get<FatherBanan>((long)4);
                //banan2.VersionObject = 1
            }

            using (var session = factorySession.OpenSession())
            {
                banan.Name = "PPPP";
                session.Update(banan);
                session.Flush();
                //banan.VersionObject = 2
            }

            using (var session = factorySession.OpenSession())
            {
                var newBanan = session.Get<FatherBanan>((long)4);
                //newBanan.VersionObject = 2
            }

            using (var session = factorySession.OpenSession())
            {
                banan2.Name = "PPPP2";
                session.Update(banan2);
                session.Flush();//exception banan2.VersionObject = 1 when in database VersionObject = 2
            }

其中 update_version_func 是:

CREATE OR REPLACE FUNCTION public.update_version_func()
  RETURNS TRIGGER AS
$BODY$
BEGIN
    NEW.VersionObject = NEW.VersionObject +1;
    return NEW;
END
$BODY$
LANGUAGE plpgsql;