Select不适用于IQueryable,但适用于IList

时间:2011-06-05 19:26:52

标签: c# .net linq subsonic subsonic-simplerepository

我有两行代码,一行是

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

和另一个

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

唯一的区别是在ToList()语句之后调用第二个语句Where。第二个法规工作正常。

在第一个语句中,使用参数命中默认的无参数构造函数而不是构造函数。所以列表已创建,但列表中的对象使用默认值而不是d.QualityType初始化。

您可以在(方法:GetBestQualityInHistory)中查看相关文件的完整来源

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

**编辑:经过进一步调查后,这似乎是一个SubSonic错误,如果上一个ToListOrderBy亚音速投掷取代The construtor 'Void .ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported

2 个答案:

答案 0 :(得分:4)

如果SubSonic以与Entity框架相同的方式工作,则不能使用带参数的构造函数 - 您必须使用无参数构造函数和初始化器。我对此的高级解释是查询不是按原样执行 - 它被转换为SQL,因此必须使用属性初始值设定项,以便表达式树知道应该用值填充投影类型中的哪些属性。当使用带有参数的构造函数时,表达式树不知道传递的参数所属的位置(它不检查构造函数的内容)。执行Tolist后,将调用真实构造函数(无参数),并将结果集实现为QuantityType个实例。

答案 1 :(得分:0)

这不是一个真正的答案,我打算将其作为评论,但需要更多的代码片段空间。

根据SubSonic代码判断,我很确定在某些情况下你会得到“不支持构造函数”的错误,SS出于某种原因试图将你的new ...()语句解析为SQL。有问题的方法是SQL Formatter的一部分,看起来它只处理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));
    }

我认为,如果你做了类似的事情,那通常就会受到影响:

someData         .Where(data => data.CreatedDate< = new DateTime(2011,12,01))         。选择(数据=>数据)

然后将newDateTime转换为SQL。 因此,无论你改变Linq以获得该异常,我认为这就是正在发生的事情。 我假设这是因为如果你在.OrderBy() 之后添加.Select() ,那么你不再调用任何AllItems()返回的IQueryable上的OrderBy,而是试图通过.Select()返回的内容排序,这是新的Quality obejcts的可枚举,因此SS可能会尝试将所有内容转换为SQL。

我想知道如果你扭转它是否会正常工作?

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