2009-05-02 40 views
4

方式的車輛類和VehicleProperty類...的NHibernate/FluentNHibernate屬性包

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

我怎樣才能在兩類地圖,讓VehicleProperty表有[VehicleId]組合鍵和[名稱] 。車輛將是一個聚合根(VehicleProperty不在車輛類外訪問)。

我都試過,我能想到的一切(我是新來的NHibernate所以這不是太大)

public class VehicleMap : ClassMap<Vehicle> 
{ 
    public VehicleMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Registration); 
     HasMany(x => x.Properties) 
      .Inverse() 
      .Cascade.All(); 
    } 
} 

public class VehiclePropertyMap : ClassMap<VehicleProperty> 
{ 
    public VehiclePropertyMap() 
    { 
     UseCompositeId() 
      .WithKeyProperty(x => x.Name) 
      .WithKeyReference(x => x.Vehicle, "Vehicle_Id"); 
     Map(x => x.Name); 
     Map(x => x.Value); 
    } 
} 

這種映射的結果在下面的SQL和StaleStateException「意外的行數:0;預期:1" (我也真的不希望對VehicleProperty車輛屬性)...

INSERT INTO "Vehicle" (Registration) VALUES (@p0); select last_insert_rowid(); @p0 = 'AA09CDE' 
UPDATE "VehicleProperty" SET Name = @p0, Value = @p1 WHERE Name = @p2 AND Vehicle_Id = @p3; @p0 = 'Colour', @p1 = 'Black', @p2 = 'Colour', @p3 = '' 

回答

4
  1. 不要使用複合材料的ID。
  2. 反向意味着,這是另一個反向關係 。如果 沒有其他人,那隻更新 。
  3. 您聲明瞭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> 
+0

我認爲一個真正的關係規範化的數據庫,而不是由ORM約束,將並應具有複合ID的,從數據庫管理員的角度來看......但我認爲NHibernate已經足夠處理複合ID了。 – 2013-08-12 22:30:31

6

我與斯特凡的點完全同意,雖然我不能證明他的映射的正確性,字面翻譯成流利的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(); 
    } 
} 
0

首先,創建一個單獨的類複合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); 
    } 
} 

(NHibernate的3.3.1和1.3.0 FluentNHibernate)