LINQ to Entities消息中只支持无参数构造函数和初始化器
本文关键字:构造函数 参数 初始化 支持 Entities to 消息 LINQ | 更新日期: 2023-09-27 18:20:13
我有一个从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的前身,MatchHistory是,所以不明白它为什么抱怨。
感谢所有的建议。
它抱怨的原因是它不知道如何将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()
返回的数据集的大小,这样就不会试图将整个表加载到内存中。
消息很清楚:linq-to实体不支持没有无参数ctor的对象。
所以
解决方案1
在之前枚举(或者使用中间匿名类型并在该类型上枚举)
.ToList()
.Select(x => new FundedCount(
x.Key.BuyerId,
x.Count() / 30 * daysInMonth))
.ToList();
解决方案2
在FundedCount类中添加一个无参数的ctor(如果可能的话)
public FundedCount() {}
并使用
.Select(x => new FundedCount{
<Property1> = x.Key.BuyerId,
<Property2> = x.Count() / 30 * daysInMonth
})
.ToList();
它抱怨,因为它无法将对FundedCount的引用转换为SQL语句。
所有LINQ提供程序都将LINQ语句和表达式转换为目标可以理解的操作。LINQ to SQL和LINQ to EF将把LINQ转换成SQL,PLINQ将把它转换成任务和并行操作,LINQ to Sharepoint将它转换成CAML等。
如果他们不能进行转换,会发生什么,取决于提供者。一些提供程序将返回中间结果,并将查询的其余部分转换为LINQ到对象查询。其他操作将简单地失败并显示错误消息。
在与数据库交谈时,处理消息失败实际上是一个更好的选择。否则,当实际只需要1或2时,服务器将不得不将所有列返回给客户端。
在你的情况下,你应该修改你的选择,以返回一个带有你想要的数据的匿名类型,调用ToList(),然后创建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,它将获得数据并创建最终对象
我在GroupBy中遇到了同样的异常。我发现异常"LINQ to Entities中只支持无参数构造函数和初始化器"并不是100%准确的描述。
我在"Linq-to-EntityFramework查询"中有一个GroupBy(),它在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() {...}