如何在Dapper中使用SQL函数?

时间:2019-03-07 14:48:12

标签: c# tsql orm dapper

我正在做一个基准测试选定的ORM(EF,NHibernate,Dapper)的应用程序。我正在.NET Core 2.0中进行开发,并且正在使用AdventureWorks数据库。我的查询有一个问题,该查询返回年龄超过50岁的所有雇员。我不知道如何使用SQL函数DateDiff,或者我需要一些其他方法来通过SQL进行此操作。这是我的DapperRepository类中的代码段:

  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;
    }

目前,我正在执行两个查询,但我想知道是否只能使用一个查询或某些不同的方式来完成它。

感谢帮助!

1 个答案:

答案 0 :(得分:1)

您已经正确使用了该功能。问题是您尝试计算字段的差异。这样可以防止服务器使用覆盖该字段的任何索引。

计算代码中的截止日期,例如var cutoff=DateTime.Today.AddYears(-50);,并将截止日期作为参数传递给查询作为参数,例如:

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();