2010-12-31 6 views
1

У меня есть следующий запрос и его сбой в Nhibernate 3 LINQ с исключением «Non supported». Его similar to this question, но этот вопрос был задан более года назад, поэтому я уверен, что ответ устарел.Почему doesnt 'nhibernate поддерживает этот синтаксис «существует в списке»?

столы

Мои БД являются:

  1. VacationRequest (идентификатор, PersonId)
  2. VacationRequestDate (идентификатор, vacationRequestId)
  3. Person (ID, FirstName, LastName)

Мои Сущности :

  1. VacationRequest (Perso п, IList)
  2. VacationRequestDate (VacationRequest Дата)

Вот запрос, получение "Non поддерживается" Exception

Session.Query<VacationRequestDate>() 
    .Where(r => people 
    .Contains(r.VacationRequest.Person, new PersonComparer())) 
    .Fetch(r=>r.VacationRequest) 
    .ToList(); 

есть лучший способ, чтобы написать это, что бы поддерживается в Нюбернате?

fyi. . PersonComparer только что сравнил person.Id

ответ

1

NHibernate не понимает тип PersonComparer и поэтому не может перевести его использование в SQL.

Вы пытались использовать перегрузку Contains, которая не принимает компаратора? NHibernate следует сделать вывод, что вы сравниваете экземпляры сущностей и правильно использовать идентификатор в сравнении SQL (что еще он мог бы использовать?):

Session.Query<VacationRequestDate>() 
    .Where(r => people.Contains(r.VacationRequest.Person)) 
    .Fetch(r => r.VacationRequest) 
    .ToList(); 

Кроме того, имейте в виду, что в рамках одной сессии NHibernate, тот же экземпляр объекта всегда возвращается для того же ID. Это означает, что person1 == person1 всегда должно быть истинным, если оба экземпляра Person были извлечены из того же сеанса. Это также связано с отношениями, поэтому vacationRequest1.Person == vacationRequest2.Person также будет истинным в том же сеансе, если оба запроса на отпуск имеют одинаковый идентификатор человека.

Это означает, что вы можете полностью избавиться от PersonComparer, если вы не смешиваете объекты из нескольких сеансов через кеширование.

2

nhibernate не может перевести ваш new PersonComparer(), вы должны его изменить.

+0

как бы это перевести – leora

+0

@ooo, если вы видите дерево выражений в режиме отладки вы можете видеть, что он не может это сделать, но я думаю, что если вы переопределите равный член своего «Лица», это можно сделать осторожно. [но если вы переопределите его раньше для другой цели, я предлагаю использовать hql] –

0

Для начала он не может выполнить код в соответствии с этим в вашем db.

Ну вот мои предложения о том, как идти об этом

var peopleIds= people.Select(x=>x.Id); 
Session.Query<VacationRequestDate>() 
    .Where(r => peopleIds.Contains(r.VacationRequest.PeopleId)).ToList() 
    .Where(x=>people.Contains(r.VacationRequest,new   
    PersonComparer()).Select(r=>r.VacationRequest).ToList() 

Если вы думаете, разве ВАЗ tyou хочет сделать, то я хотел бы предложить вам попробовать свои силы в Criteria запросах или HQL, и вы можете получить именно то, что вы хотите от db.

Вы также можете использовать свой компаратор следующим образом. Мне нравится делать мой общий. Вы можете сделать это и для сравнения строк, и здесь вы добавите свою логику игнорирования и т. Д.

public class ComparerByIntId<T> : IEqualityComparer<T> 
    where T : class, IIntegerIdentifiable 
{ 
    public bool Equals(T x, T y) 
    { 
     if (x == null && y == null) 
      return true; 

     if (x == null || y == null) 
      return false; 

     return x.Id == y.Id; 
    } 

    public int GetHashCode(T obj) 
    { 
     return base.GetHashCode(); 
    } 
} 

Теперь, когда вы запускаете запрос будет выглядеть следующим образом:

Session.Query<VacationRequestDate>() 
    .Where(r => people 
    .Contains(r.VacationRequest.Person, new ComparerByIntId<Person>())) 
    .Select(r=>r.VacationRequest) 
    .ToList(); 

Надежда, что помогает

+0

'Where (r => peopleIds.Contains (r.VacationRequest.PeopleId)). ToList()' не является хорошим предложением, загрузка всех данных может быть причиной к сбою тоже медленно –

+0

Как он загружает все данные? и мы в человеке 21-го века .. что вы имеете в виду, это сбой. говорят, что данные каждого человека составляют 1024 байта, поэтому общее пространство, скажем, 1024 записанных записей, составляет 1024 * 1024 = 1 мб памяти, которые, я думаю, являются управляемыми, если только мы не задумываемся о наличии ограничений mem для 1mb. – Baz1nga

Смежные вопросы