我访问了一个预先存在的数据库(实际上是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运算(工作)) .Add(Expression.Eq(“Code”,“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);
}
}
那么,映射是否不正确,或者是否存在我使用它们的方式?
非常感谢,我一整天都在盯着这个。
答案 0 :(得分:2)
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现在是什么样的,但答案看起来是正确的。
答案 1 :(得分:1)
在多对一关系中(在我们的案例中为Delivarable
和Job
),关系本身用一个数据库列表示。子表(Deliverable
)具有(必须具有)具有作业 ID(代码)的引用列。
因此,我们的映射需要的是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
}
。 (不确定是否有任何,例如上面的例子)
这必须在双方都使用:
Delivarable:
public JobMap()
{
...
HasMany(x => x.Deliverables)
.KeyColumn("JobCode"); // column of table Deliverable
}
作业:
Deliverable
换句话说,此映射中的两个列名实际上都是一个列的名称。两者都映射到子(可交付)表的列。
EXTENDED:基于问题中的映射变化
ID
对象的Job
(列CODE)与{{1}}(列CODE)的引用相同。这似乎很奇怪。
这也解释了这样一个事实,即JOB集合中的所有可交付项目都是相同(相同)。 Unique Deliverable(由其CODE定义)只能是一个。此场景中的Job不能有多个Deliverable(因为它由唯一的CODE列引用)。它似乎是一对一的场景。
更多项相同的原因更难判断。很高兴看到你正在使用的查询。
但我真的会两次检查列映射。可交付的,应该在名为“JobCODE”的列中引用Job ...支持更多Delivrables相关...