Как запросить базу данных Oracle с помощью NHibernate? - PullRequest
1 голос
/ 07 сентября 2011

Помогите мне перевести это на правильный NHibernate ...

У меня есть база данных Oracle с 2 таблицами:

Employees:
    Id (unique id)
    FirstName (string)
    LastName (string)
    Location (string)

Locations:
    Name (string)
    Address (string)

Как видите, таблица Employees имеет уникальный идентификатор, но таблица Locations вообще не имеет идентификатора. Поле Имя является обычным и не уникальным.

В Oracle SQL я могу выполнить следующий запрос:

SELECT *
FROM Employees e
LEFT OUTER JOIN Locations l
ON e.Location = l.Name
WHERE e.Id = 42

Местоположение, в котором находится сотрудник 42, имеет 2 строки в таблице Locations, поэтому этот запрос возвращает 2 строки, по одной для каждого местоположения, найденного для сотрудника 42.

Ну, я не могу понять, как перевести это в запрос сопоставления NHibernate + (я использую Fluent NHibernate). Я склонен думать, что мне следует сопоставить Employees.Location как ссылку на Locations.Name, и поэтому при выполнении HQL-запроса он должен возвращать 2 объекта, но NHibernate не позволил бы мне получить список из ссылки. Поэтому я попробовал HasMany, но он тоже не работает, потому что NHibernate хочет, чтобы в Locations было поле, ссылающееся на Employees, что в некотором роде имеет смысл.

Мой HQL-запрос выглядит так:

select e
from Employees e
left join e.Locations l
where e.SGId like :sgId

Почему я могу сделать это в обычном SQL, а не в NHibernate?

Спасибо.

Ответы [ 2 ]

1 голос
/ 07 сентября 2011

Я нашел решение, вы должны использовать HasMany (x => x.Locations) в сочетании с .PropertyRef ("Location"), чтобы hibernate знал, что поле в Employee, которое будет использоваться для объединения, должно быть Location ( а не идентификатор сотрудника, как по умолчанию).

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

Также я обнаружил несколько недостатков в моем подходе, главным образом из-за странной устаревшей базы данных, с которой я работаю. Это не меняет решения, но я хочу добавить, что если одна из таблиц, с которыми вы работаете, не имеет уникальных идентификаторов, у вас проблемы. Hibernate нужен уникальный идентификатор, поэтому в моем случае мне пришлось придумать составной идентификатор из нескольких полей, чтобы сделать его уникальным. Это еще одна дискуссия, но я хотел бы упомянуть ее здесь, чтобы помочь тем, кто исследует эту тему в будущем.

0 голосов
/ 07 сентября 2011

Для сопоставления вам нужно использовать объект collection / array / list / set и HasMany на ваших сотрудниках, отображающих местоположение, если оно собирается вернуть 2 местоположения для одного сотрудника

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

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...