Entity Framework: невозможно вызвать .OrderBy для вычисляемого поля IQueryable - PullRequest
0 голосов
/ 23 февраля 2020

В настоящее время я пытаюсь выяснить, как можно упорядочить запрос по полю, в котором есть только геттер. У меня IQueryable строится следующим образом:

var referrals = db.Referrals
                        .Include(x => x.Doctor)
                        .Include(x => x.OfficeLocation)
                        .Where(x => (vm.OfficeLocationSelection == -1 ? true : x.OfficeLocationId == vm.OfficeLocationSelection) &&
                        string.IsNullOrEmpty(vm.SearchTerm) ? true : x.Doctor.Name.ToLower().Contains(vm.SearchTerm.ToLower()))
                        .GroupBy(x => x.Doctor)
                        .Select(x => new ReferralGridRowViewModel
                        {
                            DoctorName = x.Key.Name,
                            January = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 1 && y.Date.Year == DateTime.Now.Year).Count(),
                            February = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 2 && y.Date.Year == DateTime.Now.Year).Count(),
                            March = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 3 && y.Date.Year == DateTime.Now.Year).Count(),
                            April = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 4 && y.Date.Year == DateTime.Now.Year).Count(),
                            May = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 5 && y.Date.Year == DateTime.Now.Year).Count(),
                            June = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 6 && y.Date.Year == DateTime.Now.Year).Count(),
                            July = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 7 && y.Date.Year == DateTime.Now.Year).Count(),
                            August = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 8 && y.Date.Year == DateTime.Now.Year).Count(),
                            September = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 9 && y.Date.Year == DateTime.Now.Year).Count(),
                            October = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 10 && y.Date.Year == DateTime.Now.Year).Count(),
                            November = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 11 && y.Date.Year == DateTime.Now.Year).Count(),
                            December = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 12 && y.Date.Year == DateTime.Now.Year).Count()
                        });

и ReferralGridRowViewModel выглядит следующим образом (обратите внимание на свойство YearToDate):

public class ReferralGridRowViewModel
    {
        public string DoctorName { get; set; }

        public int January { get; set; }

        public int February { get; set; }

        public int March { get; set; }

        public int April { get; set; }

        public int May { get; set; }

        public int June { get; set; }

        public int July { get; set; }

        public int August { get; set; }

        public int September { get; set; }

        public int October { get; set; }

        public int November { get; set; }

        public int December { get; set; }

        public int YearToDate {
            get {
                return (January + February + March + April + May + June + July + August + September + October + November + December);
            }
        }
    }

, когда я пытаюсь вызвать следующее:

referrals = referrals.OrderByDescending(x => x.YearToDate);

, затем я получаю следующее исключение:

Указанный тип члена YearToDate не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, элементы сущностей и свойства навигации сущностей.

, когда запрос фактически выполняется в этой строке:

referralRows = referrals.Skip(vm.Skip).Take(vm.PageSize).ToList();

Как я могу преодолеть это в качественной манере? Я бы предпочел не добавлять столбец в базу данных для YearToDate, поскольку он был бы избыточен, и я не могу .ToList все заранее, а затем отсортировать, так как в базе данных есть миллионы записей, и это будет существенным ударом по производительности

Ответы [ 2 ]

0 голосов
/ 23 февраля 2020

Я смог отсортировать по YearToDate записям, проверив группировку по названию доктора и году, прежде чем выбрать фактический ReferralGridRowViewModel следующим образом:

                    var referralsGrouping = db.Referrals
                        .Include(x => x.Doctor)
                        .Include(x => x.OfficeLocation)
                        .Where(x => (vm.OfficeLocationSelection == -1 ? true : x.OfficeLocationId == vm.OfficeLocationSelection) &&
                        string.IsNullOrEmpty(vm.SearchTerm) ? true : x.Doctor.Name.ToLower().Contains(vm.SearchTerm.ToLower()))
                        .GroupBy(x => x.Doctor);

                    if (!string.IsNullOrEmpty(vm.SortColumn))
                    {
                        if (vm.SortColumn == "YearToDate")
                        {
                            if (vm.SortDirection == SortDirectionType.Descending)
                            {
                                referralsGrouping = referralsGrouping.OrderByDescending(x => x.Count(y => y.DoctorId == x.Key.Id && y.Date.Year == DateTime.Now.Year));
                            }
                            else
                            {
                                referralsGrouping = referralsGrouping.OrderBy(x => x.Count(y => y.DoctorId == x.Key.Id && y.Date.Year == DateTime.Now.Year));
                            }
                        }
                    }

                    var referrals = referralsGrouping
                    .Select(x => new ReferralGridRowViewModel
                    {
                        DoctorName = x.Key.Name,
                        January = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 1 && y.Date.Year == DateTime.Now.Year).Count(),
                        February = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 2 && y.Date.Year == DateTime.Now.Year).Count(),
                        March = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 3 && y.Date.Year == DateTime.Now.Year).Count(),
                        April = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 4 && y.Date.Year == DateTime.Now.Year).Count(),
                        May = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 5 && y.Date.Year == DateTime.Now.Year).Count(),
                        June = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 6 && y.Date.Year == DateTime.Now.Year).Count(),
                        July = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 7 && y.Date.Year == DateTime.Now.Year).Count(),
                        August = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 8 && y.Date.Year == DateTime.Now.Year).Count(),
                        September = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 9 && y.Date.Year == DateTime.Now.Year).Count(),
                        October = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 10 && y.Date.Year == DateTime.Now.Year).Count(),
                        November = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 11 && y.Date.Year == DateTime.Now.Year).Count(),
                        December = x.Where(y => y.DoctorId == x.Key.Id && y.Date.Month == 12 && y.Date.Year == DateTime.Now.Year).Count()
                    });

                if (!string.IsNullOrEmpty(vm.SortColumn))
                {
                    if (vm.SortColumn == "DoctorName")
                    {
                        if (vm.SortDirection == SortDirectionType.Descending)
                        {
                            referrals = referrals.OrderByDescending(x => x.DoctorName);
                        }
                        else
                        {
                            referrals = referrals.OrderBy(x => x.DoctorName);
                        }
                    }
                    //other vm sort columns
                }
0 голосов
/ 23 февраля 2020

Вы можете просто добавить атрибут [NotMapped]:

using System.ComponentModel.DataAnnotations.Schema;
...

public class ReferralGridRowViewModel
{
    ...

    [NotMapped]
    public int YearToDate {
    get {
      return (January + February + March + April + May + June + July + August + September + October + November + December);
    }
  }
}

Это указывает на EF игнорировать свойство на стороне БД. См. Документы:
https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.schema.notmappedattribute?view=netframework-4.8

...