В сообщении 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, поэтому не может понять, почему он жалуется.
Все советы были оценены.
Ответы
Ответ 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() {...}