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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17367649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:19:35  来源:igfitidea点击:

Only parameterless constructors and initializers are supported in LINQ to Entities message

c#linqlinq-to-entities

提问by dotnetnoob

I have a method that returns data from an EF model.

我有一个从 EF 模型返回数据的方法。

I'm getting the above message, but I can't wotk our how to circumvent the problem.

我收到了上面的消息,但我不知道如何规避这个问题。

    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 is not an EF enity, MatchHistory is, so can't understand why it is complaining.

FundedCount 不是 EF 实体,MatchHistory 是,所以无法理解它为什么抱怨。

All advice appreciated.

所有建议表示赞赏。

采纳答案by Yuck

The reason it is complaining is because it doesn't know how to translate your Select()into a SQL expression. If you need to do a data transformation to a POCO that is notan entity, you should first get the relevant data from EF and then transform it to the POCO.

它抱怨的原因是它不知道如何将您的Select()转换为 SQL 表达式。如果需要对不是实体的POCO进行数据转换,应该先从EF获取相关数据,然后再转换到POCO。

In your case it should be as simple as calling ToList()earlier:

在您的情况下,它应该像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));

Be careful with this, though, and make sure that you're limiting the size of the data set returned by ToList()as much as possible so that you're not trying to load an entire table into memory.

但是要小心,并确保ToList()尽可能地限制返回的数据集的大小,这样您就不会试图将整个表加载到内存中。

回答by Panagiotis Kanavos

It's complaining because it can't convert references to FundedCount to SQL statements.

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

All LINQ providers convert LINQ statements and expressions to operations that their target can understand. LINQ to SQL and LINQ to EF will convert LINQ to SQL, PLINQ will convert it to Tasks and parallel operations, LINQ to Sharepoint will convert it to CAML etc.

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

What happens if they can't do the conversion, depends on the provider. Some providers will return intermediate results and convert the rest of the query to a LINQ to Objects query. Others will simply fail with an error message.

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

Failing with a message is actually a better option when talking to a database. Otherwise the server would have to return all columns to the client when only 1 or 2 would be actually necessary.

在与数据库交谈时,通过消息失败实际上是一个更好的选择。否则,当实际只需要 1 或 2 列时,服务器将不得不将所有列返回给客户端。

In your case you should modify your select to return an anonymous type with the data you want, call ToList() and THEN create the FundedCount objects, eg:

在您的情况下,您应该修改您的选择以使用您想要的数据返回匿名类型,调用 ToList() 然后创建 FundedCount 对象,例如:

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

The first ToList() will force the generation of the SQL statement and execute the query that will return only the data you need. The rest of the query is actually Linq to Objects and will get the data and create the final objects

第一个 ToList() 将强制生成 SQL 语句并执行仅返回您需要的数据的查询。查询的其余部分实际上是 Linq to Objects 并将获取数据并创建最终对象

回答by Rapha?l Althaus

Message is clear : linq to entities doesn't support objects without a parameterless ctor.

消息很明确:linq to entity 不支持没有无参数构造函数的对象。

So

所以

Solution1

解决方案1

enumerate before (or use an intermediate anonymous type and enumerate on that one)

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

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

Solution2

解决方案2

add a parameterless ctor to your FundedCount class (if it's possible)

向您的 FundedCount 类添加一个无参数的构造函数(如果可能)

public FundedCount() {}

and use

并使用

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

回答by David Votrubec

I had the same exception in GroupBy. I found that the exception "Only parameterless constructors and initializers are supported in LINQ to Entities" is not 100% accurate description.

我在 GroupBy 中有同样的例外。我发现异常“LINQ to Entities 中仅支持无参数构造函数和初始值设定项”并不是 100% 准确的描述。

I had a GroupBy() in my "Linq to EntityFramework query" which used a struct as a Key in GroupBy. That did not work. When I changed that struct to normal class everything worked fine.

我的“Linq to EntityFramework 查询”中有一个 GroupBy(),它使用结构作为 GroupBy 中的键。那没有用。当我将该结构更改为普通类时,一切正常。

Code sample

代码示例

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