почему nhibernate не поддерживает этот синтаксис "существует в списке"? - PullRequest
1 голос
/ 31 декабря 2010

У меня следующий запрос, и он не работает в Nhibernate 3 LINQ с исключением «Не поддерживается». Это похоже на этот вопрос , но этот вопрос был задан более года назад, поэтому я уверен, что ответ устарел.

Мои таблицы БД:

  1. VacationRequest (id, personId)
  2. VacationRequestDate (id, отпускRequestId)
  3. Персона (id, Имя, Фамилия)

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

  1. VacationRequest (Персона, IList)
  2. VacationRequestDate (VacationRequest, Date)

Вот запрос, который получает исключение «Не поддерживается»

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

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

к вашему сведению . PersonComparer только что сравнил person.Id

Ответы [ 3 ]

2 голосов
/ 01 января 2011

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

1 голос
/ 01 января 2011

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

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

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

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

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

0 голосов
/ 01 января 2011

Для начала он не может выполнить код против этого в вашей БД.

Вот мои предложения о том, как это сделать

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

Если вы считаете, что это не то, что вы хотите, то я бы посоветовал вам попробовать свои силы в запросах Criteria или HQL ивы можете получить именно то, что вы хотите от БД.

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

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

Hopeэто помогает

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