Select doesn't work on IQueryable, but does on IList

I have two lines of code, one -

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

and the other

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

The only difference from the second ToList() statement is called after the Where statement. The second status works just fine.

In the first expression, instead of a constructor with a parameter, a constructor without parameters falls instead of a constructor. therefore, the list is created, but the objects in the list are initialized with default values, and not with d.QualityType.

you can see the full source of the file in question (Method: GetBestQualityInHistory)

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

** Editing: after further investigation, this seems to be a SubSonic error, if Last ToList is replaced with OrderBy subsonic, it The construtor 'Void .ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported a The construtor 'Void .ctor(NzbDrone.Core.Repository.Quality.QualityTypes, Boolean)' is not supported .

+4
source share
2 answers

If SubSonic works in the same way as the Entity structure, you cannot use constructors with parameters - you must use gapless constructors and initializers. My very high explanation for this is that the query is not executed as it is - it is translated into SQL and because of this you have to use property initializers so that the expression tree knows which properties in the projected type should be filled with values. When using a constructor with parameters, the expression tree does not know to which the passed parameter belongs (it does not check the contents of the constructor). The real constructor (without parameters) is called as soon as you execute the Tolist , and the result is set to QuantityType instances.

+4
source

This is actually not the answer, and I'm going to make it a comment, but you need more space for the code snippet.

Judging by the SubSonic code, I'm sure that in some cases when you get errors that are not supported by the constructor, SS for some reason tries to parse your new ...() statement in SQL. The insult method is part of the SQL Formatter and looks like it is processing a 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 this is normal if you did something like:

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

Then newDateTime will be translated into SQL. Therefore, however, you change Linq to get this exception, I think this is what happens. I assume this is because if you added .OrderBy() after .Select() , then you no longer call OrderBy in IQueryable from the fact that AllItems () is returned, but instead try to arrange what is returned. Select (), which is enumerated for new qualities, so SS is probably trying to turn all this into SQL.

I am wondering if this will work correctly if you cancel it?

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

All Articles