Release notes for re-motion version 1.13.65

List of Issues

Breaking Changes

Improvements

New Features

Details

[RM-2952] DomainObjectCollection.Commit and Rollback have been removed

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


Instead, there is now a single API called ReplaceItemsWithoutNotifications which describes what the operation does, not what it is used for. It should be overridden if a derived collection holds custom state, and the custom state must be recalculated when the API is called. ReplaceItemsWithoutNotifications is called by changed end points when the associated transaction is rolled back.

When the transaction is committed, no API is called any more. The DomainObjectCollection.Commit API was previously called on the original value collection when the transaction was committed, but now the original value collection is no longer retained but instantiated on demand.

[RM-2732] Improve error message given when a delegate is used in an expression where a LambdaExpression is required

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


(no description)

[RM-2707] Automatically remove orderings from sub-statements

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


In SQL, substatements cannot hold ORDER BY clauses. In LINQ, however, subqueries with ordering expressions can easily be constructed:

from o in Orders
from oi in (
  from item in OrderItems
  where item.Order == o
  orderby item.Product
  select item.Description
)
select oi

The problem gets worse because we sometimes construct subqueries even though the user didn't write one, e.g., to handle incompatible result operators, to implement DefaultIfEmpty, etc.

The solution would be to:

  • remove the orderings from subqueries where it doesn't make a difference (Count, Distinct, Contains, Sum, etc.),
  • pull out the orderings from the subqueries to the surrounding query where it does make a difference.

The problem is that pulling out the orderings from the subquery is not generally possible unless the select projection is also changed:

from o in Orders
from oi in (
  from item in OrderItems
  where item.Order == o
  select item.Description
)
orderby item.Product // does not work, item is not known in this query
select oi
from o in Orders
from oi in (
  from item in OrderItems
  where item.Order == o
  select new { item.Description, item.Product }
)
orderby oi.Product // does not work, item is not known in this query
select oi.Description

This is a transformation that requires support for compound projections.

To keep the solution simple, we can pull out orderings only from subqueries we create in result operator handlers and throw an exception for orderings in subqueries the user wrote (unless it is safe to remove or keep them due to Count, Distinct, aggregations, or Top). That would be easier because in the first case, we control all references to the subquery, whereas we'd have to substitute existing references to the subquery in the second case. A full solution requires handling of all subqueries, however.

This issue also affects eager fetching; currently, eager fetching produces fetch query models that cannot be translated to SQL if the original query model contained an OrderByClause.

Conception needed.

[RM-2309] ThrowingExpressionTreeVisitor should automatically reduce unknown extension expressions by default

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


By default, ThrowingExpressionTreeVisitor will throw an exception when an expression is encountered that is not handled by the specific visitor subclass. Until now, this would also happen for reducible expressions.

Reducible expressions are extension expressions whose CanReduce property returns true. When the Reduce method is called on such an expression, it returns another expression with (mostly) equal semantics. For example, a VBCompareExpression would return a BinaryExpression with the same comparison semantics (but missing the VB-specific information).

With this change, ThrowingExpressionVisitors will now automatically reduce such expressions and try to visit the reduced form before throwing an exception, thus taking a second chance on the expression tree being visited.

Since the exception case usually means that the provider cannot handle the expression tree, this change should not break anything, but provide a convenient feature for dealing with reducible extension expressions.

[RM-2301] Support for VB.NET string comparisons

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


VB.NET has a very specific way of dealing with some operators, most notably string comparisons. The method call chain produced for an expression of

From c In Contacts _
Where c.FirstName = "Hugo" _
Select c

is

Contacts
   .Where (c => (Operators.CompareString (c.FirstName, "Hugo", False) == 0))
   .Select (c => c)

Therefore, the WhereClause produced by re-linq contains a Predicate with a MethodCallExpression invoking VisualBasic's CompareString method, whose result is then compared to 0.

A similar behavior occurs with many operators on other data types as well, such as Add or GreaterThan, but for thise, VB.NET does not produce MethodCallExpressions. Instead, annotated BinaryExpressions (with a MethodInfo indicating the operation) are created, so LINQ providers won't even notice the difference.

However, the VB operators do have very specific semantics; for example, VB compares Nothing and "" to equal (C# does not). Some LINQ providers might want to honor these semantics, others might not want to do so. LINQ-to-SQL does honor the semantics in part - if one side of a string comparison is a constant Nothing, it compares to string.Empty instead in the database.

To enable LINQ providers to deal with VB.NET specifics, this feature introduces a new custom expression hierarchy - deriving from a new class VBExpression - and an IVBExpressionVisitor interface. It uses the extension expression approach, which allows VB expressions to be visited by classes implementing IVBExpressionVisitor. The VB expressions are reduced to ordinary BinaryExpressions (with a MethodInfo hinting at the original operator), so LINQ providers without VB support will never need to deal with those expressions (use automatic reduce). LINQ providers with VB support can choose.

The VB transformation is included by default, but it can be removed by the LINQ provider if necessary.