NHibernate/FluentNHibernate属性袋

NHibernate/FluentNHibernate属性袋,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,给定车辆类别和车辆属性类别 public class Vehicle { public virtual int Id { get; protected set; } public virtual string Registration { get; set; } private List<VehicleProperty> _properties = new List<VehicleProperty>(); public virtual I

给定车辆类别和车辆属性类别

public class Vehicle
{
    public virtual int Id { get; protected set; }
    public virtual string Registration { get; set; }

    private List<VehicleProperty> _properties = new List<VehicleProperty>();
    public virtual IEnumerable<VehicleProperty> Properties
    {
        get { return _properties; }
        protected set{ _properties = new List<VehicleProperty>(value);}
    }

    public virtual void AddProperty(string name, string value)
    {
        _properties.Add(new VehicleProperty {Name = name, Value = value});
    }
}

public class VehicleProperty
{
    public virtual string Name { get; set; }
    public virtual string Value { get; set; }
}
  • 不要使用复合id
  • 相反的意思是,这是 另一个的反向关系。如果 没有其他人,只是没有 更新
  • 您已声明VehicleProperty.Name属性 作为主键。如果主要 密钥已初始化,NH 认为它已经存储并 因此,尝试更新。(这就是你得到例外的原因。)你可以 改变了这种行为,但它是 最好使用人工初级保健 键或下面的映射
  • 我不知道用FluentNHibernate来给你看代码。我可以告诉您它在XML中的外观

    <class name="Vehicle">
      <id name="Id" generator="native"/>
    
      <property name="Registration"/>
    
      <!-- declare the table Vehicle_Properties for the property Properties -->
      <bag name="Properties" table="Vehicle_Properties" cascade="all-delete-orphan">
    
        <!-- primary key of Vehicle_Properties and foreign key -->
        <key column="Vehicle_FK"/>
    
        <!-- contents of the table: Name and Value -->
        <composite-element class="VehicleProperty">
          <property name="Name"/>
          <property name="Value"/>
        </composite-element>
      </bag>
    
    </class>
    

    我完全同意Stefan的观点,尽管我无法证明他的映射的正确性,但对Fluent NHibernate的直译如下:

    public class VehicleMap : ClassMap<Vehicle>
    {
      public VehicleMap()
      {
        Id(x => x.Id);
        Map(x => x.Registration);
    
        HasMany(x => x.Properties)
          .Component(c =>
          {
            c.Map(x => x.Name);
            c.Map(x => x.Value);
          })
          .Cascade.AllDeleteOrphan();
      }
    }
    
    公共类车辆地图:类地图
    {
    公共车辆地图()
    {
    Id(x=>x.Id);
    Map(x=>x.0);
    HasMany(x=>x.Properties)
    .组件(c=>
    {
    c、 Map(x=>x.Name);
    c、 Map(x=>x.Value);
    })
    .Cascade.AllDeleteOrphan();
    }
    }
    
    首先,为复合PK创建一个单独的类:

    public class VehiclePropertyPK
    {
      public virtual Vehicle PropertyVehicle { set; get; }
      public virtual string Name { set; get; }
    
      // You must implement your own GetHasCode and Equals methods
      public override int GetHashCode()
      {
        ...
      }
    
      public override bool Equals(object o)
      {
        ...
      }
    }
    
    然后,通过以下方式重构
    VehicleProperty
    类:

    public class VehicleProperty
    {
      public virtual VehiclePropertyPK VehicleCompId { get; set; }
      public virtual string Value { get; set; }
    }
    
    最后,地图:

    public class VehicleMap : ClassMap<Vehicle>
    {
      public VehicleMap()
      {
        Id(x => x.Id);
        Map(x => x.Registration);
        HasMany(x => x.Properties)
            .KeyColumn("Vehicle_Id")
            .Inverse()
            .Cascade.All();
      }
    }
    
    public class VehiclePropertyMap : ClassMap<VehicleProperty>
    {
      public VehiclePropertyMap()
      {
        CompositeId<VehiclePropertyPK>(x => x.VehicleCompId)
                .KeyReference(y => y.PropertyVehicle , "Vehicle_Id")
                .KeyProperty(y => y.Name, "Name");
        Map(x => x.Value);
      }
    }
    
    公共类车辆地图:类地图
    {
    公共车辆地图()
    {
    Id(x=>x.Id);
    Map(x=>x.0);
    HasMany(x=>x.Properties)
    .KeyColumn(“车辆Id”)
    .Inverse()
    .Cascade.All();
    }
    }
    公共类车辆属性映射:类映射
    {
    公共车辆属性映射()
    {
    CompositeId(x=>x.VehicleCompId)
    .KeyReference(y=>y.PropertyVehicle,“车辆Id”)
    .KeyProperty(y=>y.Name,“Name”);
    Map(x=>x.Value);
    }
    }
    

    (NHibernate 3.3.1和FluentNHibernate 1.3.0)

    我认为,从DBA的角度来看,一个不受ORM约束的真正的关系规范化数据库将并且应该具有复合id。。。然而,我认为NHibernate足以处理复合id。不鼓励将复合id与NH一起使用。实际上,也不鼓励在纯关系环境中使用它们,链接表除外。对于这些表,NH还隐式地使用复合键。当然,您可以在使用NH运行的实体上获得复合键。但是,当你避开它的时候,你会有很多时间是安全的。
    public class VehicleProperty
    {
      public virtual VehiclePropertyPK VehicleCompId { get; set; }
      public virtual string Value { get; set; }
    }
    
    public class VehicleMap : ClassMap<Vehicle>
    {
      public VehicleMap()
      {
        Id(x => x.Id);
        Map(x => x.Registration);
        HasMany(x => x.Properties)
            .KeyColumn("Vehicle_Id")
            .Inverse()
            .Cascade.All();
      }
    }
    
    public class VehiclePropertyMap : ClassMap<VehicleProperty>
    {
      public VehiclePropertyMap()
      {
        CompositeId<VehiclePropertyPK>(x => x.VehicleCompId)
                .KeyReference(y => y.PropertyVehicle , "Vehicle_Id")
                .KeyProperty(y => y.Name, "Name");
        Map(x => x.Value);
      }
    }