BLoB
BLoB

Reputation: 9725

Incorrect number of decimal places when saving value using entity framework 4.3.1

Don't ask me why but in this legacy system it has a database field (SQL Server 2008) set as decimal(7,0) (nullable).

Now in EF4.3.1 I'm putting a value of 1360 into the entity (fine in debugger until I save) and saving, at which point I get an out of range error:

An error occurred while updating the entries. See the inner exception for details.

The inner exception explains:

Parameter value '1360.0000' is out of range.

Where has the extra four decimal places (that take it out of range) come from ?

P.S. The stack trace for what it's worth:

at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)

Here's some code:

TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions() { IsolationLevel = IsolationLevel.Serializable });

using (scope)
{
    using (WEDFUTEntities ctx = new WEDFUTEntities())
    {
        ctx.Connection.Open();

        Stock newStock = new Stock
        {
            Width = coil.Width,
        };

        ctx.Stocks.AddObject(newStock);
        ctx.SaveChanges();
        ctx.Connection.Close();
    }

    scope.Complete();
}

As stated before if the coil.Width is 3 digits, e.g. 726 it saves fine, however if the coil.Width is 1360 i get the aforementioned out of range error.

P.S. Both the Stock.Width and coil.Width are nullable decimals, i.e. decimal?

Update: Additionally I just tested changing coil.Width to be an int and it then works if passing 1360, it saves and throws no errors... hmmm

Upvotes: 2

Views: 2592

Answers (2)

BLoB
BLoB

Reputation: 9725

Solved the stupid thing...

Was using

string widthResult = "1360.0000" // The result of an edi read was giving this string.

decimal width = 0.0M;
decimal.TryParse(widthResult, out width);

The result of the TryParse was in fact 1360, not 1360.0000.

By adding

return decimal.Round(width, 0);

instead of just returning the decimal width

return width;

It works fine, how odd is that ?!?!?!?!?!?

Upvotes: 2

Blast_dan
Blast_dan

Reputation: 1125

I don't know if you are using code first or not. However if you are you can use the DecimalPropertyConfirugation class to define the decimal precision.

public class MyContext : DbContext
{
    public DbSet<MyClass> MyClass;
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MyClass>().Property(x => x.MyDecimalProperty).HasPrecision(7, 0);
    }
}

On database first you might want to regenerate the EDMX file as the metadata should define the proper decimal value.

In Model first be sure to set the appropriate precision as well.

Upvotes: 0

Related Questions