Le meilleur (et le plus sain) moyen, bien sûr, serait d'utiliser les valeurs NULL
au lieu des valeurs minimum datetime
. Si vous aviez fait cela (ou changé votre application pour le faire), alors le code que vous avez écrit fonctionnera comme écrit. De la façon dont c'est maintenant, je garantis que ces fausses valeurs reviendront hanter quelqu'un (si c'est une vraie application). Peut-être pas vous, mais le prochain gars. Bien sûr, vous devriez également normaliser ce tableau ...
Mais de toute façon. Plus sur ce truc plus tard. Vous avez posé une question spécifique.
Voici le code devrait de travail (pas faute de tests - continuer à lire).
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"))
);
(La seule raison pour laquelle je suis l'envoi d'une DateTime.MaxValue
est parce que NHibernate force les résultats vrais/faux conditionnels au même type, et je ne pouvais pas comprendre comment obtenir un NULL
dans la partie true
.)
ce code envoie cette requête au moteur DB (j'utilise SQL Server 2005 dialecte soutenu par 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
ce qui a l'air bien. Maintenant, je dis cela devrait de travail, parce que lorsque vous branchez les paramètres et exécutez la requête directement sur le moteur, il donne les résultats souhaités. Cependant, sur ma machine, en utilisant NHibernate, tout explose:
System.Data.SqlClient.SqlException: Incorrect syntax near '?'.
Ce qui me dit que SQL Server aucun paramètre de position de likie dans CASE
déclarations. Braindead si c'est vrai. Cela peut ne pas être un problème en 2008+, bien que je n'ai pas testé - je mentionne SQL Server spécifiquement parce que je suppose que c'est ce que vous utilisez depuis le 1/1/1753 est la date minimale qu'il permet dans un datetime
.
Alors, où cela laisse-t ce problème? Il y a des options.Fixer le schéma de la base de données comme mentionné dans mon tout premier paragraphe (idéal)
- Notez que vous ne devrez pas autoriser des valeurs
NULL
dans vos données si le schéma est normalisé.
- Voyez si vous pouvez écrire la requête en utilisant HQL à la place (je ne suis pas un expert, donc je ne pourrais même pas dire si c'est possible).
- Découvrez que ce n'est pas un problème dans SQL 2008+ et/ou vos moteurs de base de données cible et c'est tout ce que vous allez cibler.
- Réécrire la requête pour contourner entièrement les valeurs folles et exploiter la colonne
OrderIndex
à la place. J'ai écrit cela en SQL - Je ne suis pas sûr de savoir comment écrire cela en utilisant ICriteria
(et si vous voulez la punition de cela, faites-vous une faveur et passez le temps sur l'option n ° 1 à la place). Notez que cela est moins de la moitié aussi vite que la requête initiale, qui est AFAIK presque optimale:
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
wow qui est un très bon effort pour une question avec deux ou trois mois (presque mort) =), mon avis aller pour la première option et réparer ce design désordonné, si vous me demandez d'avoir le OrderIndex en plus d'une commande par arrivée puis par départ semblent un peu confus, vous devriez revenir en arrière et repenser si vous voulez vraiment ce "1/1/1753 00:00:00 "déconner, si un port avec une arrivée mais pas de départ (et vice versa) correspond vraiment à votre modèle ?, de mon point de vue, il n'a pas de sens, vous pourriez peut-être supposer une date si l'utilisateur ne fournit pas cela. – JOBG
@Omar: Oui. Si je me trompais dans la conception, je normaliserais dans une table de départs et une table des arrivées, alors probablement créer une vue indexée pour les voyages. Ensuite, il n'y aurait pas besoin de faire une requête folle au niveau de l'application! –