Лучшим (и самым надежным) способом, конечно же, было бы использование значений NULL
вместо минимальных значений datetime
. Если вы сделали это (или измените приложение для этого), тогда код, который вы написали, будет работать так, как написано. Как сейчас, я гарантирую, что эти фиктивные ценности вернутся, чтобы преследовать кого-то в конце концов (если это настоящее приложение). Может, не ты, а следующий парень. Конечно, вы также должны нормализовать эту таблицу ...
Но в любом случае. Подробнее об этом позже. Вы задали конкретный вопрос.
Вот код, который должен был работать (не из-за отсутствия тестирования - продолжать чтение).
DateTime bogusDate = new DateTime(1753, 1, 1);
ICriteria criteria =
session.CreateCriteria(typeof(Voyage))
.SetProjection
(
Projections.ProjectionList()
.Add
(
Projections.Min
(
Projections.Conditional
(
Restrictions.Eq("Departure", bogusDate),
Projections.Constant(DateTime.MaxValue, NHibernateUtil.DateTime),
Projections.Property("Departure")
)
)
)
.Add(Projections.Max("Arrival"))
.Add(Projections.GroupProperty("Id"))
);
(Единственная причина, я посылаю DateTime.MaxValue
потому, что NHibernate заставляет условными истина/ложь результаты того же типа, и я не мог понять, как получить NULL
в true
части.)
этот код отправляет этот запрос в двигатель DB (я использую SQL Server 2005 диалекте при поддержке SQL Express 2005):
SELECT min((case when this_.Departure = ? then ? else this_.Departure end)) as y0_,
max(this_.Arrival) as y1_,
this_.Id as y2_
FROM Voyages this_
GROUP BY this_.Id;
@p0 = 1/1/1753 12:00:00 AM,
@p1 = 12/31/9999 11:59:59 PM
который выглядит хорошо. Теперь я говорю, что должен работать, потому что когда вы подключаете параметры и запускаете запрос непосредственно на движке, он дает желаемые результаты. Тем не менее, на моей машине, используя NHibernate, все взрывается:
System.Data.SqlClient.SqlException: Incorrect syntax near '?'.
Который говорит мне, что SQL Server не likie позиционных параметров в CASE
отчетности. Braindead, если это правда. Это может быть не проблема в 2008 году, хотя я не тестировал - я упоминаю SQL Server специально, потому что я предполагаю, что это то, что вы используете с 1/1/1753, является минимальной датой, которую она разрешает в datetime
.
Итак, где же это проблема? Есть варианты.
- Исправить схему базы данных, как указано в моем первом абзаце (идеальном). Обратите внимание, что вам не нужно указывать любые значения
NULL
в ваши данные, если схема нормализована.
- Посмотрите, можете ли вы написать запрос с помощью HQL (я не эксперт, поэтому я даже не мог сказать, возможно ли это).
- Узнайте, что это не проблема в SQL 2008+ и/или в вашем целевом движке базы данных, и это все, на что вы когда-либо собираетесь настроить таргетинг.
- Перепишите запрос, чтобы полностью обойти сумасшедшие значения и использовать вместо этого столбец
OrderIndex
. Я написал это в SQL - я не уверен, как написать это с помощью ICriteria
(и если вы хотите, чтобы это наказание, сделайте себе одолжение и потратьте время на вариант № 1). Обратите внимание, что это меньше, чем в два раза быстрее, чем исходный запрос, который почти оптимален AFAIK:
SELECT
s.Id,
v1.Departure,
v2.Arrival
FROM
(
SELECT DISTINCT
Id,
MAX(OrderIndex) AS MaxIndex,
MIN(OrderIndex) AS MinIndex
FROM Voyages
GROUP BY Id
) s
INNER JOIN Voyages v1 ON v1.Id = s.Id AND v1.OrderIndex = MinIndex
INNER JOIN Voyages v2 ON v2.Id = s.Id AND v2.OrderIndex = MaxIndex
ничего себе, что это довольно хорошее усилие на вопрос с пару месяцев старых (почти мертв) =), мое мнение идет по первому варианту и исправляет этот грязный дизайн, если вы спросите меня, что у меня есть OrderIndex в дополнение к Ordered by Arrival, а затем отправлением кажется немного запутанным, вы должны вернуться и переосмыслить, если вы действительно хотите этого «1/1/1753 00:00:00 «возиться, если порт с прибытием, но не выезд (и наоборот) действительно подходит вашей модели ?, с моей точки зрения, это не имеет смысла, вы, возможно, могли бы принять дату, если пользователь не предусматривает этого. – JOBG
@ Омар: Да. Если бы я возился с дизайном, я бы нормализовался в таблицу отправлений и таблицу прибытий, а затем, вероятно, создавал индексированное представление для рейсов. Тогда не было бы необходимости делать сумасшедший запрос на уровне приложения! –