Мне удалось воспроизвести это поведение.Вот еще несколько типов, которые нужно посмотреть в отражателе:
System.Data.Linq.SqlClient.SqlBinder.Visitor
System.Data.Linq.SqlClient.SqlVisitor
На основе этой трассировки стека.
at System.Data.Linq.SqlClient.SqlBinder.Visitor.ConvertToFetchedSequence(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlBinder.Visitor.VisitAlias(SqlAlias a)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSource(SqlSource source)
at ..SqlBinder.Visitor.VisitSelect(SqlSelect select)
at ..SqlVisitor.Visit(SqlNode node)
at ..SqlVisitor.VisitSequence(SqlSelect sel)
at ..SqlVisitor.VisitScalarSubSelect(SqlSubSelect ss)
at ..SqlVisitor.VisitSubSelect(SqlSubSelect ss)
at ..SqlBinder.Visitor.VisitSubSelect(SqlSubSelect ss)
Интересно, почему свойство типа Table<T>
трактуется иначе, чемсвойство типа IQueryable<T>
или даже ITable<T>
.Реализация свойства не имеет значения, тип возвращаемого значения имеет значение.
Свойство типа IQueryable<T>
определенно обрабатывается иначе, чем локальная переменная типа IQueryable<T>
IQueryable<Customer> query1 =
myDC.Customers.Where(c => c.ID == myDC.CoolCustomers.Max(c2 => c2.ID));
IQueryable<Customer> query2 =
myDC.Customers.Where(c => c.ID == myDC.Customers.Where(c2 => c2.Flag).Max(c2 => c2.ID));
IQueryable<Customer> subQuery = myDC.CoolCustomers;
IQueryable<Customer> query3 =
myDC.Customers.Where(c => c.ID == subQuery.Max(c2 => c2.ID));
query1 демонстрирует исходное поведение (исключение, локальные последовательности).
query2 генерирует этот sql - это не идеально.
SELECT [t0].[ID], [t0].[Flag]
FROM [Customer] AS [t0]
OUTER APPLY (
SELECT MAX([t1].[ID]) AS [value]
FROM [Customer] AS [t1]
WHERE [t1].[Flag] = 1
) AS [t2]
WHERE [t0].[ID] = [t2].[value]
query3 слишком охотно выдает подзапрос во время перевода запроса, затем выполняет вторую обратную передачу для основного запроса.