Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Unable to cast object of type 'System.Single' to type 'System.Double'." thrown when querying entity that contains property Double with some custom precision/scale values #22572

Closed
maumar opened this issue Sep 17, 2020 · 3 comments · Fixed by #25881
Labels
area-type-mapping closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@maumar
Copy link
Contributor

maumar commented Sep 17, 2020

Full repro:

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new MyContext())
            {
                ctx.Database.EnsureDeleted();
                ctx.Database.EnsureCreated();

                var e1 = new MyEntity { Double1 = 1123.432D };
                var e2 = new MyEntity { Double1 = 2123.432D };
                var e3 = new MyEntity { Double1 = 3123.432D };

                ctx.Entities.AddRange(e1, e2, e3);
                ctx.SaveChanges();
            }

            using (var ctx = new MyContext())
            {
                var result = ctx.Entities.ToList();
            }
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<MyEntity> Entities { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyEntity>().Property(x => x.Double1).HasPrecision(17, 3);
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=SingleToDouble;Trusted_Connection=True;MultipleActiveResultSets=true;Column Encryption Setting=Enabled");
        }
    }

    public class MyEntity
    {
        public int Id { get; set; }
        public double Double1 { get; set; }
    }

Problem here is that even though property is typed as double, sql server stores it as real. In shaper we try to extract double from the reader the exception is thrown:

System.InvalidCastException: Unable to cast object of type 'System.Single' to type 'System.Double'.
   at Microsoft.Data.SqlClient.SqlBuffer.get_Double()
   at Microsoft.Data.SqlClient.SqlDataReader.GetDouble(Int32 i)
   at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() in D:\git\efcore\src\EFCore.Relational\Query\Internal\SingleQueryingEnumerable.cs:line 165
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
@BC89
Copy link

BC89 commented Sep 18, 2020

I came across this too and the only workaround I found was to make the datatype Float in SQL and then Double in my classes. Seems to be a variation on your issue.

@jgegenfurtner
Copy link

I solved the problem like this:

modelBuilder.Entity<MyEntity>().Property(x => x.Double1).HasColumnType("decimal").HasPrecision(17, 3);

This produces a migration which uses a decimal(17,3) type instead of a float for MS SQL Server 13.0.4001 with EF Core 5.0.4.

@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Sep 5, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0, 6.0.0-rc2 Sep 8, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0-rc2, 6.0.0 Nov 8, 2021
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
@HakanBayazitHabes
Copy link

This error usually occurs when the data record is saved as a float (System.Single in C#) in the model even though the data record is defined as a double (float in SQL Server).

  • On the database side: float type is a double precision number.
  • On the C# side: float is a single precision number.

This incompatibility occurs when an attempt is made to retrieve a double value from SQL Server, but this value is defined as a float in the model.

Like this:

SQL Table C# Code

For the solution on the C# side, you can convert the float value to double.

public double Barcode { get; set; }

I hope it is useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-type-mapping closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants