Casting issue causing exception when data is within the range

426 Views Asked by At

I have a .NET Core web-service that expose api. It has a database table like below.

CREATE TABLE Employee
(
    Id INT NOT NULL IDENTITY(1,1),
    [Name] VARCHAR(100) NOT NULL,
    Points FLOAT NOT NULL,
    CONSTRAINT [PK_Employee] PRIMARY KEY NONCLUSTERED ([Id] ASC )
)

This table was scaffolded to code as follows.

public partial class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Points { get; set; }
    }

This class is consumed as below.

var employees = context.Employee.ToList();

This code is running fine with few happy customers. So far so good.

When work for the Version 2 of same application started, I realised that data getting stored in the Points column doesn't need any precision, it can actually fit in a tinyint range. As a result, I changed the data type to tinyint for version 2 but we still have customer using version 1 of application . The class in version 2 now looks as follows with Points column has a type of byte.

public partial class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public byte Points { get; set; }
    }

With this change, my thinking was that since the data contained in table actually is all within the range of tinyint, there should not be any issues for Version 1 code base. However now the application version 1 code encounters exception when executing following line.

var employees = context.Employee.ToList();

Below is the exception.

Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory - An exception occurred in the database while iterating the results of a query. System.InvalidOperationException: An exception occured while reading a database value for property 'Employee.Points '. The expected type was 'System.Double' but the actual value was of type 'System.Byte'. ---> System.InvalidCastException: Unable to cast object of type 'System.Byte' to type 'System.Double'. at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityMaterializerSource.TryReadValue[TValue](ValueBuffer valueBuffer, Int32 index, IPropertyBase property) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityMaterializerSource.ThrowReadValueException[TValue](Exception exception, Object value, IPropertyBase property) at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityMaterializerSource.TryReadValue[TValue](ValueBuffer valueBuffer, Int32 index, IPropertyBase property) at lambda_method(Closure , ValueBuffer ) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.UnbufferedEntityShaper1.Shape(QueryContext queryContext, ValueBuffer valueBuffer) at Microsoft.EntityFrameworkCore.Query.AsyncQueryMethodProvider.<>c__DisplayClass3_01.<_ShapedQuery>b__0(ValueBuffer vb) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.SelectAsyncEnumerable2.SelectAsyncEnumerator.<MoveNext>d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.SelectAsyncEnumerable2.SelectAsyncEnumerator.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

I understand that casting from double to byte causes a data loss but in this case all the values int his table are between 1 to 5. Where is my thinking wrong here?

0

There are 0 best solutions below