使用Fluent NHibernate将单个字段映射到多个表

时间:2009-12-10 14:59:15

标签: c# nhibernate fluent-nhibernate

问题:有没有办法根据上下文将单个外键映射到多个互斥表?

背景...

在我的具体示例中,我有以下域图,表示可以针对车辆 属性的保险索赔:

public enum InvolvedPartyContext
{
    Vehicle = 1,
    Property = 2
}

public class Claim
{
    public virtual Guid Id { get; set; }
    public virtual InvolvedPartyContext InvolvedPartyContext { get; set; }
    public virtual Vehicle Vehicle { get; set; }    // set if Context = Vehicle
    public virtual Property Property { get; set; }  // set if Context = Property
}

public class Vehicle {  //... }

public class Property {  //... }

SQL看起来像这样(注意单个外键 InvolvedPartyId ):

CREATE TABLE Claims ( 
 Id uniqueidentifier NOT NULL,
 InvolvedPartyContext int NOT NULL,
 InvolvedPartyId uniqueidentifier NOT NULL
)

CREATE TABLE Vehicles (
    Id uniqueidentifier NOT NULL,
    Registration varchar(20) NOT NULL
)

CREATE TABLE Properties (
    Id uniqueidentifier NOT NULL,
    PostCode varchar(20) NOT NULL
)

声明的Fluent NHibernate映射文件:

    public ClaimMap()
    {
        Id(x => x.Id);
        Map(x => x.InvolvedPartyContext).CustomTypeIs(typeof(InvolvedPartyContext));
        References(x => x.Vehicle, "InvolvedPartyId");
        References(x => x.Property, "InvolvedPartyId");
    }

由于相同的字段( InvolvedPartyId )被映射两次,因此抛出“此SqlParameterCollection具有Count {m}”异常的“无效索引{n}”。一个简单的解决方法是创建VehicleId和PropertyId字段,但在现实世界中还有更多的上下文,所以这不是很灵活。

1 个答案:

答案 0 :(得分:2)

就个人而言,我不会选择你的设计。相反,我会分别创建Claim类,VehicleClaimPropertyClaim的子类。

public class VehicleClaim : Claim
{
  public virtual Vehicle Vehicle { get; set; }
}

然后更改映射以使用InvolvedPartyContext列作为鉴别器(NHibernate用于确定行所代表的类的列),并为每个子类创建子类映射。

public class ClaimMap : ClassMap<Claim>
{
  public ClaimMap()
  {
    Id(x => x.Id);
    DiscriminateSubClassesOnColumn("InvolvedPartyContext");
  }
}

public class VehicleClaimMap : SubclassMap<VehicleClaim>
{
  public VehicleClaimMap()
  {
    DiscriminatorValue(1);
    References(x => x.Vehicle);
  }
}

如果你确实想要运行你已经拥有的东西,你应该查看任何映射;关于它们没有很多文档,但您使用ReferencesAny方法。