Question

I have scenario where I need to conduct the sorting on a property (User.Name) in the NHibernate QueryOver query where the property contains a string that I need to grab the last portion of a name and order ASC. If I was doing it on the returned results, it might be something like:

.....
var query = session.QueryOver<User>().....
.....
query.OrderBy(u => SortByLastName(u.Name));

private string SortByLastName(string name)
    {
        if (string.IsNullOrEmpty(name)) {
            name = " ";
        }

        var nameArray = name.Trim().Split(' ');
        var lastName = nameArray[nameArray.Length - 1];

        return lastName.ToLower();
    }

In SQL it would be a combination of the SUBSTRING, CHARINDEX (and possibly other functions) to grab the last portion of a name (ie. Joe Smith, Jane A. Doe) and sort on the last name.

Question

Is there a way in NHibernate QueryOver to set this up where you didn't have to roll it up in a Stored Proc which is called by the NHibernate or passing in the Raw SQL query through .CreateSQlQuery(sql)?

But instead build this logic directly into the QueryOver?

Was it helpful?

Solution

You can do this by creating Projections that call SQL functions. In your case there are nested functions, so there will be multiple building steps.

Here is a draft solution. I haven't tested it, but it gives the idea of the approach:

IProjection nameField = Projections.Property<User>(u => u.Name);
IProjection charIndex = Projections.SqlFunction("CHARINDEX",
                                                NHibernateUtil.String,
                                                nameField,
                                                Projections.Constant(" ", NHibernateUtil.String)
                                               );
IProjection subString = Projections.SqlFunction("SUBSTRING",
                                                nHibernateUtil.String,
                                                nameField,
                                                charIndex,
                                                Projections.Constant(999, NHibernateUtil.UInt32);



var query = session.QueryOver<User>().OrderBy(subString).Asc;

Unfortunately, this solution would not work if there are spaces in the first name. (Jane A. Doe). I'm not aware of an SQL function to find the last space in a string.

See this discussion: Find index of last occurrence of a sub-string using T-SQL

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top