2

我訪問一個預先存在的數據庫(實際上是IBM i上的DB2),並且在Fluent NHibernate中存在以下(簡單)結構的映射問題。我不得不構建一個人爲的例子,所以請原諒任何遺漏。DB2 Fluent NHibernate在HasMany映射中映射重複記錄

工作...

public class Job 
{ 
    public virtual string JobCode { get; set; } 

    public virtual string Owner{ get; set; } 

    public virtual IList<Deliverable> Deliverables { get; set; } 

    public Job() 
    { 
     Deliverables = new List<Deliverable>(); 
    } 
} 

交付..

public class Deliverable 
{ 
    public virtual string JobCode { get; set; } 

    public virtual int Package { get; set; } 

    public virtual string Owner { get; set; } 

    public virtual string Reference { get; set; } 

    public virtual Job Job { get; set; } 
} 

我試圖映射工作和交付之間的 '的hasMany' 的關係,如下..

public class JobMap : ClassMap<Job> 
{ 
    public JobMap() 
    { 
     Table("JOB"); 

     Id(x => x.JobCode).Column("CODE"); 

     Map(x => x.Owner).Column("WHODO"); 

     HasMany(x => x.Deliverables) 
      .KeyColumn("CODE"); 
    } 
} 

public class DeliverableMap : ClassMap<Deliverable> 
{ 
    public DeliverableMap() 
    { 
     Table("DELIVERABLE"); 

     Id(x => x.JobCode).Column("CODE"); 

     Map(x => x.Reference).Column("UNQREF"); 

     Map(x => x.Owner).Column("WHODO"); 

     References(x => x.Job) 
      .Column("CODE") ; 
    } 
} 

這似乎工作,並且如果您採用生成的SQL,並直接運行它,則會返回正確的結果(在這個案例11個記錄,都是唯一的)。但是當我執行以下操作時,交付物列表中有11個條目全部相同。

IList的結果=會話 .CreateCriteria(typeof運算(作業)) 。新增(Expression.Eq( 「代碼」, 「206171」)) 的.List();

foreach (var job in results) 
{ 
    Console.WriteLine("job.JobCode" + job.JobCode); 
    Console.WriteLine("job.Owner" + job.Owner); 

    foreach (var deliverable in job.Deliverables) 
    { 

    **// These are all identical!** 

    Console.WriteLine(deliverable.Reference); 
    Console.WriteLine("deliverable.Owner" + deliverable.Owner); 
    Console.WriteLine(deliverable.JobNumber); 
    Console.WriteLine(deliverable.DeliverableTyoe); 
    Console.WriteLine(deliverable.Description); 
    } 
} 

那麼,映射是不正確的,還是有一些與我使用它們的方式?

非常感謝,我一直盯着這一整天。

回答

2

我似乎已經修復了它。我加CompositeID到交付映射

CompositeId() 
    .KeyProperty(x => x.JobCode, "CODE") 
    .KeyProperty(x => x.Reference, "UNQREF"); 

這意味着我不得不覆蓋在交付類

public override bool Equals(object obj) 
{ 
    if (obj == null) 
    return false; 

    var t = obj as Deliverable; 
    if (t == null) 
    return false; 

    if (JobCode == t.JobCode && Reference == t.Reference) 
    return true; 

    return false; 
} 

    public override int GetHashCode() 
    { 
    return (JobCode + "|" + Reference).GetHashCode(); 
    } 

,然後將下面也改變了工作映射如下

HasMany(x => x.Deliverables) 
    .KeyColumn("Codex") 
    .Inverse() 
    .Cascade.All(); 

我不確定其中哪些已經糾正了這種情況(我懷疑作業映射中的.Inverse()

我不確定現在生成的SQL是什麼樣的,但答案看起來是正確的。

+0

是的,這是有道理的。正如我所說的,CODE被映射爲ID和referenceId是不夠的。缺少真正的唯一ID導致了這個問題。好你讓它爲你工作。享受NHiberante;) –

+0

感謝您的幫助。這一切開始有意義 – Mmarquee

+0

偉大;)真的很棒;) –

1

在多對一的關係中(在我們的案例中爲DelivarableJob),關係本身恰好用一個 DB列表示。子表(Deliverable)具有(必須)帶有作業ID(代碼)的參考列。

因此,我們的映射需要的是可交付表格中的列,其中包含與作業的關係。 JobCode列。 (如果不知道有什麼,從上面的例子)

,這必須在兩側使用:

Delivarable:

public DeliverableMap() 
{ 
    ... 
    // References(x => x.Deliverable) ... I guess it is typo in the question snippet 
    References(x => x.Job) 
     .Column("JobCode") ; // column of table Deliverable 
} 

工作:

public JobMap() 
{ 
    ... 
    HasMany(x => x.Deliverables) 
     .KeyColumn("JobCode"); // column of table Deliverable 
} 

換句話說,這個映射中的兩個列名實際上都是一個列的名稱。兩者都映射到子(Deliverable)表的列。

EXTENDED:基於所述問題

Deliverable對象映射的變化,具有其ID(列CODE)一樣的參考Job(列CODE)。這似乎很奇怪。

這也解釋了一個事實,即JOB集合中的所有Deliverable項目都是相同(相同)。唯一可交付物(由其代碼定義)只能是一個。這種情況下的作業不能多於一個Deliverable(因爲它被唯一的CODE列引用)。看起來好像一對一的情況。

之所以有更多項目相同很難判斷。很高興看到您正在使用的查詢。

但我真的會兩次檢查列映射。可交付成果,應該在一個名爲「JobCODE」的專欄中提及Job ...支持更多交易相關...

+0

謝謝 - 我糾正了我原來的問題中的錯誤。我的代碼基本上是你上面提出的建議。生成的SQL在本地複製並運行時會生成所需的結果,但由代碼生成的可交付成果集合具有正確數量的結果,但結果卻是相同的。 – Mmarquee

+0

我擴展我的答案。什麼看起來真的是我的「代碼」列作爲ID和作業參考... –

+0

實際的文件具有相同的字段名稱的字段,用於加入他們 - 交付品有一個「組合」鍵組成(1) - >可提供的(1)(1),工作(1) - >可提供的(1)(2),工作(1) - >可提供的(1)(3),工作(1) - > Deliverable(2)(1)等(格式化的抱歉) – Mmarquee