流畅的NHibernate:抽象类的映射列表,每个具体类都有表(union-subclass)

时间:2012-12-06 17:14:00

标签: nhibernate fluent-nhibernate

我遇到以下情况的问题。

我的班级结构如下:

public class Owner
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Vehicle> Vehicles { get; set; }
}

public abstract class Vehicle
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
}

public abstract class PoweredVehicle : Vehicle
{
    public virtual string EngineType { get; set; }
}

public class Car : PoweredVehicle
{
    public virtual int Doors { get; set; }
}

public class Truck : PoweredVehicle
{
    public virtual long MaxLoad { get; set; }
}

public class Bicycle : Vehicle
{
    public virtual int FrameSize { get; set; }
}

流利映射:

public class OwnerMap : ClassMap<Owner>
{
    public OwnerMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name);
        HasMany(x => x.Vehicles);
    }
}

public class VehicleMap : ClassMap<Vehicle>
{
    public VehicleMap()
    {
        Id(x => x.Id).GeneratedBy.HiLo("10");
        Map(x => x.Name);
        UseUnionSubclassForInheritanceMapping();
    }
}

public class PoweredVehicleMap : SubclassMap<PoweredVehicle>
{
    public PoweredVehicleMap()
    {
        Map(x => x.EngineType);
        Abstract();
    }
}

public class CarMap : SubclassMap<Car>
{
    public CarMap()
    {
        Map(x => x.Doors);
    }
}

public class TruckMap : SubclassMap<Truck>
{
    public TruckMap()
    {
        Map(x => x.MaxLoad);
    }
}

public class BicycleMap : SubclassMap<Bicycle>
{
    public BicycleMap()
    {
        Map(x => x.FrameSize);
    }
}

我插入一辆汽车和一辆自行车。当我尝试插入带有Vehicle对象列表的所有者(带有Car和Bicycle)时,我收到以下错误:

  

异常:NHibernate.Exceptions.GenericADOException:无法插入   采集:   [NHibernateTest.Owner.Vehicles#8ace95bc-ad80-46d7-94c7-a11f012b67c6] [SQL:   UPDATE“Vehicle”SET Owner_id = @ p0 WHERE Id = @ p1] ---&gt;   System.Data.SQLite.SQLiteException:SQLite错误

由于我为每个具体类设置表,为什么NHibernate试图更新一个表示基类的不存在的表?这种情况不支持这种类型的映射吗?

此外,当我从HasMany更改为HasManyToMany时,这样可以正常工作。

1 个答案:

答案 0 :(得分:2)

在这种情况下,唯一的选择是Inverse()映射。这意味着混凝土车辆(汽车,自行车)必须关心关系的持久性。

要启用此功能,请使用新属性扩展Vehicle类:

public abstract class Vehicle
{ 
  ..
  // new owner independent navigation property
  public virtual Guid OwnerId { get; set; } 
}

并扩展Vehicle的映射

public VehicleMap()
{  
  ..
  Map(x => x.OwnerId).Column("Owner_id);
}

最后反转持久性责任。不是所有者,但是集合项将关注正确的Owner_id列更改(当调用具体的Vehicle插入/更新时)。

(更多关于逆:https://stackoverflow.com/a/1454445/1679310

public OwnerMap()
{
  ..
  HasMany(x => x.Vehicles)
    .Inverse()
    .Cascade.All();
}

Vehicle添加到Owner的集合中时,还必须为其分配OwnerId

owner.Vehicles.Add(car);
car.OwnerId = owner.Id;