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

LINQ translation for Nullable<T>.HasValue incorrectly translates to IS_DEFINED() - should be (NOT IS_NULL()) OR IS_DEFINED() #4864

Open
DaRosenberg opened this issue Nov 1, 2024 · 2 comments
Assignees
Labels

Comments

@DaRosenberg
Copy link

DaRosenberg commented Nov 1, 2024

Describe the bug

There is LINQ translation support for Nullable<T>.HasValue in the v3 SDK. However, the translation assumes the property must be missing or undefined in the underlying document. It ignores the fact that it might also be null and that the .HasValue property in .NET is the idiomatic (and only) way to query for that, given that .NET lacks any distinction between null and undefined.

To Reproduce

void Main()
{
    var client = new CosmosClient("connectionString", new CosmosClientOptions());
    var container = client.GetContainer("x", "y");
    var query =
        container.GetItemLinqQueryable<C>()
    	    .Where(x => !x.NullableValue.HasValue);
    Console.WriteLine(query.ToQueryDefinition());	
}

public class C
{
    public DateTime? NullableValue { get; set; }
}

Expected behavior

SELECT VALUE root FROM root WHERE ((NOT IS_DEFINED(root["nullableValue"])) OR IS_NULL(root["nullableValue"]))

Actual behavior

SELECT VALUE root FROM root WHERE (NOT IS_DEFINED(root["nullableValue"]))

(This misses documents where nullableValue == null in the database.)

Environment summary

SDK Version: 3.41.0

@microsoft-github-policy-service microsoft-github-policy-service bot added the customer-reported Issue created by a customer label Nov 1, 2024
@DaRosenberg DaRosenberg changed the title LINQ translation for Nullable<T>.HasValue incorrectly translates to IS_DEFINED() - should be IS_NULL() OR IS_DEFINED() LINQ translation for Nullable<T>.HasValue incorrectly translates to IS_DEFINED() - should be (NOT IS_NULL()) OR IS_DEFINED() Nov 26, 2024
@HEBOS
Copy link

HEBOS commented Jan 3, 2025

I'd say that using HasValue should be redundant.
I'd expect this:

var query = container.GetItemLinqQueryable<C>() .Where(x => !x.NullableValue);
to be translated to the same SQL code:

SELECT VALUE root FROM root WHERE ((NOT IS_DEFINED(root["nullableValue"])) OR IS_NULL(root["nullableValue"]))

In other words, why would we need to pass "!nullableValue.HasValue" at all?
It makes code very hard to maintain.

@DaRosenberg
Copy link
Author

@HEBOS That will not even compile I think - you can't use a Nullable<T> as a boolean expression C# (like you can in JavaScript). You can only do compare it to null or use the HasValue property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants