如何使用NHibernate查询Oracle数据库?

时间:2011-09-06 21:13:26

标签: nhibernate fluent-nhibernate

帮我翻译成适当的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中执行此操作?

感谢。

2 个答案:

答案 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();

    }
}