LINQ to Entities消息中仅支持无参数构造函数和初始值设定项

时间:2013-06-28 14:54:10

标签: c# linq 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是,所以无法理解它为什么抱怨。

所有建议都表示赞赏。

4 个答案:

答案 0 :(得分:51)

它抱怨的原因是因为它不知道如何将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()返回的数据集的大小,这样您就不会尝试加载整个表进入记忆。

答案 1 :(得分:11)

消息很明确:linq to entities不支持没有无参数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();

答案 2 :(得分:3)

它抱怨,因为它无法将对FundedCount的引用转换为SQL语句。

所有LINQ提供程序都将LINQ语句和表达式转换为其目标可以理解的操作。 LINQ to SQL和LINQ to EF将LINQ转换为SQL,PLINQ将其转换为Tasks和并行操作,LINQ to Sharepoint将其转换为CAML等。

如果他们无法进行转换会发生什么,取决于提供商。某些提供程序将返回中间结果并将查询的其余部分转换为LINQ to Objects查询。其他人只会因错误信息而失败。

与数据库通信时,失败的消息实际上是更好的选择。否则,当实际上只需要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,它将获取数据并创建最终对象

答案 3 :(得分:2)

我在GroupBy中遇到了同样的异常。我发现LINQ to Entities&#34;支持异常&#34;只有无参数构造函数和初始值设定项。不是100%准确的描述。

我在我的&#34; Linq to EntityFramework查询中有一个GroupBy()&#34;它使用struct作为GroupBy中的Key。那没用。当我将该结构更改为普通类时,一切正常。

代码示例

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() {...}