-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support ReadItem for no-tracking queries
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.
- Loading branch information
1 parent
3d7800e
commit 2e079da
Showing
20 changed files
with
1,705 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
src/EFCore.Cosmos/Metadata/Conventions/JsonIdConvention.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; | ||
|
||
namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions; | ||
|
||
/// <summary> | ||
/// A convention that builds an <see cref="JsonIdDefinition"/> for each top-level entity type. This is used | ||
/// to build JSON `id` property values from combinations of other property values. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-conventions">Model building conventions</see>, and | ||
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples. | ||
/// </remarks> | ||
public class JsonIdConvention : IModelFinalizingConvention | ||
{ | ||
/// <summary> | ||
/// Creates a new instance of <see cref="JsonIdConvention" />. | ||
/// </summary> | ||
/// <param name="dependencies">Parameter object containing dependencies for this convention.</param> | ||
public JsonIdConvention(ProviderConventionSetBuilderDependencies dependencies) | ||
{ | ||
Dependencies = dependencies; | ||
} | ||
|
||
/// <summary> | ||
/// Dependencies for this service. | ||
/// </summary> | ||
protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } | ||
|
||
/// <inheritdoc /> | ||
public virtual void ProcessModelFinalizing( | ||
IConventionModelBuilder modelBuilder, | ||
IConventionContext<IConventionModelBuilder> context) | ||
{ | ||
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) | ||
{ | ||
var primaryKey = entityType.FindPrimaryKey(); | ||
if (entityType.IsOwned() || primaryKey == null) | ||
{ | ||
entityType.RemoveAnnotation(CosmosAnnotationNames.JsonIdDefinition); | ||
continue; | ||
} | ||
|
||
// Remove properties that are also partition keys, since Cosmos handles those separately, and so they should not be in `id`. | ||
var partitionKeyNames = entityType.GetPartitionKeyPropertyNames(); | ||
var primaryKeyProperties = new List<IConventionProperty>(primaryKey.Properties.Count); | ||
foreach (var property in primaryKey.Properties) | ||
{ | ||
if (!partitionKeyNames.Contains(property.Name)) | ||
{ | ||
primaryKeyProperties.Add(property); | ||
} | ||
} | ||
|
||
var idProperty = entityType.GetProperties() | ||
.FirstOrDefault(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); | ||
|
||
var properties = new List<IConventionProperty>(); | ||
// If the property mapped to the JSON id is simply the primary key, or is the primary key without partition keys, then use | ||
// it directly. | ||
if ((primaryKeyProperties.Count == 1 | ||
&& primaryKeyProperties[0] == idProperty) | ||
|| (primaryKey.Properties.Count == 1 | ||
&& primaryKey.Properties[0] == idProperty)) | ||
{ | ||
properties.Add(idProperty); | ||
} | ||
// Otherwise, if the property mapped to the JSON id doesn't have a generator, then we can't use ReadItem. | ||
else if (idProperty != null && idProperty.GetValueGeneratorFactory() == null) | ||
{ | ||
entityType.RemoveAnnotation(CosmosAnnotationNames.JsonIdDefinition); | ||
continue; | ||
} | ||
else | ||
{ | ||
var discriminator = entityType.GetDiscriminatorValue(); | ||
// If the discriminator is not part of the primary key already, then add it to the Cosmos `id`. | ||
if (discriminator != null) | ||
{ | ||
var discriminatorProperty = entityType.FindDiscriminatorProperty(); | ||
if (!primaryKey.Properties.Contains(discriminatorProperty)) | ||
{ | ||
properties.Add(discriminatorProperty!); | ||
} | ||
} | ||
|
||
// Next add all primary key properties, except for those that are also partition keys, which were removed above. | ||
foreach (var property in primaryKeyProperties) | ||
{ | ||
properties.Add(property); | ||
} | ||
} | ||
|
||
entityType.SetAnnotation(CosmosAnnotationNames.JsonIdDefinition, new JsonIdDefinition(properties)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/EFCore.Cosmos/Metadata/Internal/IRuntimeJsonIdDefinitionFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; | ||
|
||
/// <summary> | ||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to | ||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in | ||
/// any release. You should only use it directly in your code with extreme caution and knowing that | ||
/// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
/// </summary> | ||
public interface IRuntimeJsonIdDefinitionFactory | ||
{ | ||
/// <summary> | ||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to | ||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in | ||
/// any release. You should only use it directly in your code with extreme caution and knowing that | ||
/// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
/// </summary> | ||
RuntimeJsonIdDefinition Create(RuntimeEntityType entityType, JsonIdDefinition jsonIdDefinition); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; | ||
|
||
/// <summary> | ||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to | ||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in | ||
/// any release. You should only use it directly in your code with extreme caution and knowing that | ||
/// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
/// </summary> | ||
public readonly struct JsonIdDefinition | ||
{ | ||
/// <summary> | ||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to | ||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in | ||
/// any release. You should only use it directly in your code with extreme caution and knowing that | ||
/// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
/// </summary> | ||
public IReadOnlyList<IConventionProperty> Properties { get; } | ||
|
||
/// <summary> | ||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to | ||
/// the same compatibility standards as public APIs. It may be changed or removed without notice in | ||
/// any release. You should only use it directly in your code with extreme caution and knowing that | ||
/// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
/// </summary> | ||
public JsonIdDefinition(IReadOnlyList<IConventionProperty> properties) | ||
{ | ||
Properties = properties; | ||
} | ||
} |
Oops, something went wrong.