Skip to content

Fix to #35299 - EF Core InMemory database throws an argument exception on Nullable<>.ToString#35763

Merged
maumar merged 1 commit intomainfrom
fix35299
Apr 1, 2025
Merged

Fix to #35299 - EF Core InMemory database throws an argument exception on Nullable<>.ToString#35763
maumar merged 1 commit intomainfrom
fix35299

Conversation

@maumar
Copy link
Copy Markdown
Contributor

@maumar maumar commented Mar 11, 2025

Problem was that when rewriting the (inmemory) query, sometimes we change the nullability of the expression fragment. (e.g. when accessing a property on an optional entity). We then have a logic to compensate for the change. E.g. when the modified fragment was a caller of a method, we add a null check and only call the method (as non-nullable argument) if the value is not null. This way we can retain the method signature as it was. In 9, we added some exemptions to this logic, e.g. GetValueOrDefault, or Nullable<>.ToString, which don't need the compensation. Problem was that we were matching the ToString method incorrectly, only looking at the method name, so we would also match non-nullable ToString(). Fix is to look at the declaring type of the ToString method as well to make sure it's nullable, otherwise apply the compensation.

Fixes #35299

@maumar maumar requested a review from a team as a code owner March 11, 2025 09:50
@maumar maumar requested review from a team and Copilot and removed request for a team March 11, 2025 09:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Overview

This PR addresses an issue where the compensation logic was incorrectly applied to non-nullable ToString calls by refining the matching criteria for Nullable.ToString. The changes include updating the method call condition in the expression visitor and adding a new functional test to verify the fix.

  • Updated logic in InMemoryExpressionTranslatingExpressionVisitor to check the declaring type for Nullable.ToString.
  • Added a new functional test in GearsOfWarQueryInMemoryTest to cover the behavior on non-nullable properties.

Reviewed Changes

File Description
test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs Added a functional test to ensure proper handling of ToString on non-nullable properties of an optional entity.
src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs Refined the condition to correctly exclude Nullable.ToString by verifying the method's DeclaringType.

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs:891

  • [nitpick] The updated condition for excluding Nullable.ToString now includes a check on DeclaringType, which makes the logic complex. Consider adding inline comments or refactoring this condition into a helper method for better readability and maintainability.
&& !(@object!.Type.IsNullableValueType()

@maumar
Copy link
Copy Markdown
Contributor Author

maumar commented Mar 11, 2025

added the test to InMemory only - there is a discrepancy in the results for this scenario: in memory returns null (which is what it returned in 8, this change essentially reverts to the 8.0 behavior, fixing the regression we made in 9), whereas relational returns empty string (we append coalesce "") to those queries

@maumar
Copy link
Copy Markdown
Contributor Author

maumar commented Mar 11, 2025

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@maumar maumar marked this pull request as draft March 11, 2025 17:35
…n on Nullable<>.ToString

Problem was that when rewriting the (inmemory) query, sometimes we change the nullability of the expression fragment. (e.g. when accessing a property on an optional entity). We then have a logic to compensate for the change. E.g. when the modified fragment was a caller of a method, we add a null check and only call the method (as non-nullable argument) if the value is not null. This way we can retain the method signature as it was. In 9, we added some exemptions to this logic, e.g. `GetValueOrDefault`, or `Nullable<>.ToString`, which don't need the compensation. Problem was that we were matching the ToString method incorrectly, only looking at the method name, so we would also match non-nullable ToString(). Fix is to look at the declaring type of the ToString method as well to make sure it's nullable<T>, otherwise apply the compensation.

Fixes #35299
@maumar maumar marked this pull request as ready for review March 12, 2025 05:08
@maumar maumar merged commit e119e1f into main Apr 1, 2025
@maumar maumar deleted the fix35299 branch April 1, 2025 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EF Core InMemory database throws an argument exception on Nullable<>.ToString

5 participants