【问题标题】:DB2 Fluent NHibernate mapping duplicate records in HasMany mappingDB2 Fluent NHibernate 在 HasMany 映射中映射重复记录
【发布时间】:2013-09-01 02:26:48
【问题描述】:

我访问了一个预先存在的数据库(实际上是 IBM i 上的 DB2),并且在 Fluent NHibernate 中对以下(简单)结构的映射存在问题。我不得不构建一个人为的例子,所以请原谅任何遗漏。

工作...

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

我正在尝试在 Job 和 Deliverable 之间映射“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(Job)) .Add(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);
   }
}

那么,映射是否不正确,或者我使用它们的方式有什么问题?

非常感谢,我整天都在盯着这个。

【问题讨论】:

    标签: nhibernate fluent-nhibernate fluent-nhibernate-mapping db2-400


    【解决方案1】:

    在多对一关系中(在我们的例子中是DelivarableJob),关系本身用one DB 列表示。子表 (Deliverable) 有(必须有)一个带有 Job ID (Code) 的引用列。

    因此,我们的映射需要的是 Delivarable 表中的列,其中包含与 Job 的关系。 JobCode 列。 (不确定是否有,来自上面的示例)

    而且这个必须两边都用:

    可交付:

    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 对象的 ID(列 CODE)与对 Job(列 CODE)的引用相同。这似乎很奇怪。

    这也解释了这样一个事实,即 JOB 集合中的所有可交付项目都是相同(相同)。 Unique Deliverable(由其 CODE 定义)只能是一个。此场景中的 Job 不能有多个可交付成果(因为它由唯一的 CODE 列引用)。这似乎是一对一场景。

    更多相同的原因更难判断。很高兴看到您正在使用的查询。

    但我真的会检查两次列映射。 Deliverable,应该在名为“JobCODE”的列中引用Job...支持更多Delivrables关联...

    【讨论】:

    • 谢谢 - 我已经更正了我原来问题中的错误。我的代码基本上和你上面建议的一样。生成的 SQL 在复制并在本地运行时会生成所需的结果,但是我的代码生成的可交付成果集合具有正确数量的结果,但结果相同。
    • 我扩展了我的答案。对我来说真正奇怪的是作为 ID 和工作参考的“代码”列......
    • 实际文件与用于连接它们的字段具有相同的字段名称 - 交付物有一个由这个组成的“复合”键和一个唯一的参考 - 即工作 (1) ->可交付成果 (1) (1), 工作 (1) -> 可交付成果 (1) (2), 工作 (1) -> 可交付成果 (1) (3), 工作 (1) -> 可交付成果 (2) (1),等(对不起格式)
    • 对不起,如果我不明白。但是您的映射显示:ID 到 CODE 和 ReferenceId 到 CODE。这对我来说似乎是个问题。但也许我没有正确理解。如果您使用 CODE 映射(如在您的 sn-p 中)并且 CODE 是 ID(唯一),那么对我来说这似乎是问题所在。 建议:提供真实的映射。只有这样我们才能找到问题;)
    • 每个基础表都有一个名为“CODE”的字段,对此我无能为力。这似乎是问题的原因。即使我更改了类中字段的名称,底层字段名称似乎也会产生干扰。正如我最初发布的那样,生成的 SQL 确实“工作”,似乎只是 Fluent NHibernate 感到困惑。
    【解决方案2】:

    我似乎已经修复了它。我在 Deliverables 映射中添加了 CompositeID

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

    这意味着我必须在 Deliverable 类中覆盖以下内容

    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 现在是什么样子,但答案看起来是正确的。

    【讨论】:

    • 是的,这是有道理的。正如我所说,映射为 ID 和 referenceId 的 CODE 是不够的。缺少真正的唯一 ID 是导致该问题的原因。很好,你让它为你工作。享受 NHiberante ;)
    • 感谢您的帮助。这一切都开始变得有意义
    • 太棒了;)真的太棒了;)
    猜你喜欢
    • 2012-04-03
    • 2012-10-19
    • 2012-07-26
    • 2011-04-10
    • 1970-01-01
    • 2013-01-07
    • 2013-04-04
    • 1970-01-01
    • 2013-04-24
    相关资源
    最近更新 更多