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