31

我有一个从 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 是,所以无法理解它为什么抱怨。

所有建议表示赞赏。

4

4 回答 4

55

它抱怨的原因是因为它不知道如何将您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()尽可能地限制返回的数据集的大小,以免您尝试将整个表加载到内存中。

于 2013-06-28T15:12:02.980 回答
12

消息很清楚:linq to entity 不支持没有无参数 ctor 的对象。

所以

解决方案1

枚举之前(或使用中间匿名类型并枚举那个)

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

解决方案2

将无参数 ctor 添加到 FundedCount 类(如果可能的话)

public FundedCount() {}

并使用

.Select(x => new FundedCount{
                        <Property1> = x.Key.BuyerId,
                        <Property2> = x.Count() / 30 * daysInMonth
                         })
                    .ToList();
于 2013-06-28T15:28:21.587 回答
3

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

所有 LINQ 提供程序都将 LINQ 语句和表达式转换为其目标可以理解的操作。LINQ to SQL 和 LINQ to EF 将 LINQ 转换为 SQL,PLINQ 将其转换为任务和并行操作,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 并将获取数据并创建最终对象

于 2013-06-28T15:15:07.680 回答
3

我在 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() {...}
于 2014-03-20T09:57:42.457 回答