简体   繁体   中英

How to use SQL functions in Dapper?

I am doing an application that benchmarks selected ORMs (EF,NHibernate,Dapper). I am developing it in .NET Core 2.0 and I am using AdventureWorks database for it. I have a problem with the query that returns all employees that has age more than 50. I don't know how can I use SQL function DateDiff, or I need some other way to do this via SQL. Here is the snippet from my DapperRepository class:

  public List<EmployeeAgeViewModel> GetEmployeesOlderThan50()
    {
        string sqlQuery = @"select Person.BusinessEntityID as PersonID, Person.LastName,
                    Person.FirstName,
                    Employee.BusinessEntityID as EmployeeID,
                    Employee.Gender,
                    Employee.BirthDate,
                    Employee.HireDate,
                    DATEDIFF(YEAR, Employee.BirthDate, GETDATE()) as [WIEK]
                FROM Person.Person
                    JOIN HumanResources.Employee
                    ON Person.BusinessEntityID = Employee.BusinessEntityID
                WHERE DATEDIFF(YEAR, Employee.BirthDate, GETDATE()) >= 50
                ORDER BY Wiek DESC";

        var employeesAge = _con.Query<Person, Employee, EmployeeAgeViewModel>(sqlQuery,
            (per, emp) => new EmployeeAgeViewModel()
            {
                FirstName = per.FirstName,
                LastName = per.LastName,
                Gender = emp.Gender == "M" ? Models.Helpers.Enums.Gender.M : Models.Helpers.Enums.Gender.F,
                BirthDate = emp.BirthDate,
                HireDate = emp.HireDate,
                Age = -1 
                //Description: We cannot use query below because it is inside other query. So I am assiging -1 and then after I close 
                //          current query I am doing the second one to get the age.
                //_con.Query<int>("select DATEDIFF(year, GETDATE(), @date)", new { date = emp.BirthDate }).SingleOrDefault()
            },
            splitOn: "EmployeeID")
            .ToList();

        string sqlQueryAge = "select DATEDIFF(year, @date, GETDATE())";
        foreach (var employee in employeesAge)
        {
            employee.Age = (int)_con.ExecuteScalar(sqlQueryAge, new { date = employee.BirthDate });
        }

        return employeesAge;
    }

For now I am doing two queries, but I am wondering if I can do it only using one query or maybe some different way.

Thanks for help!

You're already using the function correctly. The problem is that you try to calculate the difference from a field. This prevents the server from using any indexes that cover that field.

Calculate the cutoff date in your code, eg var cutoff=DateTime.Today.AddYears(-50); and pass the cutoff as a parameter to the query as a parameter, eg :

var cutoff=DateTime.Today.AddYears(-50);

var sqlQuery = @"select Person.BusinessEntityID as PersonID, Person.LastName,
            Person.FirstName,
            Employee.BusinessEntityID as EmployeeID,
            Employee.Gender,
            Employee.BirthDate,
            Employee.HireDate,
            DATEDIFF(YEAR, Employee.BirthDate, GETDATE()) as Age
        FROM Person.Person
            JOIN HumanResources.Employee
            ON Person.BusinessEntityID = Employee.BusinessEntityID
        WHERE Employee.BirthDate <= @cutoff
        ORDER BY Age DESC";

var employeesAge = _con.Query<Person, Employee, EmployeeAgeViewModel>(sqlQuery,
                        new {cutoff},
                       (per, emp) => new EmployeeAgeViewModel()
                        {
                            FirstName = per.FirstName,
                            LastName = per.LastName,
                            Gender = emp.Gender == "M" ? Models.Helpers.Enums.Gender.M : Models.Helpers.Enums.Gender.F,
                            BirthDate = emp.BirthDate,
                            HireDate = emp.HireDate,
                            Age = emp.Age 
                        },
                        splitOn: "EmployeeID")
                        .ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM