帮我翻译成适当的NHibernate ......
我有一个包含2个表的Oracle数据库:
Employees:
Id (unique id)
FirstName (string)
LastName (string)
Location (string)
Locations:
Name (string)
Address (string)
正如您所看到的,Employees表具有唯一的ID,但Locations表没有任何ID。 “名称”字段是常规字段,不是唯一的。
在Oracle SQL中,我可以运行以下查询:
SELECT *
FROM Employees e
LEFT OUTER JOIN Locations l
ON e.Location = l.Name
WHERE e.Id = 42
员工42所在的位置在“位置”表中有2行,因此此查询返回2行,每个位置为员工42找到的每个位置。
好吧,我无法弄清楚如何将其转换为NHibernate映射+查询(我使用Fluent NHibernate)。我倾向于认为我应该将Employees.Location映射为Locations.Name的引用,因此在运行我的HQL查询时它应该返回2个对象,但是NHibernate不允许我从Reference中检索列表。所以我尝试了HasMany,但它也不起作用,因为NHibernate希望Locations中的一个字段引用回雇员,这有点意义。
我的HQL查询如下所示:
select e
from Employees e
left join e.Locations l
where e.SGId like :sgId
为什么我可以在常规SQL中而不是在NHibernate中执行此操作?
感谢。
答案 0 :(得分:1)
我找到了解决方案,你必须将HasMany(x => x.Locations)与.PropertyRef(“Location”)结合使用,以便hibernate知道要用于连接的Employee中的字段应该是Location (而不是默认的员工ID)。
class Employee
{
public virtual int Id {get;set}
public virtual string FirstName {get;set;}
public virtual string LastName {get;set;}
public virtual string Location {get;set;}
public virtual IList<Location> Locations {get;set;}
}
class EmployeeMapping : ClassMap<Employee>
{
public EmployeeMapping()
{
Id(x=>x.Id);
Map(x=>x.FirstName);
Map(x=>x.LastName);
Map(x=>x.Location);
HasMany<Location>(x => x.Locations)
.PropertyRef("Location")
.KeyColumn("Name");
}
}
此外,我发现我的方法存在一些缺陷,主要是由于我正在使用的奇怪的遗留数据库。这并没有改变解决方案,但我想补充一点,如果你正在处理的其中一个表没有唯一的ID,那你就麻烦了。 Hibernate需要一个唯一的id,所以在我的情况下,我必须想出一个由多个字段组成的复合id,以使其独一无二。这是另一场辩论,但我想在此提及它,以帮助将来研究这一主题的人。
答案 1 :(得分:0)
对于您的映射,如果要为一名员工返回2个位置,则需要在员工映射中使用集合/数组/列表/集对象和HasMany
class Employee
{
public virtual int Id {get;set}
public virtual string FirstName {get;set;}
public virtual string LastName {get;set;}
public virtual IList<Location> Location {get;set;}
}
class EmployeeMapping : ClassMap<Employee>
{
public EmployeeMapping()
{
Id(x=>x.Id);
Map(x=>x.FirstName);
Map(x=>x.LastName);
HasMany<Location>(x => x.Location)
.KeyColumn("Name")
.PropertyRef("Location")
.LazyLoad();
}
}