Efcore: [2.2] [SQLCE] Failing query test

Created on 27 Oct 2018  路  3Comments  路  Source: dotnet/efcore

Test fail - wonder what I am doing wrong? TypeMapping?

Test 'Microsoft.EntityFrameworkCore.Query.SimpleQuerySqlCeTest.Average_over_nested_subquery_is_client_eval(isAsync: True)' failed:
    System.InvalidOperationException : An exception occurred while reading a database value. The expected type was 'System.Double' but the actual value was of type 'System.Decimal'.
---- System.InvalidCastException : Specified cast is not valid.
    at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.ThrowReadValueException[TValue](Exception exception, Object value, IPropertyBase property)
    at lambda_method(Closure , DbDataReader )
    at Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.<BufferlessMoveNext>d__12.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.<MoveNext>d__11.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.AsyncQueryMethodProvider.ParameterInjector`1.InjectParametersEnumerator.<MoveNext>d__4.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.AsyncSelectEnumerable`2.AsyncSelectEnumerator.<MoveNext>d__3.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Linq.AsyncEnumerable.<Average_>d__76.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.TaskLiftingExpressionVisitor.<_ExecuteAsync>d__8`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.AsyncSelectEnumerable`2.AsyncSelectEnumerator.<MoveNext>d__3.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Linq.AsyncEnumerable.<Average_>d__80.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.TaskResultAsyncEnumerable`1.Enumerator.<MoveNext>d__3.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.<MoveNext>d__5.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<ExecuteSingletonAsyncQuery>d__21`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.EntityFrameworkCore.TestUtilities.QueryAsserter`1.<AssertAverage>d__82`2.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ----- Inner Stack Trace -----
    at System.Data.SqlServerCe.SqlCeDataReader.GetDouble(Int32 ordinal)
    at lambda_method(Closure , DbDataReader )

Further technical details

EF Core version: 2.2-preview3
Database Provider: SQL Compact

closed-external customer-reported

Most helpful comment

Query plan for CE:

(QueryContext queryContext) => IEnumerable<decimal> _InterceptExceptions(
|__ source: IEnumerable<decimal> _ToSequence(() => decimal Average(IEnumerable<decimal> _ShapedQuery(
|   |__ queryContext: queryContext, 
|   |__ shaperCommandContext: SelectExpression: 
|   |       SELECT TOP(@__p_0) [c].[CustomerID]
|   |       FROM [Customers] AS [c]
|   |       ORDER BY [c].[CustomerID], 
|   |__ shaper: (QueryContext queryContext | ValueBuffer c) => (decimal)double Average(IEnumerable<double> _Select(
|       |__ source: IEnumerable<ValueBuffer> _InjectParameters(
|       |   |__ queryContext: queryContext, 
|       |   |__ source: IEnumerable<ValueBuffer> _ShapedQuery(
|       |   |   |__ queryContext: queryContext, 
|       |   |   |__ shaperCommandContext: SelectExpression: 
|       |   |   |       SELECT [o1].[OrderID], 5.0
|       |   |   |       FROM [Orders] AS [o1]
|       |   |   |       WHERE @_outer_CustomerID = [o1].[CustomerID], 
|       |   |   |__ shaper: ValueBufferShaper), 
|       |   |__ parameterNames: new string[]{ "_outer_CustomerID" }, 
|       |   |__ parameterValues: new object[]{ string TryReadValue(c, 0, Customer.CustomerID) }), 
|       |__ selector: (ValueBuffer o) => (double)Nullable<double> TryReadValue(o, 1, null) + double GetResult(
|           |__ valueBuffers: IEnumerable<ValueBuffer> _InjectParameters(
|           |   |__ queryContext: queryContext, 
|           |   |__ source: IEnumerable<ValueBuffer> _Query(
|           |   |   |__ queryContext: queryContext, 
|           |   |   |__ shaperCommandContext: SelectExpression: 
|           |   |           SELECT AVG(CAST([od7].[ProductID] AS float))
|           |   |           FROM [Order Details] AS [od7]
|           |   |           WHERE @_outer_OrderID2 = [od7].[OrderID]), 
|           |   |__ parameterNames: new string[]{ "_outer_OrderID2" }, 
|           |   |__ parameterValues: new object[]{ (object)Nullable<int> TryReadValue(o, 0, Order.OrderID) }), 
|           |__ throwOnNullResult: True)))))), 
|__ contextType: TestModels.Northwind.NorthwindRelationalContext, 
|__ logger: DiagnosticsLogger<Query>, 
|__ queryContext: Unhandled parameter: queryContext)

query plan for sql server:

(QueryContext queryContext) => IEnumerable<decimal> _InterceptExceptions(
|__ source: IEnumerable<decimal> _ToSequence(() => decimal Average(IEnumerable<decimal> _ShapedQuery(
|   |__ queryContext: queryContext, 
|   |__ shaperCommandContext: SelectExpression: 
|   |       SELECT TOP(@__p_0) [c].[CustomerID]
|   |       FROM [Customers] AS [c]
|   |       ORDER BY [c].[CustomerID], 
|   |__ shaper: (QueryContext queryContext | ValueBuffer c) => (decimal)double Average(IEnumerable<double> _Select(
|       |__ source: IEnumerable<ValueBuffer> _InjectParameters(
|       |   |__ queryContext: queryContext, 
|       |   |__ source: IEnumerable<ValueBuffer> _ShapedQuery(
|       |   |   |__ queryContext: queryContext, 
|       |   |   |__ shaperCommandContext: SelectExpression: 
|       |   |   |       SELECT [o1].[OrderID], 5.0E0
|       |   |   |       FROM [Orders] AS [o1]
|       |   |   |       WHERE @_outer_CustomerID = [o1].[CustomerID], 
|       |   |   |__ shaper: ValueBufferShaper), 
|       |   |__ parameterNames: new string[]{ "_outer_CustomerID" }, 
|       |   |__ parameterValues: new object[]{ string TryReadValue(c, 0, Customer.CustomerID) }), 
|       |__ selector: (ValueBuffer o) => (double)Nullable<double> TryReadValue(o, 1, null) + double GetResult(
|           |__ valueBuffers: IEnumerable<ValueBuffer> _InjectParameters(
|           |   |__ queryContext: queryContext, 
|           |   |__ source: IEnumerable<ValueBuffer> _Query(
|           |   |   |__ queryContext: queryContext, 
|           |   |   |__ shaperCommandContext: SelectExpression: 
|           |   |           SELECT AVG(CAST([od7].[ProductID] AS float))
|           |   |           FROM [Order Details] AS [od7]
|           |   |           WHERE @_outer_OrderID2 = [od7].[OrderID]), 
|           |   |__ parameterNames: new string[]{ "_outer_OrderID2" }, 
|           |   |__ parameterValues: new object[]{ (object)Nullable<int> TryReadValue(o, 0, Order.OrderID) }), 
|           |__ throwOnNullResult: True)))))), 
|__ contextType: TestModels.Northwind.NorthwindRelationalContext, 
|__ logger: DiagnosticsLogger<Query>, 
|__ queryContext: Unhandled parameter: queryContext)

The only difference is how constant 5 in the second query, so it does look like a type mapping issue. On sql server literal is printed in this for by SqlServerDoubleTypeMapping.GenerateNonNullSqlLiteral. SqlCE does seem to have a corresponding class - SqlCeFloatTypeMapping which is supposed to introduce a cast to float, but this doesn't happen.

All 3 comments

@maumar to take a look

Query plan for CE:

(QueryContext queryContext) => IEnumerable<decimal> _InterceptExceptions(
|__ source: IEnumerable<decimal> _ToSequence(() => decimal Average(IEnumerable<decimal> _ShapedQuery(
|   |__ queryContext: queryContext, 
|   |__ shaperCommandContext: SelectExpression: 
|   |       SELECT TOP(@__p_0) [c].[CustomerID]
|   |       FROM [Customers] AS [c]
|   |       ORDER BY [c].[CustomerID], 
|   |__ shaper: (QueryContext queryContext | ValueBuffer c) => (decimal)double Average(IEnumerable<double> _Select(
|       |__ source: IEnumerable<ValueBuffer> _InjectParameters(
|       |   |__ queryContext: queryContext, 
|       |   |__ source: IEnumerable<ValueBuffer> _ShapedQuery(
|       |   |   |__ queryContext: queryContext, 
|       |   |   |__ shaperCommandContext: SelectExpression: 
|       |   |   |       SELECT [o1].[OrderID], 5.0
|       |   |   |       FROM [Orders] AS [o1]
|       |   |   |       WHERE @_outer_CustomerID = [o1].[CustomerID], 
|       |   |   |__ shaper: ValueBufferShaper), 
|       |   |__ parameterNames: new string[]{ "_outer_CustomerID" }, 
|       |   |__ parameterValues: new object[]{ string TryReadValue(c, 0, Customer.CustomerID) }), 
|       |__ selector: (ValueBuffer o) => (double)Nullable<double> TryReadValue(o, 1, null) + double GetResult(
|           |__ valueBuffers: IEnumerable<ValueBuffer> _InjectParameters(
|           |   |__ queryContext: queryContext, 
|           |   |__ source: IEnumerable<ValueBuffer> _Query(
|           |   |   |__ queryContext: queryContext, 
|           |   |   |__ shaperCommandContext: SelectExpression: 
|           |   |           SELECT AVG(CAST([od7].[ProductID] AS float))
|           |   |           FROM [Order Details] AS [od7]
|           |   |           WHERE @_outer_OrderID2 = [od7].[OrderID]), 
|           |   |__ parameterNames: new string[]{ "_outer_OrderID2" }, 
|           |   |__ parameterValues: new object[]{ (object)Nullable<int> TryReadValue(o, 0, Order.OrderID) }), 
|           |__ throwOnNullResult: True)))))), 
|__ contextType: TestModels.Northwind.NorthwindRelationalContext, 
|__ logger: DiagnosticsLogger<Query>, 
|__ queryContext: Unhandled parameter: queryContext)

query plan for sql server:

(QueryContext queryContext) => IEnumerable<decimal> _InterceptExceptions(
|__ source: IEnumerable<decimal> _ToSequence(() => decimal Average(IEnumerable<decimal> _ShapedQuery(
|   |__ queryContext: queryContext, 
|   |__ shaperCommandContext: SelectExpression: 
|   |       SELECT TOP(@__p_0) [c].[CustomerID]
|   |       FROM [Customers] AS [c]
|   |       ORDER BY [c].[CustomerID], 
|   |__ shaper: (QueryContext queryContext | ValueBuffer c) => (decimal)double Average(IEnumerable<double> _Select(
|       |__ source: IEnumerable<ValueBuffer> _InjectParameters(
|       |   |__ queryContext: queryContext, 
|       |   |__ source: IEnumerable<ValueBuffer> _ShapedQuery(
|       |   |   |__ queryContext: queryContext, 
|       |   |   |__ shaperCommandContext: SelectExpression: 
|       |   |   |       SELECT [o1].[OrderID], 5.0E0
|       |   |   |       FROM [Orders] AS [o1]
|       |   |   |       WHERE @_outer_CustomerID = [o1].[CustomerID], 
|       |   |   |__ shaper: ValueBufferShaper), 
|       |   |__ parameterNames: new string[]{ "_outer_CustomerID" }, 
|       |   |__ parameterValues: new object[]{ string TryReadValue(c, 0, Customer.CustomerID) }), 
|       |__ selector: (ValueBuffer o) => (double)Nullable<double> TryReadValue(o, 1, null) + double GetResult(
|           |__ valueBuffers: IEnumerable<ValueBuffer> _InjectParameters(
|           |   |__ queryContext: queryContext, 
|           |   |__ source: IEnumerable<ValueBuffer> _Query(
|           |   |   |__ queryContext: queryContext, 
|           |   |   |__ shaperCommandContext: SelectExpression: 
|           |   |           SELECT AVG(CAST([od7].[ProductID] AS float))
|           |   |           FROM [Order Details] AS [od7]
|           |   |           WHERE @_outer_OrderID2 = [od7].[OrderID]), 
|           |   |__ parameterNames: new string[]{ "_outer_OrderID2" }, 
|           |   |__ parameterValues: new object[]{ (object)Nullable<int> TryReadValue(o, 0, Order.OrderID) }), 
|           |__ throwOnNullResult: True)))))), 
|__ contextType: TestModels.Northwind.NorthwindRelationalContext, 
|__ logger: DiagnosticsLogger<Query>, 
|__ queryContext: Unhandled parameter: queryContext)

The only difference is how constant 5 in the second query, so it does look like a type mapping issue. On sql server literal is printed in this for by SqlServerDoubleTypeMapping.GenerateNonNullSqlLiteral. SqlCE does seem to have a corresponding class - SqlCeFloatTypeMapping which is supposed to introduce a cast to float, but this doesn't happen.

The SQL CE provider was missing a DoubleTypeMapping! (The FloatTypemapping is for Single)

Was this page helpful?
0 / 5 - 0 ratings