如何使用与父ID不同的列映射到已连接的子类?

ahs*_*ele 6 nhibernate nhibernate-mapping fluent-nhibernate fluent-nhibernate-mapping

我正在使用一个棕色数据库,我正在尝试配置一个子类映射,该映射使用除指定id之外的列连接到其子类.该login表有一个主键列login_sk,我想用它作为它的id.它通过一个login_cust_id列连接到两个表(为了使相邻表中相应列的命名方式更加有趣).如果我设置login_cust_id为UserMap的id,它会按预期加入其子类.我希望显而易见的原因是我不想将login_cust_id其用作我的User对象的id.

public class UserMap : ClassMap<IUser>
{
    public UserMap()
    {
        Table("login");
        Id(x => x.Id).Column("login_sk"); // want to setup map like this

        // if used instead this works for subclass joining / mapping
        // Id(x => x.Id).Column("login_cust_id");
        // would prefer to only reference login_cust_id for subclass mapping
    }
}

public class CustomerUserMap : SubclassMap<CustomerUser>
{
    public CustomerUserMap()
    {
        Table("customer");
        Map(c => c.DisplayName, "cust_mail_name");
        Map(c => c.RecordChangeName, "cust_lookup_name");
        KeyColumn("cust_id");
    }
}

public class EntityUserMap : SubclassMap<EntityUser>
{
    public EntityUserMap()
    {
        Table("entity");
        Map(c => c.DisplayName, "entity_name");
        KeyColumn("entity_id");
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要做的只是login_cust_id在加入子类时使用列.是否有一个流畅的映射设置,允许我指定这个?如果没有流畅的映射,那么常规的NHibernate XML映射会起作用吗?我甚至不想映射列,只在可能的情况下使用它来加入.如果它有帮助,则有一个潜在的鉴别器列login_holder_type,指示要加入的表.

它确实发生在我设置,IClassConvention但在通过后IClassInstance我无法确定任何可以帮助我的设置.

public class UserIdConvention : IClassConvention, IClassConventionAcceptance
{

    public void Apply(IClassInstance instance)
    {
        // do something awesome with instance.Subclasses to
        // specify the use of login_cust_id for subclass joining...
    }

    public void Accept(IAcceptanceCriteria<IClassInspector> criteria)
    {
        criteria.Expect(x => typeof(User).Equals(x.EntityType));
    }
}
Run Code Online (Sandbox Code Playgroud)

传递的实例缺少一个填充的Subclasses集合,这使我找到了一个更具体的检查器IParentInspector.不幸的是,Fluent NHibernate似乎没有相应的实现IParentInstance,IParentConvention或者IParentConventionAcceptance像它那样IJoinedSubclassInspector.虽然我可以在我做之前实现自己,但我想确保我没有咆哮错误的树.

是否可以进行这种子类id调整?我在地图或Fluent NHibernate Conventions命名空间中遗漏了哪些东西?如何使用与父ID不同的列/属性映射到已连接的子类?

mic*_*old 3

我能够想到三种可能的解决方案来解决您的问题,请参阅下面的我的发现。

解决方案 1:使用 Join 进行基于鉴别器的映射

我最初的想法是使用基于鉴别器的映射来对继承进行建模,每个子类都包含带有属性引用的连接,即

<class name="IUser" abstract="true" table="login">
    <id name="Id" column="login_sk">
        <generator class="identity"/>
    </id>
    <discriminator column="login_holder_type" not-null="true" type="System.String"/>

    <subclass name="CustomerUser" discriminator-value="Customer">
        <join table="customer" >
          <key column="cust_id" property-ref="login_cust_id" />
          <property name="DisplayName" column="cust_mail_name"/>
          <property name="RecordChangeName" column="cust_lookup_name" />
        </join>
    </subclass>

    <subclass name="EntityUser" discriminator-value="Entity">
      <join table="entity" >        
        <key column="entity_id" property-ref="login_cust_id" />
        <property name="CompanyName"/>
      </join>
    </subclass>
</class>
Run Code Online (Sandbox Code Playgroud)

不幸的是,目前 Hibernate 支持此功能,但 NHibernate 不支持。请参阅此处此处查看未偿还的门票。一些工作致力于添加此功能,可以在github 上的分支上看到。

解决方案 2:基于鉴别器的多对一映射

另一种选择是仍然使用基于鉴别器的映射,但many-to-one在每个子类中使用映射,这将允许您使用属性引用连接外键。这样做的缺点是需要为客户和实体表中的所有属性提供单独的类,但这是一个可行的解决方案。

<class name="IUser" abstract="true" table="login">
    <id name="Id" column="login_sk">
        <generator class="identity"/>
    </id>
    <discriminator column="login_holder_type" not-null="true" type="System.String"/>

    <subclass name="CustomerUser" discriminator-value="Customer">
        <many-to-one name="CustomerProps" property-ref="login_cust_id" />
    </subclass>

    <subclass name="EntityUser" discriminator-value="entity">
        <many-to-one name="EntityProps" property-ref="login_cust_id" />     
    </subclass>
</class>

<class name="CustomerProps" Table="customer" >
  <id name="Id" column="cust_id">
    <generator class="assigned"/>
  </id>
  <property name="DisplayName" column="cust_mail_name"/>
  <property name="RecordChangeName" column="cust_lookup_name" />
</class>

<class name="EntityProps" Table="entity" >
  <id name="Id" column="entity_id">
    <generator class="assigned"/>
  </id>
  <property name="CompanyName"/>
</class>
Run Code Online (Sandbox Code Playgroud)

解决方案 3:基于鉴别器的映射,并连接到可更新视图

最后一个选项是在数据库中为包含 login_sk 字段的客户和实体表创建可更新视图。然后您可以Join在每个子类中使用,因为您不需要property-ref.

<class name="IUser" abstract="true" table="login">
    <id name="Id" column="login_sk">
        <generator class="identity"/>
    </id>
    <discriminator column="login_holder_type" not-null="true" type="System.String"/>

    <subclass name="CustomerUser" discriminator-value="Customer">
        <join table="customerView" >
          <key column="login_sk" />
          <property name="DisplayName" column="cust_mail_name"/>
          <property name="RecordChangeName" column="cust_lookup_name" />
        </join>
    </subclass>

    <subclass name="EntityUser" discriminator-value="Entity">
      <join table="entityView" >        
        <key column="login_sk" />
        <property name="CompanyName"/>
      </join>
    </subclass>
</class>
Run Code Online (Sandbox Code Playgroud)