Я делаю приложение, которое проверяет выбранные 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
zari 7 Мар 2019 в 17:48

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();
1
Panagiotis Kanavos 7 Мар 2019 в 15:01