Skip to content

InvalidCastException when casting from one value type to another in a simple select statement #8652

Closed
@samb0t

Description

@samb0t

InvalidCastApp.zip
When casting a property from a nullable double to a nullable int in a Select function, an InvalidCastException occurs. Likewise, the same exception occurs if the types are not nullable.

Attached is a working example of the issue. Just create the database and table first and then update the connection string in Program.cs.

The select looks like this:

.Select(o => new DTO() {  
  Limit = o.Limit__c.HasValue ? (int?)o.Limit__c : null,   
  Slots = o.Slots__c.HasValue ? (int?)o.Slots__c : null  
  })  
  .Where(o => cIds.Contains(o.CId))  
  .ToListAsync());  

Limit__c and Slots__c are nullable doubles
The SQL profiler does not show any casting before the exception is thrown.
The same query was working in EF 6.x (Full Framework).

Exception message: Specified cast is not valid.
Stack trace:
<error errorId="7f262bc2-3b41-439b-be10-ed2c6e480a0f" application="/LM/W3SVC/2/ROOT" host="" type="System.InvalidCastException" message="Specified cast is not valid." source="Anonymously Hosted DynamicMethods Assembly" detail="System.InvalidCastException: Specified cast is not valid.;  
 at lambda_method(Closure , QueryContext , ValueBuffer );  
 at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer valueBuffer);  
 at Microsoft.EntityFrameworkCore.Query.AsyncQueryMethodProvider.&lt;&gt;c__DisplayClass3_0`1.&lt;_ShapedQuery&gt;b__0(ValueBuffer vb);  
 at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.&lt;MoveNextCore&gt;d__7.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.AsyncIterator`1.&lt;MoveNext&gt;d__10.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.&lt;MoveNext&gt;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 System.Linq.AsyncEnumerable.&lt;Aggregate_&gt;d__6`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.Runtime.CompilerServices.TaskAwaiter`1.GetResult();  
 at --snip--.&lt;WithContext&gt;d__5`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 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult();  
 at --snip--.&lt;GetByContractIds&gt;d__13.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.Runtime.CompilerServices.TaskAwaiter`1.GetResult();  
 at --snip--d__54.MoveNext() in 
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task);  
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task);  
 at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult();  
 at --snip--Load&gt;d__14.MoveNext() in 
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task);  
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task);  
 at System.Runtime.CompilerServices.TaskAwaiter.GetResult();  
 at --snip--Contract&gt;d__70.MoveNext() in 
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task);  
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task);  
 at System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass37.&lt;BeginInvokeAsynchronousActionMethod&gt;b__36(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.&lt;InvokeActionMethodFilterAsynchronouslyRecursive&gt;b__3d();  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.&lt;&gt;c__DisplayClass46.&lt;InvokeActionMethodFilterAsynchronouslyRecursive&gt;b__3f();  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass21.&lt;&gt;c__DisplayClass2b.&lt;BeginInvokeAction&gt;b__1c();  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass21.&lt;BeginInvokeAction&gt;b__1e(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult);  
 at System.Web.Mvc.Controller.&lt;BeginExecuteCore&gt;b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState);  
 at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult);  
 at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult);  
 at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult);  
 at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult);  
 at System.Web.Mvc.MvcHandler.&lt;BeginProcessRequest&gt;b__5(IAsyncResult asyncResult, ProcessRequestState innerState);  
 at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult);  
 at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult);  
 at System.Web.HttpApplication.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)" user="" time="2017-05-31T19:14:36.8015246Z">

Steps to reproduce

  1. Create a table with a column defined as decimal(18,0),null and an int primary key.
  2. Use the project in the attached zip, first updating the connection string in Program.cs.
  3. Running the application will give the invalid cast exception.
.Select(o => new DTO() {  
  ModelWithNullableInt = o.ModelWithNullableDecimal.HasValue ? (int?)o.ModelWithNullableDecimal: null})  

Further technical details

EF Core version: Reproduced in 1.1.2 as well as 2.0.0-preview1-final
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10 64-bit
IDE: Visual Studio 2017 - build 26510.0 Preview

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions