Skip to content

Support ReadItem for no-tracking queries#33927

Merged
ajcvickers merged 3 commits intomainfrom
PrettyLittleKeys
Jun 15, 2024
Merged

Support ReadItem for no-tracking queries#33927
ajcvickers merged 3 commits intomainfrom
PrettyLittleKeys

Conversation

@ajcvickers
Copy link
Copy Markdown
Contributor

Part of #20693
Part of #33893

There is a lot left to do here, but I'm making a break here to get reviews before it goes too far.

Major changes here are:

  • Discover and record properties used to form the JSON id in one place.
  • Use this to generate ate id values without tracking an instance. (Makes no-tracking work, needed for Reload.)
  • Be better at detecting only detecting patterns we can later translate.

Next up: be better at detecting non-Find query patterns that we can translate.

@ajcvickers ajcvickers requested a review from a team June 7, 2024 14:07
Comment thread src/EFCore.Cosmos/Metadata/Conventions/JsonIdConvention.cs Outdated
Comment thread src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinition.cs Outdated
Comment thread src/EFCore.Cosmos/Metadata/Conventions/CosmosRuntimeModelConvention.cs Outdated
Comment thread src/EFCore.Cosmos/Metadata/Internal/RuntimeJsonIdDefinition.cs Outdated
{
if (_queryCompilationContext.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll // Issue #33893
&& expression is MethodCallExpression
if (expression is MethodCallExpression
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(not quite related to this PR)

This being in Visit() means that it's done recursively for every node - although we should only pattern-match on the top-level node. In other words, if the whole ReadItem-compatible fragment is composed upon with something, we probably incorrectly convert (and have a bug). To fix this, we should override QueryableMethodTranslatingExpressionVisitor.Translate() and have it there.

As a nit, I'd also move the logic to a dedicated function (TryTransformToReadItem) just to make it extra clear what's being done here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@ajcvickers noticed this again while working in an area of the code; opened #34085 to make sure we don't forget it.

}
else
{
Check.DebugFail("Parameters should cover all properties or we should not be using ReadItem.");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: I've switched to throwing UnreachableException in these cases, since Check.DebugFail is for DEBUG-only, i.e. to get the assertion to trip in actual released bits (but not super important).

Comment thread src/EFCore.Cosmos/Metadata/Conventions/JsonIdConvention.cs Outdated
Comment thread src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs
@ajcvickers
Copy link
Copy Markdown
Contributor Author

@AndriySvyryd @roji There is a meta point that probably should be discussed here. In current versions of the Cosmos provider, a user can put their own value generator on the id property and in doing so change the way we build the composite key string. If we hard-code (that is remove the code from a convention and remove the factory that creates the definition) then everything here gets simpler. But it means that people can no longer customize this if they need to. (I'm not sure they need to--but this goes to the discussion about how much we can break things that can work now. We have tests that do this customization, so at some point we thought it important enough to test.)

@roji
Copy link
Copy Markdown
Member

roji commented Jun 12, 2024

@ajcvickers yeah, understood. We should maybe have a discussion on this in design...

@AndriySvyryd
Copy link
Copy Markdown
Member

@ajcvickers Users can still use their implementation of IRuntimeJsonIdDefinitionFactory if they need to customize this.

@ajcvickers
Copy link
Copy Markdown
Contributor Author

@AndriySvyryd @roji New version up based on Andriy's suggestion.

protected override void InitializeModel(IModel model, bool designTime, bool prevalidation)
{
base.InitializeModel(model, designTime, prevalidation);
model.SetRuntimeAnnotation(CosmosAnnotationNames.ModelDependencies, CosmosDependencies);
Copy link
Copy Markdown
Member

@AndriySvyryd AndriySvyryd Jun 14, 2024

Choose a reason for hiding this comment

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

Only set this if prevalidation is true or false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@AndriySvyryd

Only set this if prevalidation is true or false

prevalidation is a non-nullable bool...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Only set it when it's true xor false.
Basically, only do it once.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@AndriySvyryd I'm obviously missing something fundamental here. prevalidation is a single bool value. What am I xoring that with?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

C# is more precise than English. Add this after the first line:

if (!prevalidation)
{
    return;
}

Comment thread src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs Outdated
Part of #20693
Part of #33893

There is a lot left to do here, but I'm making a break here to get reviews before it goes too far.

Major changes here are:
- Discover and record properties used to form the JSON `id` in one place.
- Use this to generate ate `id` values without tracking an instance. (Makes no-tracking work, needed for Reload.)
- Be better at detecting only detecting patterns we can later translate.

Next up: be better at detecting non-Find query patterns that we can translate.
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.

3 participants