Как мне выразить этот запрос LINQ с помощью API NHibernate ICriteria? - PullRequest
5 голосов
/ 29 октября 2010

Мой текущий проект использует NHibernate 3.0b1 и NHibernate.Linq.Query<T>() API.Я довольно свободно владею LINQ, но у меня нет абсолютно никакого опыта работы с HQL или ICriteria API.Один из моих запросов не поддерживается API IQueryable, поэтому я предполагаю, что мне нужно использовать один из предыдущих API - но я не знаю, с чего начать.

Я попытался найти в Интернетехорошее руководство по началу работы с ICriteria, но единственные примеры, которые я нашел, либо слишком упрощены для применения здесь, либо слишком сложны для понимания.Если у кого-то есть хорошие учебные материалы для передачи, это будет очень полезно.

В любом случае объектная модель, к которой я обращаюсь, выглядит следующим образом (очень упрощенные, нерелевантные свойства опущены):

class Ticket {
    IEnumerable<TicketAction> Actions { get; set; }
}
abstract class TicketAction {
    Person TakenBy { get; set; }
    DateTime Timestamp { get; set; }
}
class CreateAction : TicketAction {}
class Person {
    string Name { get; set; }
}

A Ticket имеет коллекцию TicketAction, описывающую его историю.TicketAction подтипы включают CreateAction, ReassignAction, CloseAction и т. Д. Все заявки имеют добавленный CreateAction в эту коллекцию при создании.

Этот запрос LINQ ищет заявки, созданные кем-то сданное имя.

var createdByName = "john".ToUpper();
var tickets = _session.Query<Ticket>()
    .Where(t => t.Actions
        .OfType<CreateAction>()
        .Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName));

Метод OfType<T>() вызывает выброс NotSupportedException.Могу ли я сделать это, используя вместо этого ICriteria?

Ответы [ 2 ]

2 голосов
/ 01 ноября 2010

попробуйте что-то вроде этого.Он не скомпилирован, но должен работать до тех пор, пока IEnumerable<TicketAction> Actions и Person TakenBy никогда не равны нулю.Если вы установите пустой список в конструкторе заявок, это решит проблему с нулями.

Если вы добавите ссылку на объект Ticket в TicketAction, вы можете сделать что-то вроде этого:

ICriteria criteria = _session.CreateCriteria(typeof(CreateAction))
   .Add(Expression.Eq("TakenBy.Name", createdByName));

var actions = criteria.List<CreateAction>();

var results = from a in criteria.List<>()
   select a.Ticket;

По моему опыту, nhibernate имеет проблемы с критериями, когда речь идет о списках, когда список находится на стороне объекта - как, например, в вашем случае.Когда это список значений на стороне ввода, вы можете использовать Expression.Eq.Мне всегда приходилось находить способы обойти это ограничение через linq, где я получаю первоначальный набор результатов, отфильтрованный как можно лучше, а затем снова фильтрую с помощью linq, чтобы получить то, что мне нужно.

0 голосов
/ 03 ноября 2010

OfType поддерживается. Я не уверен, что ToUpper, хотя, но SQL игнорирует регистр, это не имеет значения (если вы не выполняете запрос в памяти ...). Вот рабочий тестовый модуль из проекта nHibernate.LINQ:

var animals = (from animal in session.Linq<Animal>()
               where animal.Children.OfType<Mammal>().Any(m => m.Pregnant)
               select animal).ToArray();
Assert.AreEqual("789", animals.Single().SerialNumber);

Возможно, ваш запрос должен выглядеть примерно так:

var animals = (from ticket in session.Linq<Ticket>()
               where ticket.Actions.OfType<CreateAction>().Any(m => m.TakenBy.Name.Contains("john"))
               select ticket).ToArray();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...