efcore icon indicating copy to clipboard operation
efcore copied to clipboard

Cosmos: Add support for IS_DEFINED() to EF.Functions

Open divega opened this issue 5 years ago • 6 comments

The full context is explained in #13131, but I decided to create a new issue to gather more targeted customer feedback on this.

The short version is that in a schema-less database like Cosmos DB it is valid for each document in a container to contain completely different set of properties. In an object mapping situation this translates into some of the mapped properties being absent. Cosmos DB provides a function IS_DEFINED() that can be used in queries to test for this situation. Note also that a property not being defined is different (albeit one can argue only slightly) from the value being null.

The Cosmos DB provider could define an extension method in EF.Functions that could be used, for example, like this:

var itemsMissingData = context.Items.Where(i => !EF.Functions.IsDefined(i.Data));

divega avatar Sep 09 '19 20:09 divega

It seems that Cosmos DB is still filtering out documents where a property is undefined if you ORDER BY that property. This makes providing access to the IS_DEFINED() function from LINQ queries more important. That way, you can use it like this:

var orderedItems = context.Items.OrderBy(i => i.Data);
var itemsMissingData = context.Items.Where(i => !EF.Functions.IsDefined(i.Data));
orderedItems.AddRange(itemsMissingData);

divega avatar Sep 09 '19 20:09 divega

Also consider Coalesce operator ?? which is used to coalesce based on present keys.

smitpatel avatar Dec 10 '19 23:12 smitpatel

Do we have a timeline on when this will be implemented?

prachita-mane avatar Apr 16 '20 23:04 prachita-mane

@prachita-mane It's in the backlog meaning we don't plan on working on it in the upcoming releases. However we are open to well-written external PRs.

AndriySvyryd avatar Apr 16 '20 23:04 AndriySvyryd

Is there an alternative to this? For example I am trying to check if a nested property is null and am getting an exception about the query not being able to be translated. My query looks like the following where .Provider is a complex type. I only want to return types where there isn't a Provider field set.

.Where(p => p.Provider == null)

This throws the following exception:

DbSet<User> .Where(u => EF.Property<Nullable<Guid>>(EF.Property<Provider>(u, "Provider"), "UserId") == null)' could not be translated.

Are we dealing with the same/similar thing here?

I would have expected the translation for CosmosDB to be as simple as

WHERE c["Provider"] == null

clintsinger avatar May 12 '20 17:05 clintsinger

Note to implementer, add these test cases:

  • IsDefined in a Where call
  • IsDefined in a Select call that creates an anonymous type
  • IsDefined on a shadow property (Person.__id)
  • IsDefined on a derived property (Bird.IsFlightless in InheritanceQueryCosmosTest)
  • IsDefined on an embedded scalar property (OwnedPerson.PersonAddress.Country.Name in OwnedQueryCosmosTest)
  • IsDefined on an embedded scalar collection
  • IsDefined on an embedded reference navigation (OwnedPerson.PersonAddress in OwnedQueryCosmosTest, can throw)
  • IsDefined on an embedded collection navigation (OwnedPerson.Orders in OwnedQueryCosmosTest, can throw)
  • IsDefined on a non-embedded navigation (Person.Orders, should throw)
  • IsDefined on a non-existing property (Person.NonExisting, should throw)
  • IsDefined on a non-mapped property (Person.__jObject, should throw)

AndriySvyryd avatar May 05 '22 19:05 AndriySvyryd

Note also #33904, which is about adding support for the undefined coalescing operator (??).

roji avatar Jun 04 '24 19:06 roji

Poaching as I'm in the area with #33904.

roji avatar Jun 08 '24 21:06 roji