-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
EF Core Changing my Parameter Types (adding precision to decimals and random numbers to floats) #35548
Comments
In summary, Visual Studio doesn't display the truth and you have to use profiler to see that the actual data being sent to the DB looks nothing like the linq statement you're debugging. How can you justify releasing this? 0.005 being converted to 1 - wtf?! So now I can't perform a basic linq statement with a double or a float? |
As explained on dotnet/runtime#1643 (comment), this is how You likely have some other issue in your code, such as in how you're initializing |
that doesn't seem related to floating point representation and warrants further debugging to see what happens between EF Core and SQL statement generation |
Apologies...been a long night and day. I've posted the code and it works in EF6 but doesn't in EF Core. The Holding class is a DTO (also posted above) - I literally call new Holding { Expense = 0.005m, Shares = 0.0004 }. This is what I see in the debugger: |
OK, I've debugged the old version and the Shares float behaviour is identical to above...I accept I'm incorrect here and have learnt something new, which I appreciate. There are some other differences to note: EF6 appears to declare the Expense as a decimal(3,3) and has a value of 5 - once again, I don't understand this behaviour but this does return the correct record. I also checked the SQL that was being generated in EF Core by using .ToQueryString() on the IQueryable but the sql looks fine - the Expense matches what I have in the test (0.005). |
Closing as there doesn't seem to be any issue with EF here. If I've misunderstood, please post back with a clear EF-specific repro and we can revisit. |
So the decimal 0.005 being incorrectly represented as 1 isn't an issue? @weltkante Is this normal behaviour? The old version did something difference and works...EF Core doesn't work here. I should be able to select a decimal from the database using the code above as it worked fine before upgrading to .Net 8 and EF Core. Multiple individuals mention there must be something wrong with the code what's wrong with this: So why can't I retrieve my record from the DB? Why do I have to change code that works perfectly before? Can anyone explain why this doesn't work in EF Core but works fine in EF6? |
Seems you misunderstood, but I agree, the proper way is to create a repro scenario that you can investigate instead of code-screenshots ;-)
They probably missed that particular detail of the discussion, there was a lot of distraction going on. I already agreed it looks wrong and its probably worth debugging how .NET Core gets from 0.005 to 1 while Desktop Framework doesn't - I'd not expect this conversion, same as you, and I'm not aware of any "obvious" reason why that should happen. Whether or not "its an issue of EF Core" depends on why its happening and only can be determined once its understood what happens. Currently it looks like the most likely the conversion happens inside EF Core. The normal approach is to either create a reproduction scenario that can be posted in the issue as code, so the EF Core team can investigate. Posting screenshots and describing your issue in plaintext only helps if you made an "obvious" mistake which someone else already knows what its being caused by. Nobody can really do further investigation on a screenshot. Alternatively you can continue investigating yourself and look into why this conversions happens. There are multiple ways to "debug into" a library, for example you could try to set breakpoints in EF Core functions (by function name) and look at the stacktrace you break and repeat until you close in on the place it happens, or you could turn off "just my code" in VS options and try stepping through the library. You could also use a third party debugger like dnspy which doesn't distinguish between your own code and library code and allows to debug everything. Personally I'd suggest creating a repro scenario, thats probably the least amount of work, and more often than not its possible to learn more about the problem while trying to reproduce it, like whether there is additional code that influences triggering the problem. PS: just giving friendly advice here and am not otherwise involved with the repository or Microsoft. I was subscribed on the Math.Round issue to get notified of updates on the (unrelated) problem they had there, and figured it would make sense to point out that the discussion was losing focus of the actual problem |
OK, thanks @weltkante. I'll keep this closed until a proper repro is provided, which shows EF doing something wrong. |
Hi Guys, wanted to provide an update as I think I may have found the issue.... In producing the repro my table definition has a number of Money type fields. In the associated model in the solution we have these mapped to Decimal but these don't have any precision associated to them. Checking the breaking changes in EF you now have to specify the precision of a decimal in configuration. Thanks for the help/pointers all round...not sure I'd have got to the bottom of this without it. |
Question
Can someone explain this behaviour to me please:
I have this dto:
When I execute this code with the Expense set to 0.005 and the shares set to 0.0004:
var result =
_context.Holding.Where(
h =>
(h.ClientRef == holding.ClientRef) &&
(h.SecurityRef == holding.SecurityRef) &&
(!holding.Expense.HasValue || h.Expense == holding.Expense) && -- 0.005
(!holding.Shares.HasValue || h.Shares == holding.Shares) && -- 0.0004
(!holding.AvExpense.HasValue || h.AvExpense == holding.AvExpense) &&
(!holding.Proceeds.HasValue || h.Proceeds == holding.Proceeds) &&
(!holding.Valuation.HasValue || h.Valuation == holding.Valuation) &&
(!holding.Truncation.HasValue || h.Truncation == holding.Truncation) &&
(!holding.Indexation.HasValue || h.Indexation == holding.Indexation) &&
(!holding.QEExpense.HasValue || h.QEExpense == holding.QEExpense) &&
(!holding.QEProceeds.HasValue || h.QEProceeds == holding.QEProceeds) &&
(!holding.Price.HasValue || h.Price == holding.Price));
What I see in the profiler is this:
exec sp_executesql N'SELECT [h].[HoldingRef], [h].[AvExpense], [h].[CGTExpense], [h].[ClientRef], [h].[Expense], [h].[Indexation], [h].[Price], [h].[Proceeds], [h].[QEExpense], [h].[QEProceeds], [h].[SecurityRef], [h].[Shares], [h].[SuspectMarker], [h].[Truncation], [h].[UpdateDate], [h].[Valuation], [h].[ValueDate] FROM [Holding] AS [h] WHERE [h].[ClientRef] = @__holding_ClientRef_0 AND [h].[SecurityRef] = @__holding_SecurityRef_1 AND [h].[Expense] = @__holding_Expense_2 AND [h].[Shares] = @__holding_Shares_3',N'@__holding_ClientRef_0 int,@__holding_SecurityRef_1 int,@__holding_Expense_2 decimal(18,2),@__holding_Shares_3 float',@__holding_ClientRef_0=5755894,@__holding_SecurityRef_1=5734051,@__holding_Expense_2=1,@__holding_Shares_3=0.0004000000000000000191686944095437183932517655
Notice the following
@__holding_Expense_2=1 -- this should be 0.005
@__holding_Shares_3=0.0004000000000000000191686944095437183932517655 -- this should be 0.0004
Why is this happening and how do I stop it from happening? I have not specified '@__holding_Expense_2 decimal(18,2),@__holding_Shares_3 float' anywhere in my code
Your code
Stack traces
Verbose output
EF Core version
8.0.3
Database provider
No response
Target framework
.net 8
Operating system
No response
IDE
No response
The text was updated successfully, but these errors were encountered: