-
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.
Deprecate defining query at Core level
Fixes #18903
- Loading branch information
1 parent
94452ca
commit 66bb342
Showing
39 changed files
with
452 additions
and
161 deletions.
There are no files selected for viewing
77 changes: 77 additions & 0 deletions
77
src/EFCore.InMemory/Extensions/InMemoryEntityTypeBuilderExtensions.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,77 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
using JetBrains.Annotations; | ||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | ||
using Microsoft.EntityFrameworkCore.Metadata.Internal; | ||
using Microsoft.EntityFrameworkCore.Utilities; | ||
|
||
// ReSharper disable once CheckNamespace | ||
namespace Microsoft.EntityFrameworkCore | ||
{ | ||
/// <summary> | ||
/// Extension methods for <see cref="EntityTypeBuilder" /> for the in-memory provider. | ||
/// </summary> | ||
public static class InMemoryEntityTypeBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Configures a query used to provide data for an entity type. | ||
/// </summary> | ||
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param> | ||
/// <param name="query"> The query that will provide the underlying data for the entity type. </param> | ||
/// <returns> The same builder instance so that multiple calls can be chained. </returns> | ||
public static EntityTypeBuilder<TEntity> ToQuery<TEntity>( | ||
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder, | ||
[NotNull] Expression<Func<IQueryable<TEntity>>> query) | ||
where TEntity : class | ||
{ | ||
Check.NotNull(query, nameof(query)); | ||
|
||
InMemoryEntityTypeExtensions.SetDefiningQuery(entityTypeBuilder.Metadata, query); | ||
|
||
return entityTypeBuilder; | ||
} | ||
|
||
/// <summary> | ||
/// Configures a query used to provide data for an entity type. | ||
/// </summary> | ||
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param> | ||
/// <param name="query"> The query that will provide the underlying data for the entity type. </param> | ||
/// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> | ||
/// <returns> | ||
/// The same builder instance if the query was set, <see langword="null" /> otherwise. | ||
/// </returns> | ||
public static IConventionEntityTypeBuilder HasDefiningQuery( | ||
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, | ||
[CanBeNull] LambdaExpression query, | ||
bool fromDataAnnotation = false) | ||
{ | ||
if (CanSetDefiningQuery(entityTypeBuilder, query, fromDataAnnotation)) | ||
{ | ||
InMemoryEntityTypeExtensions.SetDefiningQuery(entityTypeBuilder.Metadata, query, fromDataAnnotation); | ||
|
||
return entityTypeBuilder; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Returns a value indicating whether the given defining query can be set from the current configuration source. | ||
/// </summary> | ||
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param> | ||
/// <param name="query"> The query that will provide the underlying data for the keyless entity type. </param> | ||
/// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> | ||
/// <returns> <see langword="true" /> if the given defining query can be set. </returns> | ||
public static bool CanSetDefiningQuery( | ||
[NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, | ||
[CanBeNull] LambdaExpression query, | ||
bool fromDataAnnotation = false) | ||
#pragma warning disable EF1001 // Internal EF Core API usage. | ||
=> entityTypeBuilder.CanSetAnnotation(CoreAnnotationNames.DefiningQuery, query, fromDataAnnotation); | ||
#pragma warning restore EF1001 // Internal EF Core API usage. | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
src/EFCore.InMemory/Extensions/InMemoryEntityTypeExtensions.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,68 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Linq.Expressions; | ||
using JetBrains.Annotations; | ||
using Microsoft.EntityFrameworkCore.Metadata; | ||
using Microsoft.EntityFrameworkCore.Metadata.Internal; | ||
using Microsoft.EntityFrameworkCore.Utilities; | ||
|
||
// ReSharper disable once CheckNamespace | ||
namespace Microsoft.EntityFrameworkCore | ||
{ | ||
/// <summary> | ||
/// Extension methods for <see cref="IEntityType" /> for the in-memory provider. | ||
/// </summary> | ||
public static class InMemoryEntityTypeExtensions | ||
{ | ||
/// <summary> | ||
/// Gets the LINQ query used as the default source for queries of this type. | ||
/// </summary> | ||
/// <param name="entityType"> The entity type to get the defining query for. </param> | ||
/// <returns> The LINQ query used as the default source. </returns> | ||
public static LambdaExpression GetDefiningQuery([NotNull] this IEntityType entityType) | ||
#pragma warning disable EF1001 // Internal EF Core API usage. | ||
=> (LambdaExpression)Check.NotNull(entityType, nameof(entityType))[CoreAnnotationNames.DefiningQuery]; | ||
#pragma warning restore EF1001 // Internal EF Core API usage. | ||
|
||
/// <summary> | ||
/// Sets the LINQ query used as the default source for queries of this type. | ||
/// </summary> | ||
/// <param name="entityType"> The entity type. </param> | ||
/// <param name="definingQuery"> The LINQ query used as the default source. </param> | ||
public static void SetDefiningQuery( | ||
[NotNull] this IMutableEntityType entityType, | ||
[CanBeNull] LambdaExpression definingQuery) | ||
=> Check.NotNull(entityType, nameof(entityType)) | ||
#pragma warning disable EF1001 // Internal EF Core API usage. | ||
.SetOrRemoveAnnotation(CoreAnnotationNames.DefiningQuery, definingQuery); | ||
#pragma warning restore EF1001 // Internal EF Core API usage. | ||
|
||
/// <summary> | ||
/// Sets the LINQ query used as the default source for queries of this type. | ||
/// </summary> | ||
/// <param name="entityType"> The entity type. </param> | ||
/// <param name="definingQuery"> The LINQ query used as the default source. </param> | ||
/// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> | ||
/// <returns> The configured entity type. </returns> | ||
public static LambdaExpression SetDefiningQuery( | ||
[NotNull] this IConventionEntityType entityType, | ||
[CanBeNull] LambdaExpression definingQuery, | ||
bool fromDataAnnotation = false) | ||
=> (LambdaExpression)Check.NotNull(entityType, nameof(entityType)) | ||
#pragma warning disable EF1001 // Internal EF Core API usage. | ||
.SetOrRemoveAnnotation(CoreAnnotationNames.DefiningQuery, definingQuery, fromDataAnnotation) | ||
#pragma warning restore EF1001 // Internal EF Core API usage. | ||
?.Value; | ||
|
||
/// <summary> | ||
/// Returns the configuration source for <see cref="EntityTypeExtensions.GetDefiningQuery" />. | ||
/// </summary> | ||
/// <param name="entityType"> The entity type. </param> | ||
/// <returns> The configuration source for <see cref="EntityTypeExtensions.GetDefiningQuery" />. </returns> | ||
public static ConfigurationSource? GetDefiningQueryConfigurationSource([NotNull] this IConventionEntityType entityType) | ||
#pragma warning disable EF1001 // Internal EF Core API usage. | ||
=> entityType.FindAnnotation(CoreAnnotationNames.DefiningQuery)?.GetConfigurationSource(); | ||
#pragma warning restore EF1001 // Internal EF Core API usage. | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using JetBrains.Annotations; | ||
using Microsoft.EntityFrameworkCore.Diagnostics; | ||
using Microsoft.EntityFrameworkCore.Infrastructure; | ||
using Microsoft.EntityFrameworkCore.Metadata; | ||
using Microsoft.EntityFrameworkCore.Utilities; | ||
|
||
namespace Microsoft.EntityFrameworkCore.InMemory.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 InMemoryModelValidator : ModelValidator | ||
{ | ||
/// <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 InMemoryModelValidator([NotNull] ModelValidatorDependencies dependencies) | ||
: base(dependencies) | ||
{ | ||
} | ||
|
||
/// <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 override void Validate(IModel model, IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger) | ||
{ | ||
base.Validate(model, logger); | ||
|
||
ValidateDefiningQuery(model, logger); | ||
} | ||
|
||
/// <summary> | ||
/// Validates the configuration of defining queries in the model. | ||
/// </summary> | ||
/// <param name="model"> The model to validate. </param> | ||
/// <param name="logger"> The logger to use. </param> | ||
protected virtual void ValidateDefiningQuery( | ||
[NotNull] IModel model, [NotNull] IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger) | ||
{ | ||
Check.NotNull(model, nameof(model)); | ||
|
||
foreach (var entityType in model.GetEntityTypes()) | ||
{ | ||
if (InMemoryEntityTypeExtensions.GetDefiningQuery(entityType) != null) | ||
{ | ||
if (entityType.BaseType != null) | ||
{ | ||
throw new InvalidOperationException( | ||
CoreStrings.DerivedTypeDefiningQuery(entityType.DisplayName(), entityType.BaseType.DisplayName())); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
src/EFCore.InMemory/Metadata/Conventions/DefiningQueryRewritingConvention.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,44 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Linq.Expressions; | ||
using JetBrains.Annotations; | ||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | ||
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; | ||
using Microsoft.EntityFrameworkCore.Query; | ||
|
||
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions | ||
{ | ||
/// <summary> | ||
/// Convention that converts accesses of <see cref="DbSet{TEntity}"/> inside query filters and defining queries into <see cref="QueryRootExpression"/>. | ||
/// This makes them consistent with how DbSet accesses in the actual queries are represented, which allows for easier processing in the | ||
/// query pipeline. | ||
/// </summary> | ||
public class DefiningQueryRewritingConvention : QueryFilterRewritingConvention | ||
{ | ||
/// <summary> | ||
/// Creates a new instance of <see cref="QueryFilterRewritingConvention" />. | ||
/// </summary> | ||
/// <param name="dependencies"> Parameter object containing dependencies for this convention. </param> | ||
public DefiningQueryRewritingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) | ||
: base(dependencies) | ||
{ | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override void ProcessModelFinalizing( | ||
IConventionModelBuilder modelBuilder, | ||
IConventionContext<IConventionModelBuilder> context) | ||
{ | ||
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) | ||
{ | ||
var definingQuery = InMemoryEntityTypeExtensions.GetDefiningQuery(entityType); | ||
if (definingQuery != null) | ||
{ | ||
InMemoryEntityTypeExtensions.SetDefiningQuery( | ||
entityType, (LambdaExpression)DbSetAccessRewriter.Rewrite(modelBuilder.Metadata, definingQuery)); | ||
} | ||
} | ||
} | ||
} | ||
} |
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
Oops, something went wrong.