简体   繁体   English

Select 不适用于 IQueryable 但适用于 IList

[英]Select doesn't work on IQueryable but does on IList

I have two lines of code, one is我有两行代码,一个是

AllItems().Where(c => c.Id== id)
          .Select(d => new Quality(d.QualityType)).ToList();

and the other one和另一个

AllItems().Where(c => c.Id== id).ToList()
          .Select(d => new Quality(d.QualityType)).ToList();

The only difference is on the second statement ToList() is called after the Where statement.唯一的区别在于第二条语句ToList()Where语句之后调用。 The second statment works just fine.第二条语句工作得很好。

On the first statement, the default parameterless constructor is hit instead of the constructor with the parameter.在第一条语句中,默认的无参数构造函数被命中,而不是带有参数的构造函数。 so the list is created but the objects in the list are initialized with default values rather than with the d.QualityType.因此创建了列表,但列表中的对象使用默认值而不是 d.QualityType 进行初始化。

you can see the full source of the file in question at (Method: GetBestQualityInHistory)您可以在(方法:GetBestQualityInHistory)查看相关文件的完整来源

https://github.com/kayone/NzbDrone/blob/master/NzbDrone.Core/Providers/HistoryProvider.cs https://github.com/kayone/NzbDrone/blob/master/NzbDrone.Core/Providers/HistoryProvider.cs

**Edit: After further investigation, this seems to be a SubSonic bug, if the Last ToList is replaced by an OrderBy subsonic throws an The construtor 'Void.ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported . **编辑:经过进一步调查,这似乎是一个 SubSonic 错误,如果 Last ToListOrderBy subsonic 替换,则会抛出The construtor 'Void.ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported

If SubSonic works in the same way as Entity framework you cannot use constructors with parameters - you must use parameterless constructors and initializers.如果 SubSonic 以与实体框架相同的方式工作,则不能使用带参数的构造函数 - 您必须使用无参数构造函数和初始化程序。 My very high level explanation of this is that the query is not executed as is - it is translated to SQL and because of that you must use property initializers so that expression tree knows which properties in the projected type should be filled by values.我对此的高级解释是查询没有按原样执行 - 它被转换为 SQL 并且因此您必须使用属性初始化程序,以便表达式树知道投影类型中的哪些属性应该由值填充。 When using constructor with parameters, expression tree doesn't know where the passed parameter belongs to (it doesn't check content of the constructor).当使用带参数的构造函数时,表达式树不知道传递的参数属于哪里(它不检查构造函数的内容)。 The real constructor (parameterless) is called once you execute Tolist and result set is materialized into QuantityType instances.一旦您执行Tolist并将结果集具体化为QuantityType实例,就会调用真正的构造函数(无参数)。

This isn't really an answer, and I was going to make it a comment, but needed more room for code snippet.这不是一个真正的答案,我打算将其作为评论,但需要更多的代码片段空间。

Judging by the SubSonic code, I'm pretty sure that in some cases where you get the "constructor not supported" errors, SS is for some reason trying to parse your new...() statement into SQL.从 SubSonic 代码来看,我很确定在某些情况下你得到“不支持构造函数”错误,SS 出于某种原因试图将你的new...()语句解析为 SQL。 The offending method is part of the SQL Formatter, and looks like it only handles DateTime:违规方法是 SQL 格式化程序的一部分,看起来它只处理 DateTime:

    protected override NewExpression VisitNew(NewExpression nex)
    {
        if (nex.Constructor.DeclaringType == typeof(DateTime))
        {
            // ...omitted for brevity...
        }
        throw new NotSupportedException(string.Format("The construtor '{0}' is not supported", nex.Constructor));
    }

I think that would normally be hit if you did something like:我认为如果您执行以下操作通常会受到影响:

someData.Where(data => data.CreatedDate <= new DateTime(2011, 12, 01)).Select(data => data) someData.Where(data => data.CreatedDate <= new DateTime(2011, 12, 01)).Select(data => data)

Then that newDateTime would be translated to SQL.然后该newDateTime将被转换为 SQL。 So however you change the Linq to get that exception, I think that is what is happening.因此,无论您更改 Linq 以获得该异常,我认为这就是正在发生的事情。 I assume this is because if you add an .OrderBy() after the .Select() then you are no longer calling the OrderBy on the IQueryable of whatever AllItems() returns, but instead trying to order by what is returned by the.Select(), which is the enumerable of new Quality obejcts, so SS probably tries to turn all that into SQL.我认为这是因为如果您在.Select()之后添加.OrderBy() ,那么您将不再在 AllItems() 返回的任何 IQueryable 上调用 OrderBy ,而是尝试按 .Select 返回的内容进行排序(),这是新质量对象的可枚举,所以 SS 可能试图将所有这些都变成 SQL。

I'm wondering if it would work right if you reversed it?我想知道如果你反转它是否会正常工作?

AllItems().Where(c => c.Id== id)
      .OrderBy(d => d.QualityType)
      .Select(d => new Quality(d.QualityType));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM