glenn223
glenn223

Reputation: 303

EF Core: Can I Use `.HasConversion()` For A SQL Float To C# Decimal Conversion?

I have various existing SQL tables that have float columns that retain prices and I need to load them into C# decimal properties

After reading up on the .HasConversion() and .HasColumnType() methods, I thought I could read a SQL float (which EF Core should know is a float because of .HasColumnType() and intern translates that to a double) then convert it to a C# decimal using the .HasConversion() method; then vice-versa for writing back.

Have I misunderstood or am I misusing the methods?


Context OnModelCreating

entity.Property(e => e.Price) // <-- decimal field
    .IsRequired()
    .HasColumnName("PREFIX-Price")
    .HasColumnType("float")
    .HasDefaultValueSql("((0))")
    .HasConversion(
        v => Decimal.ToDouble(v),
        v => Convert.ToDecimal(v)
    )

After running something like:

var x = myContext.TableName.Select(x => x.Price);

I get the following exception:

InvalidCastException: Unable to cast object of type 'System.Double' to type 'System.Decimal'.
System.Data.SqlClient.SqlBuffer.get_Decimal()
System.Data.SqlClient.SqlDataReader.GetDecimal(int i)
lambda_method(Closure , DbDataReader )
Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)

I wouldn't expect it to call System.Data.SqlClient.SqlBuffer.get_Decimal() but rather fetch the float/double.

In the end, can I do what I'm trying to do?


Extra info:

(Although obvious) if I were to call the below then it works fine but this isn't really feasible as I/others could forget or not realise, plus the workload!

var x = myContext.TableName.Select(x => Convert.ToDecimal(x.Price));

Upvotes: 0

Views: 5484

Answers (1)

Kieran Devlin
Kieran Devlin

Reputation: 1433

You'll need to create your own Value Converter like so:

var converter = new ValueConverter<decimal, double>(
    v => (double)v,
    v => (decimal)v
);

and then use it in the fluent API configuration:

modelBuilder
    .Entity<EntityType>()
    .Property(e => e.FeildName)
    .HasConversion(converter);

Upvotes: 2

Related Questions