我正在使用brownfield数据库,并且我正在尝试配置一个子类映射,该映射使用除指定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");
}
}
我想要做的是在加入子类时只使用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));
}
}
传递的实例缺少填充的Subclasses集合导致我寻找IParentInspector
似乎更具体的检查器。遗憾的是,Fluent NHibernate似乎没有IParentInstance
,IParentConvention
或IParentConventionAcceptance
的相应实现,就像IJoinedSubclassInspector
一样。虽然在我做之前我可能会实现自己的,但我想确保我没有咆哮错误的树。
这种子类id调整是否可行?我在地图或Fluent NHibernate Conventions namespace中遗漏了一些明显的东西吗?如何映射到具有与父ID
不同的列/属性的已连接子类答案 0 :(得分:3)
我能够想到三个可能解决您问题的方法,请参阅下面的调查结果。
我最初的想法是使用基于鉴别器的映射来建模继承,每个子类包含一个带属性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="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>
不幸的是,此时Hibernate支持此功能,但NHibernate不支持。有关优秀门票,请参阅here和here。一些工作已经用于添加此功能,可以在github上的this fork上看到。
另一种选择是仍然使用基于鉴别器的映射,但在每个子类中使用many-to-one
映射,这将允许您使用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">
<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>
最后一个选项是在DB中为包含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>