使用每个 table 的主键进行一对一或多对一映射

One-to-one or many-to-one mapping using primary key of each table

我有一个旧架构,其中包含一个主 table 和一个辅助 table,其中辅助 table 通过具有相同的主 table 连接到主 table键(对于给定的 Main,Secondary 不一定存在)。我一直在上下搜索 XML 可以实现这项工作的映射,但没有找到适合我的东西。

  <class name="Secondary" table="Secondary" lazy="true" dynamic-insert="true" dynamic-update="true">
    <id name="mainId" type="Int32">
      <column name="MAIN_ID" not-null="true" />
      <generator class="foreign">
        <param name="property">Main</param>
      </generator>
    </id>
    <one-to-one class="Main" name="Main" constrained="true" />
  </class>


  <class name="Main" table="Main" lazy="true" dynamic-insert="true" dynamic-update="true">
    <one-to-one name="Secondary" cascade="all-delete-orphan" class="Secondary" />

主端也试过了,还是不行。它不一定会中断,但肯定不会达到我的预期。例如:

session.Query<Main>().Count(m => m.Secondary != null) 生成

select
    cast(count(*) as INT) as col_0_0_ 
from
    MAIN main0_ 
where
    main0_.MAIN_ID is not null

请注意,它使用的是 MAIN table 中的 MAIN_ID 并且完全忽略了 Secondary。

此问题已在 NHibernate 5.3 中修复

这是一个已知的 issue (PR with suggested fix is here)。

目前,作为 LINQ 中的解决方法,您可以在某些非 ID 和不可为 null 的 属性:

上调用 Count
session.Query<Main>().Count(m => m.Secondary.NotNullableProperty != null)

如果这样的 属性 不存在(或者您只是想在将来轻松找到所有此类 hacky 用法),您还可以将您的 Id 列映射为只读 属性 并使用它相反:

<property name="ForceJoinId" not-null="true" column="MAIN_ID" insert="false" update="false" />
session.Query<Main>().Count(m => m.Secondary.ForceJoinId != null)