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

Support ReadItem for no-tracking queries #33927

Merged
merged 3 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator
{
annotations.Remove(CosmosAnnotationNames.Throughput);
}
else
{
annotations.Remove(CosmosAnnotationNames.ModelDependencies);
}

base.Generate(model, parameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using Microsoft.EntityFrameworkCore.Cosmos.Diagnostics.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;

// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -99,6 +101,7 @@ public static IServiceCollection AddEntityFrameworkCosmos(this IServiceCollectio
.TryAdd<IExecutionStrategyFactory, CosmosExecutionStrategyFactory>()
.TryAdd<IDbContextTransactionManager, CosmosTransactionManager>()
.TryAdd<IModelValidator, CosmosModelValidator>()
.TryAdd<IModelRuntimeInitializer, CosmosModelRuntimeInitializer>()
.TryAdd<IProviderConventionSetBuilder, CosmosConventionSetBuilder>()
.TryAdd<IValueGeneratorSelector, CosmosValueGeneratorSelector>()
.TryAdd<IDatabaseCreator, CosmosDatabaseCreator>()
Expand All @@ -115,11 +118,12 @@ public static IServiceCollection AddEntityFrameworkCosmos(this IServiceCollectio
.TryAddSingleton<ICosmosSingletonOptions, CosmosSingletonOptions>()
.TryAddSingleton<ISingletonCosmosClientWrapper, SingletonCosmosClientWrapper>()
.TryAddSingleton<IQuerySqlGeneratorFactory, QuerySqlGeneratorFactory>()
.TryAddSingleton<CosmosModelRuntimeInitializerDependencies, CosmosModelRuntimeInitializerDependencies>()
.TryAddSingleton<IJsonIdDefinitionFactory, JsonIdDefinitionFactory>()
.TryAddScoped<ISqlExpressionFactory, SqlExpressionFactory>()
.TryAddScoped<IMemberTranslatorProvider, CosmosMemberTranslatorProvider>()
.TryAddScoped<IMethodCallTranslatorProvider, CosmosMethodCallTranslatorProvider>()
.TryAddScoped<ICosmosClientWrapper, CosmosClientWrapper>()
);
.TryAddScoped<ICosmosClientWrapper, CosmosClientWrapper>());

builder.TryAddCoreServices();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// ReSharper disable once CheckNamespace

using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Infrastructure.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 class CosmosModelRuntimeInitializer : ModelRuntimeInitializer
{
/// <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 CosmosModelRuntimeInitializer(
ModelRuntimeInitializerDependencies dependencies,
CosmosModelRuntimeInitializerDependencies cosmosDependencies)
: base(dependencies)
{
CosmosDependencies = cosmosDependencies;
}

/// <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>
protected virtual CosmosModelRuntimeInitializerDependencies CosmosDependencies { 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>
protected override void InitializeModel(IModel model, bool designTime, bool prevalidation)
{
base.InitializeModel(model, designTime, prevalidation);

if (prevalidation || !designTime)
{
model.SetRuntimeAnnotation(CosmosAnnotationNames.ModelDependencies, CosmosDependencies);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.Infrastructure.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 sealed record CosmosModelRuntimeInitializerDependencies
{
/// <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>
/// <remarks>
/// Do not call this constructor directly from either provider or application code as it may change
/// as new dependencies are added. Instead, use this type in your constructor so that an instance
/// will be created and injected automatically by the dependency injection container. To create
/// an instance with some dependent services replaced, first resolve the object from the dependency
/// injection container, then replace selected services using the C# 'with' operator. Do not call
/// the constructor at any point in this process.
/// </remarks>
[EntityFrameworkInternal]
public CosmosModelRuntimeInitializerDependencies(IJsonIdDefinitionFactory jsonIdDefinitionFactory)
{
JsonIdDefinitionFactory = jsonIdDefinitionFactory;
}

/// <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 IJsonIdDefinitionFactory JsonIdDefinitionFactory { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public class CosmosRuntimeModelConvention : RuntimeModelConvention
/// Creates a new instance of <see cref="CosmosRuntimeModelConvention" />.
/// </summary>
/// <param name="dependencies">Parameter object containing dependencies for this convention.</param>
public CosmosRuntimeModelConvention(
ProviderConventionSetBuilderDependencies dependencies)
public CosmosRuntimeModelConvention(ProviderConventionSetBuilderDependencies dependencies)
: base(dependencies)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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.Internal;

/// <summary>
Expand All @@ -17,8 +19,7 @@ public class CosmosConventionSetBuilder : ProviderConventionSetBuilder
/// 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 CosmosConventionSetBuilder(
ProviderConventionSetBuilderDependencies dependencies)
public CosmosConventionSetBuilder(ProviderConventionSetBuilderDependencies dependencies)
: base(dependencies)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ private static void ProcessIdProperty(IConventionEntityTypeBuilder entityTypeBui

if (idProperty != null)
{
if (idProperty.ClrType == typeof(string))
var converter = idProperty.GetValueConverter();
if ((converter == null ? idProperty.ClrType : converter.ProviderClrType) == typeof(string))
{
if (idProperty.IsPrimaryKey())
{
Expand Down
16 changes: 16 additions & 0 deletions src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,20 @@ public static class CosmosAnnotationNames
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public const string Throughput = Prefix + "Throughput";

/// <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 const string JsonIdDefinition = Prefix + "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 const string ModelDependencies = Prefix + "ModelDependencies";
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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.Infrastructure.Internal;

namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;

/// <summary>
Expand All @@ -21,4 +23,15 @@ public static bool IsDocumentRoot(this IReadOnlyEntityType entityType)
=> entityType.BaseType?.IsDocumentRoot()
?? (entityType.FindOwnership() == null
|| entityType[CosmosAnnotationNames.ContainerName] != null);

/// <summary>
/// Returns the JSON `id` definition, or <see langword="null"/> if there is none.
/// </summary>
/// <param name="entityType">The entity type.</param>
public static IJsonIdDefinition? GetJsonIdDefinition(this IEntityType entityType)
=> entityType.GetOrAddRuntimeAnnotationValue(CosmosAnnotationNames.JsonIdDefinition,
static e =>
((CosmosModelRuntimeInitializerDependencies)e!.Model.FindRuntimeAnnotationValue(
CosmosAnnotationNames.ModelDependencies)!).JsonIdDefinitionFactory.Create(e),
entityType);
}
37 changes: 37 additions & 0 deletions src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 IJsonIdDefinition
{
/// <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>
IReadOnlyList<IProperty> 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>
string GenerateIdString(EntityEntry entry);

/// <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>
string GenerateIdString(IEnumerable<object?> values);
}
21 changes: 21 additions & 0 deletions src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinitionFactory.cs
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 IJsonIdDefinitionFactory
{
/// <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>
IJsonIdDefinition? Create(IEntityType entityType);
}
Loading