2011-06-18 112 views
0

這可能很簡單,但我認爲我錯過了一些東西。我有一個自我聯接表Units,每個單元都有一個主單元:NHibernate映射自聯表?

enter image description here

這樣我就可以查詢的是這樣的:

enter image description here

units映射到以下課程:

public class Units 
{ 
    public virtual int Unit_Id { get; private set; } 
    public virtual string Unit { get; set; } 
    public virtual decimal Unit_Value { get; set; } 
    public virtual Units Main_Unit { get; set; } 
} 

以.hbm映射文件爲f ollows:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NewA.Domain"  namespace="NewA.Domain"> 
    <class name="NewA.Domain.Entities.Units,NewA.Domain" table="Units"> 
    <id name="Unit_Id" column="Unit_Id" type="Int32" length="4" unsaved-value="0"> 
     <generator class="native"> 
     </generator> 
    </id> 
    <property name="Unit" column="Unit" type="string" length="50" not-null="true"/> 
    <one-to-one name="Main_Unit" class="NewA.Domain.Entities.Units,NewA.Domain"/> 
    </class> 
</hibernate-mapping> 

當用下面的代碼測試這些實體:

Units unit = _UnitsRepository.GetById(2); 
string parent_unitname = unit.Main_Unit.Unit; 
Assert.AreEqual("pack",parent_unitname); 

我得到了以下錯誤時拋出:

Expected values to be equal. 

Expected Value : "pack" 
Actual Value : "kg" 

的問題是的Main_Unit財產Unit實體引用了它自己,所以我錯過了什麼我怎樣才能寫出像遞歸SQL CTE這樣的東西來應用等級等,因爲我有與其他更復雜的自連接表和更復雜的查詢相同的問題。

回答

3

您需要多對一映射,而不是一對一。 試試這個配置:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="NewA.Domain.Entities.Units.Units, NewA.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Units`"> 
    <id name="Unit_Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Unit_Id" /> 
     <generator class="native" /> 
    </id> 
    <property name="Unit" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Unit" /> 
    </property> 
    <property name="Unit_Value" type="System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Unit_Value" /> 
    </property> 
    <many-to-one class="NewA.Domain.Entities.Units.Units, NewA.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Main_Unit"> 
     <column name="Main_Unit_id" /> 
    </many-to-one> 
    </class> 
</hibernate-mapping> 

我建議你嘗試功能NHibernate - 它可以動態生成您的映射。 下面是我使用的配置:

var fluent = Fluently.Configure() 
    .Mappings(c => c.AutoMappings.Add(AutoMap.AssemblyOf<Units>() 
     .Override<Units>(u => u.Id(uu => uu.Unit_Id).GeneratedBy.Native()))) 
    .Database(() => SQLiteConfiguration.Standard.UsingFile("test.sqlite3")); 

var configuration = fluent.BuildConfiguration(); 

// Generate database schema 
new SchemaExport(configuration).Create(false, true); 

var sessionFactory = configuration.BuildSessionFactory(); 
// Now just open session and do whatever you need 
+0

爲什麼需要多到一個一個一對一的映射??何地映射insteed是在您的配置關係的另一部分,一對多部分?? Main_Unit僅引用了一個單位的引用,正如我所提到的那樣,只有一個表單位。那你的配置中的Main_Unit_id是什麼,沒有Main_Unit表,它只是Units表。 –

+0

**一對一**意味着您將無法在** kg **中表示** g **和** mg **(即類似1000克==千克,1,000,000 = = 1公斤)。在你的情況下,許多不同的「小數」單位可能表示在同一個Main_Unit中,所以你需要**多對一**。 ** Main_Unit_id **引用對象** Units **(映射到表** Units **),在您的示例中,這對應於列** Main_Unit **。流利的NHibernate只是爲外鍵列添加了** _id **這個命名約定。您可以像使用Id生成器一樣重寫此約定 –