2014-11-08 81 views
2

我讀了很多關於此的討論,但無法找到解決方案。 There我發現在nhibernate版本3,必須工作。我使用NHibernate的3.3.3Nhibernate一對多元素添加

設備具有多個IP

public class Device 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string Place { get; set; } 

    private Iesi.Collections.Generic.ISet<Ip> _ips = new HashedSet<Ip>(); 

    public virtual Iesi.Collections.Generic.ISet<Ip> Ips 
    { 
     get 
     { 
      return _ips; 
     } 
     set 
     { 
      _ips = value; 
     } 
    } 
}   

public class Ip 
{ 
    public virtual int Id { get; set; } 
    public virtual Device Device { get; set; } 
    public virtual string Adress { get; set; } 
} 

映射

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhibbd" namespace="nhibbd.Domain"> 
    <class name="Device" table="devices" lazy="true"> 
    <id name="Id"> 
     <generator class="identity" /> 
    </id> 
    <property name="Name"> 
     <column name="name" sql-type="character varying" not-null="true" length="30"/> 
    </property> 
    <property name="Place" > 
     <column name="place" sql-type="character varying" not-null="true" length="30"/> 
    </property> 
    <set name="Ips" inverse="false" cascade="all" generic="true"> 
     <key column="device_id" not-null="true" update="false"/> 
     <one-to-many class="nhibbd.Domain.Ip" /> 
    </set> 
    </class> 
</hibernate-mapping> 

<hibernate-mapping assembly="nhibbd" namespace="nhibbd.Domain" xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="Ip" table="ips" lazy="true" > 
    <id name="Id"> 
    <generator class="identity" /> 
</id> 
    <many-to-one name="Device" class="Device"> 
     <column name="device_id" not-null="true" sql-type="INTEGER" /> 
    </many-to-one> 
    <property name="Adress"> 
     <column name="adress" sql-type="character varying" not-null="true" length="12"/> 
    </property> 
    </class> 
</hibernate-mapping> 

只是想添加設備

var device = new Device {Name = "D-Link DIR 320", Place = "320 room"}; 
var ip = new Ip {Adress = "1921680000001"}; 
using (var session = GetSession) 
using (var transaction = session.BeginTransaction()) 
{ 
    device.Ips.Add(ip); 
    session.Save(device); 
    transaction.Commit(); 
} 

並獲得例外

NHibernate.PropertyValueException:非空屬性引用一個空 或瞬時值nhibbd.Domain.Ip.Device

我想用逆= 「假」收集和不可─對於Ip.Device值,爲null =「true」。我怎樣才能做到這一點?

回答

1

要解決您的問題,我們首先必須始終正確設置域模型。這意味着,關係的雙方必須進行分配:

using (var transaction = session.BeginTransaction()) 
{ 
    device.Ips.Add(ip); 
    // new line 
    ip.Device == device; 
    session.Save(device); 
    transaction.Commit(); 
} 

後來,當我們將通過NHibernate的加載數據,我們預期兩端都正確的初始化。我們應該在創建實例時做同樣的事情。

inverse="false"

現在,如果你可以讓列 「DEVICE_ID」 表中的 「IPS」 可空...,將工作。但是,因爲你已經明確宣佈逆=「假」(默認設置),NHibernate的必須始終將

  1. 插入記錄到IPS表,與代表之間的關係,以父爲NULL(DEVICE_ID)列
  2. 更新參考ID其父記錄(DEVICE_ID將適當的設備參考更新)

這總是會發生。如果inverse =「false」

II。 inverse="true"

因爲我們已經提到過,關係的兩端必須在C#中定義 - 不需要使用NHibernate的強大功能....

只需使用映射到inverse="true"和:

  • INSERT會發出增加新的IP記錄,影響其正常關係到設備(DEVICE_ID列)

那映射實際上對我們來說是存在的。爲了優化數據處理,基於我們在代碼中正確設置關係的信任。

一般情況下,我很難記得形勢時對雙向映射逆不會使用...

+0

是否有辦法離開'不空=「真」'爲Ip.Device值,而不是手動設置'ip.Device == device;'在代碼中? – 2014-11-09 07:16:10

+0

我想說:**這是一個錯誤**在我們的代碼中不使用'ip.Device ==設備;'這是域模型設置。這是關係如何工作的,而不管ORM的持久性如何。如果它是我們在內存中的高速緩存......沒有任何設置。我們只需要。必須...希望它有幫助;)享受驚人的NHibernate;) – 2014-11-09 07:59:05