Search code examples
c#nhibernatefluent-nhibernate

How to use datediff sql function in nHibernate?


I am developing an application to test execution time SQL queries using different frameworks. I have some problem to write one of the queries using Fluent nHibernate. The query should return all employees that are older than 50 years. In some page I found the DateProjections class which I attach below.

public static class DateProjections
    {
        private const string DateDiffFormat = "datediff({0}, ?1, ?2)";

        public static IProjection DateDiff(
            string datepart,
            Expression<Func<object>> startDate,
            Expression<Func<object>> endDate)
        {
            // Build the function template based on the date part.
            string functionTemplate = string.Format(DateDiffFormat, datepart);

            return Projections.SqlFunction(
                new SQLFunctionTemplate(NHibernateUtil.Int32, functionTemplate),
                NHibernateUtil.Int32,
                Projections.Property(startDate),
                Projections.Property(endDate));
        }
    }

The function to get employees is the following:

public List<EmployeeAgeViewModel> GetEmployeesOlderThan50()
        {
            Person personAlias = null;
            EmployeeAgeViewModel result = null;

            var temp = _session.QueryOver<Employee>().JoinQueryOver(x => x.Person, () => personAlias).SelectList(
                list => list
                .Select(x => personAlias.FirstName).WithAlias(() => result.FirstName)
                .Select(x => personAlias.LastName).WithAlias(() => result.LastName)
                .Select(x => x.Gender).WithAlias(() => result.Gender)
                .Select(x => x.BirthDate).WithAlias(() => result.BirthDate)
                .Select(x => x.HireDate).WithAlias(() => result.HireDate)
                .Select(DateProjections.DateDiff("yy", () => personAlias.Employee.BirthDate, () => DateTime.Now)).WithAlias(() => result.Age)
                )
                .TransformUsing(Transformers.AliasToBean<EmployeeAgeViewModel>())
                .List<EmployeeAgeViewModel>();

            return temp.ToList();

The problem is probably the way I am passing BirthDate property and DateTime.Now to DateDiff function. In the personAlias variable the Employee property is null - maybe I should assign it somehow before - any help will be appreciated.


Solution

  • Instead of personAlias.Employee.BirthDate you need to use an employeeAlias.

    Your code with the necessary changes looks like this:

    Person personAlias = null;
    Employee employeeAlias = null;
    EmployeeAgeViewModel result = null;
    
    var temp = _session.QueryOver<Employee>(() => employeeAlias)
        .JoinQueryOver(x => x.Person, () => personAlias)
        .SelectList(
            list => list
            .Select(x => personAlias.FirstName).WithAlias(() => result.FirstName)
            .Select(x => personAlias.LastName).WithAlias(() => result.LastName)
            .Select(x => x.Gender).WithAlias(() => result.Gender)
            .Select(x => x.BirthDate).WithAlias(() => result.BirthDate)
            .Select(x => x.HireDate).WithAlias(() => result.HireDate)
            .Select(DateProjections.DateDiff("yy", () => employeeAlias.BirthDate, () => DateTime.Now))
                .WithAlias(() => result.Age)
            )
        .TransformUsing(Transformers.AliasToBean<EmployeeAgeViewModel>())
        .List<EmployeeAgeViewModel>();
    
    return temp.ToList();