Release notes for re-motion version 1.13.76

List of Issues

Bugfixes

Breaking Changes

New Features

Details

[RM-3207] When a NewExpression contains a subquery whose original type is IEnumerable<T>, an ArgumentException (wrapped into a TargetInvocationException) is thrown

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


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).

[RM-3198] SQL Backend: InvalidOperationException is thrown when a comparison or join condition involves a nullable and a non-nullable expression

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


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.

[RM-3323] The method call expression node parsers now cause the generated QueryModel to have a result type defined by the MethodCallExpressions

Component/s: Data.Linq
Issue Type: Breaking Change
Resolution: Fixed
Status: Closed


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:

  • If they previously depended on QueryModel.GetResultType() or GetOutputDataInfo(), or the type of SubQueryExpressions, they should be aware that this type might now be different (eg., IEnumerable<T> or SpecificQueryable<T> instead of IQueryable<T>).
  • If they change QueryModels that result from the node parsers, they should make sure that they reset the ResultTypeOverride to null if they change the SelectClause or any result operator in such a way that the ResultTypeOverride doesn't match any longer. Otherwise, if the ResultTypeOverride doesn't fit to the calculated type, an exception will be thrown the first time the query model's type is accessed.
  • If they manually create QueryModels, they can (but do not have to) use the ResultTypeOverride to adjust the result type of the QueryModel.

[RM-3074] SQL Backend: Support methods translated to LIKE with non-constant values

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


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.

[RM-3065] SQL Backend: Support for GroupBy where the keyExpression is a constant or a subquery

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


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.