我希望我的一个实体与类层次结构具有一对一的关系。可以把它想象成一种策略模式,每种策略都需要不同的参数来保持。我尝试使用OneToOne
和JoinedBase
/ JoinedKey
的组合,但我遇到了一个问题。
通过这种组合,主实体的主键也显示为表示层次结构中根类的表的主键,并作为子类的主键:
Order --------------- TaxCalculator
([PrimaryKey]Id = 1234) ([PrimaryKey(PrimaryKeyType.Foreign)]OrderId = 1234)
^
|
|
UkTaxCalculator
([JoinedKey]UkTaxCalculatorId = 1234)
我可以坚持这一点,但是我无法改变TaxCalculator
的哪个子类。当我做类似的事情时:
order.TaxCalculator = new OverseasTaxCalculator(order);
然后尝试刷新,然后ActiveRecord / NHibernate(可以理解)不满意现在有两个TaxCalculators
Id = 1234
。
我可以通过用OneToOne
/ HasMany
替换BelongsTo
并隐藏Order
对象的用户的多重性来解决这个问题,但我感兴趣要知道是否可以使用OneToOne
执行此操作。
有一个完整的代码示例on github。处理第二个SessionScope
时,此代码会抛出异常。如果您克隆项目,它应该是开箱即用的。
答案 0 :(得分:1)
首先我很抱歉,但我没有尝试过我的解决方案。这是迟到的,我真的需要我的睡眠;-)。我认为一对一可以工作的唯一方法是使用一个鉴别器列而不是每子类表来“逐层表”。也许这将使您能够将现有对象变形为另一个子类。另一种方式,不幸的是,如你所述,不支持像多态删除孤儿这样的东西。所以我猜这将是你(非常)的最后选择。
但是,如果这样做失败,为什么不将它映射为一对多而不是多对一的订单表中的外键,重用TaxCalculators?我认为它们非常静止。
有趣的想法:多态删除 - 孤儿。
答案 1 :(得分:-1)
我们做的事与您尝试的非常相似。我认为这是一对一和导致问题的联合密钥的组合。试试这个:
[ActiveRecord, JoinedBase]
public class TaxCalculator
{
protected int TaxCalculatorId;
[PrimaryKey]
public virtual int Id
{
get { return TaxCalculatorId; }
set { TaxCalculatorId = value; }
}
// common tax calculation fields, methods etc...
}
[ActiveRecord]
public class OverseasTaxCalculator : TaxCalculator
{
[JoinedKey]
public override int Id
{
get { return TaxCalculatorId; }
set { TaxCalculatorId = value; }
}
// overseas tax calculation specific methods, properties etc...
}