3

I needed to filter a list of results using the combination of two properties. A plain SQL statement would look like this:

SELECT TOP 10 *
FROM Person
WHERE FirstName + ' ' + LastName LIKE '%' + @Term + '%'

The ICriteria in NHibernate that I ended up using was:

ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Sql(
    "FirstName + ' ' + LastName LIKE ?",
    "%" + term + "%",
    NHibernateUtil.String));
criteria.SetMaxResults(10);

It works perfectly, but I'm not sure if it is the ideal solution since I'm still learning about NHibernate's Criteria API. What are the recommended alternatives?

  • Is there something besides Expression.Sql that would perform the same operation? I tried Expression.Like but couldn't figure out how to combine the first and last names.
  • Should I map a FullName property to the formula "FirstName + ' ' + LastName" in the mapping class?
  • Should I create a read only FullName property on the domain object then map it to a column?
DavGarcia
  • 18,540
  • 14
  • 58
  • 96

2 Answers2

13

You can do one of the following:


Session.CreateCriteria<Person>()
       .Add(Restrictions.Like(
            Projections.SqlFunction("concat",
                                    NHibernateUtil.String,
                                    Projections.Property("FirstName"),
                                    Projections.Constant(" "),
                                    Projections.Property("LastName")),
            term,
            MatchMode.Anywhere))
DavGarcia
  • 18,540
  • 14
  • 58
  • 96
Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
  • Query-only - how very useful, didn't know about that option. Seems like I learn something new every day in NHibernate. Thanks for the Projections code sample too. – DavGarcia May 30 '10 at 05:58
0

On the pure technical side i don't have an answer, but consider this: since you are only have a single input field for the user to enter the term, you don't know if he is going to enter 'foo bar' or 'bar foo'... so i would recommend this:

ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Like("FirstName",term, MatchMode.Anywhere) || Expression.Like("LastName",term, MatchMode.Anywhere));
criteria.SetMaxResults(10);
Jaguar
  • 5,929
  • 34
  • 48
  • Thanks for the suggestions. Originally I tried that but people were typing in "john smi" and expecting to see John Smith pop up. – DavGarcia May 30 '10 at 05:59
  • I handle this case by looking if there is no space I match against first or last if there is a space I then split the search string and search against the first and last again. – JoshBerke Jan 15 '13 at 20:10