Critères NHibernate - Comment filtrer sur combinaison de propriétés
-
05-10-2019 - |
Question
Je avais besoin de filtrer une liste de résultats en utilisant la combinaison de deux propriétés. Une instruction SQL simple ressemblerait à ceci:
SELECT TOP 10 *
FROM Person
WHERE FirstName + ' ' + LastName LIKE '%' + @Term + '%'
Le ICriteria à NHibernate que je fini par utiliser était:
ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Sql(
"FirstName + ' ' + LastName LIKE ?",
"%" + term + "%",
NHibernateUtil.String));
criteria.SetMaxResults(10);
Il fonctionne parfaitement, mais je ne suis pas sûr que ce soit la solution idéale puisque je suis encore à apprendre au sujet de l'API Critères de NHibernate. Quelles sont les alternatives recommandées?
- Y at-il quelque chose en plus
Expression.Sql
qui effectuer la même opération? J'ai essayéExpression.Like
mais ne pouvait pas comprendre comment combiner les noms et prénoms. - Devrais-je mapper une propriété FullName à la formule "+ FirstName '' + LastName" dans la classe de cartographie?
- Dois-je créer une propriété en lecture seule FullName sur l'objet de domaine la carte puis à une colonne?
La solution
Vous pouvez faire un des éléments suivants:
- Si vous travaillez toujours avec le nom complet, il est probablement préférable d'avoir une seule propriété
- Créer une propriété de requête uniquement à cette fin (voir http://ayende.com/Blog/archive/2009/06/10/nhibernate-ndash-query-only-properties.aspx )
- Est-ce que la requête dans HQL, ce qui est mieux adapté pour les requêtes de forme libre (il sera probablement à peu près le même que votre SQL)
- sur un critère basé entité-appropriés:
Session.CreateCriteria<Person>()
.Add(Restrictions.Like(
Projections.SqlFunction("concat",
NHibernateUtil.String,
Projections.Property("FirstName"),
Projections.Constant(" "),
Projections.Property("LastName")),
term,
MatchMode.Anywhere))
Autres conseils
Sur le plan technique pur je n'ai pas de réponse, mais considérez ceci: puisque vous avez seulement un seul champ d'entrée pour l'utilisateur d'entrer le terme, vous ne savez pas s'il va entrer dans « foo bar » ou « bar foo » ... donc je recommande ceci:
ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Like("FirstName",term, MatchMode.Anywhere) || Expression.Like("LastName",term, MatchMode.Anywhere));
criteria.SetMaxResults(10);