Example:
from p in DB.Products
group p by p.CategoryID
into g
select new
{
CategoryID = g.Key,
CheapestProducts =
from p2 in g
where p2.UnitPrice == g.Min (p3 => p3.UnitPrice)
select p2
};
The problem is that the expression holding the sub-query gets an expression type of IQueryable<Product>, where IEnumerable<Product> was assumed.
There are several possibilities to solving this bug; the simplest one would probably be to allow SubQueryExpression to take a specific type in its ctor (which must be assignable from the queryModel's data type).
System.InvalidOperationException : The binary operator Equal is not defined for the types 'System.Int32' and 'System.Nullable`1[System.Int32]'.
In SqlContextExpressionVisitor.VisitBinaryExpression and SelGeneratingExpressionVisitor.VisitJoinConditionExpression.
Previously, the type of a QueryModel (GetResultType(), GetOutputDataInfo(), used primarily for the type of SubQueryExpressions) was always calculated from its SelectClause and its result operators. This, however, could cause problems when a sub-query was expected to have a certain type in the expression tree.
Therefore, QueryModel now has a ResultTypeOverride property that can optionally be set to override the calculated type in GetResultType() and GetOutputDataInfo(). The expression node parsers have been changed to automatically set that override. This may cause QueryModels and SubQueryExpressions to have different types than before.
For users of the re-linq front-end, this is only relevant in three cases:
This affects the transformers for string.StartsWith, string.EndsWith, and string.Contains. These currently do not allow non-constant parameters.
With this feature, they will support non-constant values (eg., properties mapped to columns), and emit SQL of something like the following:
... LIKE REPLACE (REPLACE (REPLACE (REPLACE (REPLACE([column], '\', '\\'), '%', '\%'), '_', '\_'), '[', '\['), ']', '\]') ESCAPE '\'
The host of REPLACE statements is - unfortunately - required because the column might contain a reserved character.
SQL does not allow grouping on constants. Apparently, there is at least one popular control library out there that issues GROUP BY statements that group on constants, so we should really support such statements:
Cooks.GroupBy (c => 0).Select (c => c.Key)
This can be solved by transforming the constant into a substatement selecting just that constant and allowing GroupBy on substatements, which is a sensible feature anyway:
Cooks.GroupBy (c => c.Assistants.Count()).Select (c => new { AssistantCount = c.Key, CookCount = c.Count() })
SQL doesn't allow substatements to occur in GroupBy clauses, they need to be moved to the FROM clause.