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?
Était-ce utile?

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top