ElenaRez Ответов: 1

Проблема с получением атрибута, которого нет в запросе groupby, в выбранную часть запроса linq


Привет. Я реализации asp.net ядро 3.1 проекта. У меня есть запрос, результатом которого является поиск среднего значения различий между двумя датами, сгруппированными по годам и месяцам, как в следующем запросе. Моя проблема заключается в том, что после запуска моего проекта возникает ошибка для тех атрибутов, которые я использовал в своей выбранной части запроса, в то время как они не были использованы в groupby.

Ошибка заключается в следующем:

.FirstOrDefault()' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information


Что я уже пробовал:

var groupedDate =     (from t1 in _context.Apiapp
                                   join t2 in _context.ApiAppHistory on t1.Id         equals t2.ApiAppId
                                   join t3 in _context.EntityType on t2.LastReqStatus equals t3.Id
                                   where t1.IsDeleted == false && t1.LastRequestStatus == t2.Id && t3.Name == "granted"
                                   group new { t1, t2 }
                                   by new { Year = t1.ApiRequestDate.Substring(0, 4), Month = t1.ApiRequestDate.Substring(5, 2), LastReqStatus = t2.LastReqStatus } into g

                                   select new
                                   {
  diff=GetPersianDaysDiffDate(g.FirstOrDefault().t1.ApiRequestDate, g.FirstOrDefault().t2.Date),
                                       Year = g.Key.Year,
                                       Month = g.Key.Month,
                                       GrantedCount = g.Count()

                                   }).ToList();

            var avgDateDiff = groupedDate
                      .GroupBy(x => new { x.Year, x.Month })
                      .Select(x => new { Year = x.Key.Year, Month = x.Key.Month, Avg = x.Average(y => y.diff) })
                      .ToList();


public int GetPersianDaysDiffDate(string Date1, string Date2)
        {
            int year1 = Convert.ToInt16(Date1.Substring(0, 4));
            int month1 = Convert.ToInt16(Date1.Substring(5, 2));
            int day1 = Convert.ToInt16(Date1.Substring(8, 2));

            int year2 = Convert.ToInt16(Date2.Substring(0, 4));
            int month2 = Convert.ToInt16(Date2.Substring(5, 2));
            int day2 = Convert.ToInt16(Date2.Substring(8, 2));

            System.Globalization.PersianCalendar calendar = new System.Globalization.PersianCalendar();
            DateTime dt1 = calendar.ToDateTime(year1, month1, day1, 0, 0, 0, 0);
            DateTime dt2 = calendar.ToDateTime(year2, month2, day2, 0, 0, 0, 0);
            TimeSpan ts = dt2.Subtract(dt1);

            return ts.Days;
        }
        //string Date1 = "1398/01/01";
        //string Date2 = "1398/01/05";

        //int Diff = GetPersianDaysDiffDate(Date1, Date2);

1 Ответов

Рейтинг:
2

Richard Deeming

Я не удивлен, что Entity Framework не знает, как преобразовать это в SQL-запрос! Помимо того, что GetPersianDaysDiffDate функция, вероятно, не сопоставлена с функцией SQL, неясно, какие даты в группе вы хотите сравнить.

Например, если у вас есть пять записей, сгруппированных в январе 2020 года, из какой единственной записи вы собираетесь взять даты? Вы еще не указали OrderBy на FirstOrDefault запрос, так что нет никакого способа узнать.

Возможно, что-то вроде этого может сработать:

var query = from t1 in _context.Apiapp
            join t2 in _context.ApiAppHistory on t1.Id equals t2.ApiAppId
            join t3 in _context.EntityType on t2.LastReqStatus equals t3.Id
            where t1.IsDeleted == false && t1.LastRequestStatus == t2.Id && t3.Name == "granted"
            let tg = new
            {
                Year = t1.ApiRequestDate.Substring(0, 4), 
                Month = t1.ApiRequestDate.Substring(5, 2), 
                t2.LastReqStatus,
                t1.ApiRequestDate,
                t2.Date
            }
            group tg by new { tg.Year, tg.Month, tg.LastReqStatus } into g
            select new
            {
                g.Key.Year,
                g.Key.Month,
                ApiRequestDate = g.Min(i => i.ApiRequestDate),
                Date = g.Max(i => i.Date)
            };

var avgDateDiff = query.AsEnumerable()
    .GroupBy(x => new { x.Year, x.Month }, (key, g) => new
    {
        key.Year,
        key.Month,
        Avg = g.Average(y => GetPersianDaysDiffDate(y.ApiRequestDate, y.Date))
    })
    .ToList();