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.UnbufferedEntityShaper
1.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?