NHibernate/FluentNHibernate property bag

前端 未结 3 1887
栀梦
栀梦 2021-01-13 22:44

Given a Vehicle class and a VehicleProperty class...

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


        
相关标签:
3条回答
  • 2021-01-13 23:01

    I agree entirely with Stefan's points, and although I can't attest to the correctness of his mapping, the literal translation into Fluent NHibernate is as follows:

    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();
      }
    }
    
    0 讨论(0)
  • 2021-01-13 23:10
    1. Don't use composite id's.
    2. Inverse means, that this is the inverse relation of an other one. If there is no other one, it's just not updated.
    3. You declared the VehicleProperty.Name Property as the primary key. if the primary key is already initialized, NH thinks it is already stored and therefore tries an update. (that's why you get the exception.) You can changed this behaviour, but it's better to use an artificial primary key or the mapping bellow.

    I don't know FluentNHibernate to show you the code. I can tell you how it looks in 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>
    
    0 讨论(0)
  • 2021-01-13 23:15

    First, create a separate class for the composite 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)
      {
        ...
      }
    }
    

    Then, refactor the VehicleProperty class this way:

    public class VehicleProperty
    {
      public virtual VehiclePropertyPK VehicleCompId { get; set; }
      public virtual string Value { get; set; }
    }
    

    Finally, the maps:

    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);
      }
    }
    

    (NHibernate 3.3.1 and FluentNHibernate 1.3.0)

    0 讨论(0)
提交回复
热议问题