Подтвердить что ты не робот

В сообщении LINQ to Entities поддерживаются только конструкторы и инициализаторы без параметров

У меня есть метод, который возвращает данные из EF-модели.

Я получаю сообщение выше, но я не могу понять, как обойти эту проблему.

    public static IEnumerable<FundedCount> GetFundedCount()
    {
        var today = DateTime.Now;
        var daysInMonth = DateTime.DaysInMonth(today.Year, today.Month);

        var day1 = DateTime.Now.AddDays(-1);
        var day31 = DateTime.Now.AddDays(-31);

        using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
        {
            var r = new Repository<MatchHistory>(uow.Context);

            return r.Find()
                .Where(x =>
                    x.AppliedOn >= day1 && x.AppliedOn <= day31 &&
                    x.ResultTypeId == (int)MatchResultType.Accepted)
                .GroupBy(x => new { x.BuyerId, x.AppliedOn })
                .Select(x => new FundedCount(
                    x.Key.BuyerId,
                    x.Count() / 30 * daysInMonth))
                .ToList();
        }
    }

FundedCount не является EF enity, MatchHistory, поэтому не может понять, почему он жалуется.

Все советы были оценены.

4b9b3361

Ответ 1

Причина, по которой она жалуется, заключается в том, что она не знает, как перевести ваш Select() в выражение SQL. Если вам нужно сделать преобразование данных в POCO, что не объект, вы должны сначала получить соответствующие данные из EF, а затем преобразовать его в POCO.

В вашем случае это должно быть так же просто, как вызвать ToList() раньше:

return r.Find()
        .Where(x => x.AppliedOn >= day1 && x.AppliedOn <= day31 &&
                    x.ResultTypeId == (int)MatchResultType.Accepted)
        .GroupBy(x => new { x.BuyerId, x.AppliedOn })
        .ToList() // this causes the query to execute
        .Select(x => new FundedCount(x.Key.BuyerId, x.Count() / 30 * daysInMonth));

Будьте осторожны с этим и убедитесь, что вы максимально ограничены размером набора данных, возвращаемого ToList(), чтобы не пытаться загрузить всю таблицу в память.

Ответ 2

Сообщение ясно: linq для объектов не поддерживает объекты без без параметров ctor.

Итак,

Решение1

перечислить до (или использовать промежуточный анонимный тип и перечислить на нем)

.ToList()
.Select(x => new FundedCount(
                    x.Key.BuyerId,
                    x.Count() / 30 * daysInMonth))
                .ToList();

Solution2

добавьте без параметров ctor в свой класс FundedCount (если это возможно)

public FundedCount() {}

и используйте

.Select(x => new FundedCount{
                        <Property1> = x.Key.BuyerId,
                        <Property2> = x.Count() / 30 * daysInMonth
                         })
                    .ToList();

Ответ 3

Он жалуется, потому что не может преобразовать ссылки на заявки FundedCount на SQL.

Все поставщики LINQ преобразуют операторы и выражения LINQ в операции, которые может понять их цель. LINQ to SQL и LINQ to EF преобразуют LINQ в SQL, PLINQ преобразует его в задачи и параллельные операции, LINQ to Sharepoint преобразует его в CAML и т.д.

Что произойдет, если они не смогут выполнить преобразование, зависит от поставщика. Некоторые поставщики возвратят промежуточные результаты и преобразуют остальную часть запроса в запрос LINQ to Objects. Другие просто выходят из строя с сообщением об ошибке.

Неудача с сообщением на самом деле является лучшим вариантом при разговоре с базой данных. В противном случае серверу пришлось бы возвращать все столбцы клиенту, когда на самом деле было бы нужно только 1 или 2.

В вашем случае вы должны изменить свой выбор, чтобы вернуть анонимный тип с нужными данными, вызвать ToList() и THEN создать объекты FundedCount, например:

.Select( x=> new {Id=x.Key.BuyerId,Count=x.Count()/30 * daysInMonth)
.ToList()
.Select(y => new FundedCount(y.Id,y.Count))
.ToList();

Первый ToList() заставит генерировать инструкцию SQL и выполнить запрос, который будет возвращать только нужные вам данные. Остальная часть запроса на самом деле является Linq to Objects и будет получать данные и создавать конечные объекты

Ответ 4

У меня было такое же исключение в GroupBy. Я обнаружил, что исключение "Только без параметров конструкторы и инициализаторы поддерживаются в LINQ to Entities" не является точным описанием на 100%.

У меня был GroupBy() в моем "Linq to EntityFramework query", который использовал структуру как ключ в GroupBy. Это не сработало. Когда я изменил эту структуру на обычный класс, все сработало нормально.

Пример кода

var affectedRegistrationsGrouped = await db.Registrations
  .Include(r => r.Person)
  .Where(r =>
      //whatever
  )
  .GroupBy(r => new GroupByKey
  {
      EventId = r.EventId, 
      SportId = r.SportId.Value
  })
 .ToListAsync();

...
...
// this does not work
private struct GroupByKey() {...}

// this works fine
private class GroupByKey() {...}