diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs
index 30a21325e34..110ae9e1692 100644
--- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs
+++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs
@@ -3,10 +3,7 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
// ReSharper disable once CheckNamespace
@@ -18,36 +15,150 @@ namespace Microsoft.EntityFrameworkCore
public static class CosmosEntityTypeBuilderExtensions
{
///
- /// Configures the container that the entity maps to when targeting Azure Cosmos.
+ /// Configures the container that the entity type maps to when targeting Azure Cosmos.
///
/// The builder for the entity type being configured.
/// The name of the container.
/// The same builder instance so that multiple calls can be chained.
- public static EntityTypeBuilder ToContainer(
+ public static EntityTypeBuilder ForCosmosToContainer(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name)
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
Check.NullButNotEmpty(name, nameof(name));
- entityTypeBuilder.GetInfrastructure()
- .Cosmos(ConfigurationSource.Explicit)
- .ToContainer(name);
+ entityTypeBuilder.Metadata.SetCosmosContainerName(name);
return entityTypeBuilder;
}
///
- /// Configures the container that the entity maps to when targeting Azure Cosmos.
+ /// Configures the container that the entity type maps to when targeting Azure Cosmos.
///
/// The entity type being configured.
/// The builder for the entity type being configured.
/// The name of the container.
/// The same builder instance so that multiple calls can be chained.
- public static EntityTypeBuilder ToContainer(
+ public static EntityTypeBuilder ForCosmosToContainer(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name)
where TEntity : class
- => (EntityTypeBuilder)ToContainer((EntityTypeBuilder)entityTypeBuilder, name);
+ => (EntityTypeBuilder)ForCosmosToContainer((EntityTypeBuilder)entityTypeBuilder, name);
+
+ ///
+ /// Configures the container that the entity type maps to when targeting Azure Cosmos.
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the container.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// null otherwise.
+ ///
+ public static IConventionEntityTypeBuilder ForCosmosToContainer(
+ [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ {
+ if (!entityTypeBuilder.ForCosmosCanSetContainer(name, fromDataAnnotation))
+ {
+ return null;
+ }
+
+ entityTypeBuilder.Metadata.SetCosmosContainerName(name, fromDataAnnotation);
+
+ return entityTypeBuilder;
+ }
+
+ ///
+ /// Returns a value indicating whether the container that the entity type maps to can be set
+ /// from the current configuration source
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the container.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// true if the configuration can be applied.
+ public static bool ForCosmosCanSetContainer(
+ [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
+ {
+ Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
+ Check.NullButNotEmpty(name, nameof(name));
+
+ return entityTypeBuilder.CanSetAnnotation(CosmosAnnotationNames.ContainerName, name, fromDataAnnotation);
+ }
+
+ ///
+ /// Configures the property name that the entity is mapped to when stored as an embedded document.
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the parent property.
+ /// The same builder instance so that multiple calls can be chained.
+ public static OwnedNavigationBuilder ForCosmosToProperty(
+ [NotNull] this OwnedNavigationBuilder entityTypeBuilder,
+ [CanBeNull] string name)
+ {
+ entityTypeBuilder.OwnedEntityType.SetCosmosContainingPropertyName(name);
+
+ return entityTypeBuilder;
+ }
+
+ ///
+ /// Configures the property name that the entity is mapped to when stored as an embedded document.
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the parent property.
+ /// The same builder instance so that multiple calls can be chained.
+ public static OwnedNavigationBuilder ForCosmosToProperty(
+ [NotNull] this OwnedNavigationBuilder entityTypeBuilder,
+ [CanBeNull] string name)
+ where TEntity : class
+ where TDependentEntity : class
+ {
+ entityTypeBuilder.OwnedEntityType.SetCosmosContainingPropertyName(name);
+
+ return entityTypeBuilder;
+ }
+
+ ///
+ /// Configures the property name that the entity is mapped to when stored as an embedded document.
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the parent property.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// null otherwise.
+ ///
+ public static IConventionEntityTypeBuilder ForCosmosToProperty(
+ [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ {
+ if (!entityTypeBuilder.ForCosmosCanSetProperty(name, fromDataAnnotation))
+ {
+ return null;
+ }
+
+ entityTypeBuilder.Metadata.SetCosmosContainingPropertyName(name, fromDataAnnotation);
+
+ return entityTypeBuilder;
+ }
+
+ ///
+ /// Returns a value indicating whether the parent property name to which the entity type is mapped to can be set
+ /// from the current configuration source
+ ///
+ /// The builder for the entity type being configured.
+ /// The name of the parent property.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// true if the configuration can be applied.
+ public static bool ForCosmosCanSetProperty(
+ [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
+ {
+ Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
+ Check.NullButNotEmpty(name, nameof(name));
+
+ return entityTypeBuilder.CanSetAnnotation(CosmosAnnotationNames.PropertyName, name, fromDataAnnotation);
+ }
}
}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs
new file mode 100644
index 00000000000..0d4aeadf2f6
--- /dev/null
+++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs
@@ -0,0 +1,108 @@
+// 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 JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Utilities;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore
+{
+ ///
+ /// Extension methods for for Cosmos metadata.
+ ///
+ public static class CosmosEntityTypeExtensions
+ {
+ ///
+ /// Returns the name of the container to which the entity type is mapped.
+ ///
+ /// The entity type to get the container name for.
+ /// The name of the container to which the entity type is mapped.
+ public static string GetCosmosContainerName([NotNull] this IEntityType entityType) =>
+ entityType.BaseType != null
+ ? entityType.RootType().GetCosmosContainerName()
+ : (string)entityType[CosmosAnnotationNames.ContainerName]
+ ?? GetCosmosDefaultContainerName(entityType);
+
+ private static string GetCosmosDefaultContainerName(IEntityType entityType)
+ => entityType.Model.GetCosmosDefaultContainerName()
+ ?? entityType.ShortName();
+
+ ///
+ /// Sets the name of the container to which the entity type is mapped.
+ ///
+ /// The entity type to set the container name for.
+ /// The name to set.
+ public static void SetCosmosContainerName([NotNull] this IMutableEntityType entityType, [CanBeNull] string name)
+ => entityType.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.ContainerName,
+ Check.NullButNotEmpty(name, nameof(name)));
+
+ ///
+ /// Sets the name of the container to which the entity type is mapped.
+ ///
+ /// The entity type to set the container name for.
+ /// The name to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetCosmosContainerName(
+ [NotNull] this IConventionEntityType entityType, [CanBeNull] string name, bool fromDataAnnotation = false)
+ => entityType.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.ContainerName,
+ Check.NullButNotEmpty(name, nameof(name)),
+ fromDataAnnotation);
+
+ ///
+ /// Gets the for the container to which the entity type is mapped.
+ ///
+ /// The entity type to find configuration source for.
+ /// The for the container to which the entity type is mapped.
+ public static ConfigurationSource? GetCosmosContainerNameConfigurationSource([NotNull] this IConventionEntityType entityType)
+ => entityType.FindAnnotation(CosmosAnnotationNames.ContainerName)
+ ?.GetConfigurationSource();
+
+ ///
+ /// Returns the name of the parent property to which the entity type is mapped.
+ ///
+ /// The entity type to get the containing property name for.
+ /// The name of the parent property to which the entity type is mapped.
+ public static string GetCosmosContainingPropertyName([NotNull] this IEntityType entityType) =>
+ entityType[CosmosAnnotationNames.PropertyName] as string
+ ?? GetDefaultContainingPropertyName(entityType);
+
+ private static string GetDefaultContainingPropertyName(IEntityType entityType)
+ => entityType.FindOwnership()?.PrincipalToDependent.Name;
+
+ ///
+ /// Sets the name of the parent property to which the entity type is mapped.
+ ///
+ /// The entity type to set the containing property name for.
+ /// The name to set.
+ public static void SetCosmosContainingPropertyName([NotNull] this IMutableEntityType entityType, [CanBeNull] string name)
+ => entityType.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.PropertyName,
+ Check.NullButNotEmpty(name, nameof(name)));
+
+ ///
+ /// Sets the name of the parent property to which the entity type is mapped.
+ ///
+ /// The entity type to set the containing property name for.
+ /// The name to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetCosmosContainingPropertyName(
+ [NotNull] this IConventionEntityType entityType, [CanBeNull] string name, bool fromDataAnnotation = false)
+ => entityType.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.PropertyName,
+ Check.NullButNotEmpty(name, nameof(name)),
+ fromDataAnnotation);
+
+ ///
+ /// Gets the for the parent property to which the entity type is mapped.
+ ///
+ /// The entity type to find configuration source for.
+ /// The for the parent property to which the entity type is mapped.
+ public static ConfigurationSource? GetCosmosContainingPropertyNameConfigurationSource([NotNull] this IConventionEntityType entityType)
+ => entityType.FindAnnotation(CosmosAnnotationNames.PropertyName)
+ ?.GetConfigurationSource();
+ }
+}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosMetadataExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosMetadataExtensions.cs
deleted file mode 100644
index 2c738df771c..00000000000
--- a/src/EFCore.Cosmos/Extensions/CosmosMetadataExtensions.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 Microsoft.EntityFrameworkCore.Cosmos.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata;
-
-namespace Microsoft.EntityFrameworkCore
-{
- ///
- /// Cosmos-specific extension methods for metadata.
- ///
- public static class CosmosMetadataExtensions
- {
- ///
- /// Gets the Cosmos-specific metadata for a model.
- ///
- /// The model to get metadata for.
- /// The Cosmos-specific metadata for the model.
- public static ICosmosModelAnnotations Cosmos(this IModel model)
- => new CosmosModelAnnotations(model);
-
- ///
- /// Gets the Cosmos-specific metadata for a model.
- ///
- /// The model to get metadata for.
- /// The Cosmos-specific metadata for the model.
- public static CosmosModelAnnotations Cosmos(this IMutableModel model)
- => (CosmosModelAnnotations)Cosmos((IModel)model);
-
- ///
- /// Gets the Cosmos-specific metadata for an entity type.
- ///
- /// The entity type to get metadata for.
- /// The Cosmos-specific metadata for the entity type.
- public static ICosmosEntityTypeAnnotations Cosmos(this IEntityType entityType)
- => new CosmosEntityTypeAnnotations(entityType);
-
- ///
- /// Gets the Cosmos-specific metadata for an entity type.
- ///
- /// The entity type to get metadata for.
- /// The Cosmos-specific metadata for the entity type.
- public static CosmosEntityTypeAnnotations Cosmos(this IMutableEntityType entityType)
- => (CosmosEntityTypeAnnotations)Cosmos((IEntityType)entityType);
-
- ///
- /// Gets the Cosmos-specific metadata for a property.
- ///
- /// The property to get metadata for.
- /// The Cosmos-specific metadata for the property.
- public static ICosmosPropertyAnnotations Cosmos(this IProperty property)
- => new CosmosPropertyAnnotations(property);
-
- ///
- /// Gets the Cosmos-specific metadata for a property.
- ///
- /// The property to get metadata for.
- /// The Cosmos-specific metadata for the property.
- public static CosmosPropertyAnnotations Cosmos(this IMutableProperty property)
- => (CosmosPropertyAnnotations)Cosmos((IProperty)property);
- }
-}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs
index fad46c19a50..5b3789e487a 100644
--- a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs
+++ b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs
@@ -3,8 +3,7 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Utilities;
// ReSharper disable once CheckNamespace
@@ -22,16 +21,60 @@ public static class CosmosModelBuilderExtensions
/// The model builder.
/// The default container name.
/// The same builder instance so that multiple calls can be chained.
- public static ModelBuilder HasDefaultContainerName(
+ public static ModelBuilder ForCosmosHasDefaultContainerName(
[NotNull] this ModelBuilder modelBuilder,
[CanBeNull] string name)
{
Check.NotNull(modelBuilder, nameof(modelBuilder));
Check.NullButNotEmpty(name, nameof(name));
- modelBuilder.GetInfrastructure().Cosmos(ConfigurationSource.Explicit).HasDefaultContainerName(name);
+ modelBuilder.Model.SetCosmosDefaultContainerName(name);
return modelBuilder;
}
+
+ ///
+ /// Configures the default container name that will be used if no name
+ /// is explicitly configured for an entity type.
+ ///
+ /// The model builder.
+ /// The default container name.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// null otherwise.
+ ///
+ public static IConventionModelBuilder ForCosmosHasDefaultContainerName(
+ [NotNull] this IConventionModelBuilder modelBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ {
+ if (modelBuilder.ForCosmosCanSetDefaultContainerName(name, fromDataAnnotation))
+ {
+ return null;
+ }
+
+ modelBuilder.Metadata.SetCosmosDefaultContainerName(name, fromDataAnnotation);
+
+ return modelBuilder;
+ }
+
+ ///
+ /// Returns a value indicating whether the given schema can be set as default.
+ ///
+ /// The model builder.
+ /// The default container name.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// true if the given container name can be set as default.
+ public static bool ForCosmosCanSetDefaultContainerName(
+ [NotNull] this IConventionModelBuilder modelBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ {
+ Check.NotNull(modelBuilder, nameof(modelBuilder));
+ Check.NullButNotEmpty(name, nameof(name));
+
+ return modelBuilder.CanSetAnnotation(CosmosAnnotationNames.ContainerName, name, fromDataAnnotation);
+ }
}
}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs
new file mode 100644
index 00000000000..2c6f0588082
--- /dev/null
+++ b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs
@@ -0,0 +1,55 @@
+// 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 JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Utilities;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore
+{
+ ///
+ /// Extension methods for for Cosmos metadata.
+ ///
+ public static class CosmosModelExtensions
+ {
+ ///
+ /// Returns the default container name.
+ ///
+ /// The model.
+ /// The default container name.
+ public static string GetCosmosDefaultContainerName([NotNull] this IModel model)
+ => (string)model[CosmosAnnotationNames.ContainerName];
+
+ ///
+ /// Sets the default container name.
+ ///
+ /// The model.
+ /// The name to set.
+ public static void SetCosmosDefaultContainerName([NotNull] this IMutableModel model, [CanBeNull] string name)
+ => model.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.ContainerName,
+ Check.NullButNotEmpty(name, nameof(name)));
+
+ ///
+ /// Sets the default container name.
+ ///
+ /// The model.
+ /// The name to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetCosmosDefaultContainerName([NotNull] this IConventionModel model, [CanBeNull] string name, bool fromDataAnnotation = false)
+ => model.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.ContainerName,
+ Check.NullButNotEmpty(name, nameof(name)),
+ fromDataAnnotation);
+
+ ///
+ /// Returns the configuration source for the default container name.
+ ///
+ /// The model.
+ /// The configuration source for the default container name.
+ public static ConfigurationSource? GetCosmosDefaultContainerNameConfigurationSource([NotNull] this IConventionModel model)
+ => model.FindAnnotation(CosmosAnnotationNames.ContainerName)?.GetConfigurationSource();
+ }
+}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosOwnedNavigationBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosOwnedNavigationBuilderExtensions.cs
deleted file mode 100644
index 25f2a4da665..00000000000
--- a/src/EFCore.Cosmos/Extensions/CosmosOwnedNavigationBuilderExtensions.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Builders;
-
-// ReSharper disable once CheckNamespace
-namespace Microsoft.EntityFrameworkCore
-{
- ///
- /// Cosmos-specific extension methods for .
- ///
- public static class CosmosOwnedNavigationBuilderExtensions
- {
- ///
- /// Configures the property name that the entity is mapped to when stored as an embedded document.
- ///
- /// If an empty string is supplied then the property will not be persisted.
- /// The builder for the entity type being configured.
- /// The name of the container.
- /// The same builder instance so that multiple calls can be chained.
- public static OwnedNavigationBuilder ToProperty(
- [NotNull] this OwnedNavigationBuilder entityTypeBuilder,
- [CanBeNull] string name)
- {
- entityTypeBuilder.GetInfrastructure()
- .Cosmos(ConfigurationSource.Explicit)
- .ToProperty(name);
-
- return entityTypeBuilder;
- }
-
- ///
- /// Configures the property name that the entity is mapped to when stored as an embedded document.
- ///
- /// If an empty string is supplied then the property will not be persisted.
- /// The builder for the entity type being configured.
- /// The name of the container.
- /// The same builder instance so that multiple calls can be chained.
- public static OwnedNavigationBuilder ToProperty(
- [NotNull] this OwnedNavigationBuilder entityTypeBuilder,
- [CanBeNull] string name)
- where TEntity : class
- where TDependentEntity : class
- {
- entityTypeBuilder.GetInfrastructure()
- .Cosmos(ConfigurationSource.Explicit)
- .ToProperty(name);
-
- return entityTypeBuilder;
- }
- }
-}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs
index 7e5e2a08a17..488914db29a 100644
--- a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs
+++ b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs
@@ -3,12 +3,11 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Utilities;
-namespace Microsoft.EntityFrameworkCore.Cosmos
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore
{
///
/// Cosmos-specific extension methods for .
@@ -22,14 +21,16 @@ public static class CosmosPropertyBuilderExtensions
/// The builder for the property being configured.
/// The name of the container.
/// The same builder instance so that multiple calls can be chained.
- public static PropertyBuilder ToProperty(
+ public static PropertyBuilder ForCosmosToProperty(
[NotNull] this PropertyBuilder propertyBuilder,
[CanBeNull] string name)
- => propertyBuilder.GetInfrastructure()
- .Cosmos(ConfigurationSource.Explicit)
- .ToProperty(name)
- ? propertyBuilder
- : propertyBuilder;
+ {
+ Check.NotNull(propertyBuilder, nameof(propertyBuilder));
+
+ propertyBuilder.Metadata.SetCosmosPropertyName(name);
+
+ return propertyBuilder;
+ }
///
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
@@ -39,9 +40,52 @@ public static PropertyBuilder ToProperty(
/// The builder for the property being configured.
/// The name of the container.
/// The same builder instance so that multiple calls can be chained.
- public static PropertyBuilder ToProperty(
+ public static PropertyBuilder ForCosmosToProperty(
[NotNull] this PropertyBuilder propertyBuilder,
[CanBeNull] string name)
- => (PropertyBuilder)ToProperty((PropertyBuilder)propertyBuilder, name);
+ => (PropertyBuilder)ForCosmosToProperty((PropertyBuilder)propertyBuilder, name);
+
+ ///
+ ///
+ /// Configures the property name that the property is mapped to when targeting Azure Cosmos.
+ ///
+ ///
+ /// If an empty string is supplied then the property will not be persisted.
+ ///
+ ///
+ /// The builder for the property being configured.
+ /// The name of the container.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// null otherwise.
+ ///
+ public static IConventionPropertyBuilder ForCosmosToProperty(
+ [NotNull] this IConventionPropertyBuilder propertyBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ {
+ if (!propertyBuilder.ForCosmosCanSetProperty(name, fromDataAnnotation))
+ {
+ return null;
+ }
+
+ propertyBuilder.Metadata.SetCosmosPropertyName(name, fromDataAnnotation);
+
+ return propertyBuilder;
+ }
+
+ ///
+ /// Returns a value indicating whether the given property name can be set.
+ ///
+ /// The builder for the property being configured.
+ /// The name of the container.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// true if the property name can be set.
+ public static bool ForCosmosCanSetProperty(
+ [NotNull] this IConventionPropertyBuilder propertyBuilder,
+ [CanBeNull] string name,
+ bool fromDataAnnotation = false)
+ => propertyBuilder.CanSetAnnotation(CosmosAnnotationNames.PropertyName, name, fromDataAnnotation);
}
}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs
new file mode 100644
index 00000000000..39e156405a3
--- /dev/null
+++ b/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs
@@ -0,0 +1,55 @@
+// 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 JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore
+{
+ ///
+ /// Extension methods for for Cosmos metadata.
+ ///
+ public static class CosmosPropertyExtensions
+ {
+ ///
+ /// Returns the property name used when targeting Cosmos.
+ ///
+ /// The property.
+ /// The property name used when targeting Cosmos.
+ public static string GetCosmosPropertyName([NotNull] this IProperty property) =>
+ (string)property[CosmosAnnotationNames.PropertyName]
+ ?? property.Name;
+
+ ///
+ /// Sets the property name used when targeting Cosmos.
+ ///
+ /// The property.
+ /// The name to set.
+ public static void SetCosmosPropertyName([NotNull] this IMutableProperty property, [CanBeNull] string name)
+ => property.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.PropertyName,
+ name);
+
+ ///
+ /// Sets the property name used when targeting Cosmos.
+ ///
+ /// The property.
+ /// The name to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetCosmosPropertyName([NotNull] this IConventionProperty property, [CanBeNull] string name, bool fromDataAnnotation = false)
+ => property.SetOrRemoveAnnotation(
+ CosmosAnnotationNames.PropertyName,
+ name,
+ fromDataAnnotation);
+
+ ///
+ /// Gets the for the property name used when targeting Cosmos.
+ ///
+ /// The property.
+ /// The for the property name used when targeting Cosmos.
+ public static ConfigurationSource? GetCosmosPropertyNameConfigurationSource([NotNull] this IConventionProperty property)
+ => property.FindAnnotation(CosmosAnnotationNames.PropertyName)?.GetConfigurationSource();
+ }
+}
diff --git a/src/EFCore.Cosmos/Infrastructure/CosmosModelCustomizer.cs b/src/EFCore.Cosmos/Infrastructure/CosmosModelCustomizer.cs
index a8b96594461..bb519e5fab4 100644
--- a/src/EFCore.Cosmos/Infrastructure/CosmosModelCustomizer.cs
+++ b/src/EFCore.Cosmos/Infrastructure/CosmosModelCustomizer.cs
@@ -1,7 +1,6 @@
// 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 Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
@@ -39,7 +38,7 @@ public CosmosModelCustomizer(ModelCustomizerDependencies dependencies)
///
public override void Customize(ModelBuilder modelBuilder, DbContext context)
{
- modelBuilder.GetInfrastructure().Cosmos(ConfigurationSource.Convention).HasDefaultContainerName(context.GetType().Name);
+ ((IConventionModel)modelBuilder.Model).Builder.ForCosmosHasDefaultContainerName(context.GetType().Name);
base.Customize(modelBuilder, context);
}
diff --git a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs
index d6741c7c019..47eae27b83d 100644
--- a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs
+++ b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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 JetBrains.Annotations;
@@ -20,13 +20,15 @@ public override ConventionSet CreateConventionSet()
{
var conventionSet = base.CreateConventionSet();
- var discriminatorConvention = new DiscriminatorConvention();
+ var discriminatorConvention = new CosmosDiscriminatorConvention(Dependencies.Logger);
var storeKeyConvention = new StoreKeyConvention();
conventionSet.EntityTypeAddedConventions.Add(storeKeyConvention);
conventionSet.EntityTypeAddedConventions.Add(discriminatorConvention);
+ ReplaceConvention(conventionSet.EntityTypeRemovedConventions, (DiscriminatorConvention)discriminatorConvention);
+
conventionSet.BaseEntityTypeChangedConventions.Add(storeKeyConvention);
- conventionSet.BaseEntityTypeChangedConventions.Add(discriminatorConvention);
+ ReplaceConvention(conventionSet.BaseEntityTypeChangedConventions, (DiscriminatorConvention)discriminatorConvention);
conventionSet.ForeignKeyOwnershipChangedConventions.Add(storeKeyConvention);
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationsBuilder.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosDiscriminatorConvention.cs
similarity index 52%
rename from src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationsBuilder.cs
rename to src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosDiscriminatorConvention.cs
index 00a7c2f1eec..779570cc2af 100644
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationsBuilder.cs
+++ b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosDiscriminatorConvention.cs
@@ -1,11 +1,14 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Internal;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
+namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions.Internal
{
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -13,7 +16,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
/// 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.
///
- public class CosmosAnnotationsBuilder : CosmosAnnotations
+ public class CosmosDiscriminatorConvention : DiscriminatorConvention, IEntityTypeAddedConvention
{
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -21,13 +24,9 @@ public class CosmosAnnotationsBuilder : CosmosAnnotations
/// 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.
///
- public CosmosAnnotationsBuilder(
- [NotNull] InternalAnnotatableBuilder internalBuilder,
- ConfigurationSource configurationSource)
- : base(internalBuilder.Metadata)
+ public CosmosDiscriminatorConvention([NotNull] IDiagnosticsLogger logger)
+ : base(logger)
{
- MetadataBuilder = internalBuilder;
- ConfigurationSource = configurationSource;
}
///
@@ -36,15 +35,18 @@ public CosmosAnnotationsBuilder(
/// 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.
///
- public virtual ConfigurationSource ConfigurationSource { get; }
+ public InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
+ {
+ var entityType = entityTypeBuilder.Metadata;
+ if (entityTypeBuilder.Metadata.BaseType == null
+ && !entityTypeBuilder.Metadata.GetDerivedTypes().Any())
+ {
+ ((IConventionEntityTypeBuilder)entityTypeBuilder).HasDiscriminator(typeof(string))
+ .HasValue(entityType, entityType.ShortName());
+ }
- ///
- /// 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.
- ///
- public virtual InternalAnnotatableBuilder MetadataBuilder { get; }
+ return entityTypeBuilder;
+ }
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -52,21 +54,33 @@ public CosmosAnnotationsBuilder(
/// 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.
///
- public override bool SetAnnotation(
- string relationalAnnotationName,
- object value)
- => MetadataBuilder.HasAnnotation(relationalAnnotationName, value, ConfigurationSource) != null;
+ public override bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
+ {
+ IConventionEntityTypeBuilder conventionEntityTypeBuilder = entityTypeBuilder;
+ IConventionDiscriminatorBuilder discriminator;
+ var entityType = entityTypeBuilder.Metadata;
+ if (entityType.BaseType == null)
+ {
+ discriminator = conventionEntityTypeBuilder.HasDiscriminator(typeof(string));
+ }
+ else
+ {
+ discriminator = ((IConventionEntityTypeBuilder)entityType.BaseType.Builder)?.HasDiscriminator(typeof(string));
- ///
- /// 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.
- ///
- public override bool CanSetAnnotation(
- string relationalAnnotationName,
- object value)
- => MetadataBuilder.CanSetAnnotation(relationalAnnotationName, value, ConfigurationSource);
+ if (entityType.BaseType.BaseType == null)
+ {
+ discriminator?.HasValue(entityType.BaseType, entityType.BaseType.ShortName());
+ }
+ }
+
+ if (discriminator != null)
+ {
+ discriminator.HasValue(entityTypeBuilder.Metadata, entityTypeBuilder.Metadata.ShortName());
+ SetDefaultDiscriminatorValues(entityType.GetDerivedTypes(), discriminator);
+ }
+
+ return true;
+ }
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -74,7 +88,9 @@ public override bool CanSetAnnotation(
/// 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.
///
- public override bool RemoveAnnotation(string annotationName)
- => MetadataBuilder.RemoveAnnotation(annotationName, ConfigurationSource) != null;
+ public override bool Apply(InternalModelBuilder modelBuilder, EntityType type)
+ {
+ return true;
+ }
}
}
diff --git a/src/EFCore.Cosmos/Metadata/Conventions/Internal/DiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/DiscriminatorConvention.cs
deleted file mode 100644
index 43c2b3d536e..00000000000
--- a/src/EFCore.Cosmos/Metadata/Conventions/Internal/DiscriminatorConvention.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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.Collections.Generic;
-using System.Linq;
-using Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions.Internal
-{
- public class DiscriminatorConvention : IEntityTypeAddedConvention, IBaseTypeChangedConvention
- {
- public InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
- {
- if (entityTypeBuilder.Metadata.BaseType == null
- && !entityTypeBuilder.Metadata.GetDerivedTypes().Any())
- {
- ConfigureDiscriminator(entityTypeBuilder);
- }
-
- return entityTypeBuilder;
- }
-
- public bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
- {
- var entityType = entityTypeBuilder.Metadata;
- if (entityType.BaseType == null)
- {
- ConfigureDiscriminator(entityTypeBuilder);
- SetDefaultDiscriminatorValues(entityType.GetDerivedTypes());
- }
- else
- {
- if (entityType.BaseType.Cosmos().DiscriminatorProperty == null)
- {
- ConfigureDiscriminator(entityType.BaseType.Builder);
- }
-
- entityType.Cosmos().DiscriminatorProperty = null;
- SetDefaultDiscriminatorValues(entityType.GetDerivedTypesInclusive());
- }
-
- return true;
- }
-
- private static void ConfigureDiscriminator(InternalEntityTypeBuilder entityTypeBuilder)
- {
- var propertyBuilder = entityTypeBuilder.Property(typeof(string), "Discriminator", ConfigurationSource.Convention);
- propertyBuilder.IsRequired(true, ConfigurationSource.Convention);
- propertyBuilder.AfterSave(PropertySaveBehavior.Throw, ConfigurationSource.Convention);
- propertyBuilder.HasValueGenerator(
- (_, et) => new DiscriminatorValueGenerator(et.Cosmos().DiscriminatorValue),
- ConfigurationSource.Convention);
-
- var entityType = entityTypeBuilder.Metadata;
-
- entityType.Cosmos().DiscriminatorProperty = propertyBuilder.Metadata;
- entityType.Cosmos().DiscriminatorValue = entityType.ShortName();
- }
-
- private static void SetDefaultDiscriminatorValues(IEnumerable entityTypes)
- {
- foreach (var entityType in entityTypes)
- {
- entityType.Cosmos().DiscriminatorValue = entityType.ShortName();
- }
- }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Conventions/Internal/StoreKeyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/StoreKeyConvention.cs
index 66e279d39dc..4b8a1ce3826 100644
--- a/src/EFCore.Cosmos/Metadata/Conventions/Internal/StoreKeyConvention.cs
+++ b/src/EFCore.Cosmos/Metadata/Conventions/Internal/StoreKeyConvention.cs
@@ -32,7 +32,7 @@ public InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuild
entityTypeBuilder.HasKey(new[] { idProperty.Metadata }, ConfigurationSource.Convention);
var jObjectProperty = entityTypeBuilder.Property(typeof(JObject), JObjectPropertyName, ConfigurationSource.Convention);
- jObjectProperty.Cosmos(ConfigurationSource.Convention).ToProperty("");
+ jObjectProperty.ForCosmosToProperty("");
jObjectProperty.ValueGenerated(ValueGenerated.OnAddOrUpdate, ConfigurationSource.Convention);
}
else
diff --git a/src/EFCore.Cosmos/Metadata/CosmosEntityTypeAnnotations.cs b/src/EFCore.Cosmos/Metadata/CosmosEntityTypeAnnotations.cs
deleted file mode 100644
index 94dc2f4ffda..00000000000
--- a/src/EFCore.Cosmos/Metadata/CosmosEntityTypeAnnotations.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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.Reflection;
-using JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Utilities;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public class CosmosEntityTypeAnnotations : ICosmosEntityTypeAnnotations
- {
- public CosmosEntityTypeAnnotations(IEntityType entityType)
- : this(new CosmosAnnotations(entityType))
- {
- }
-
- protected CosmosEntityTypeAnnotations(CosmosAnnotations annotations) => Annotations = annotations;
-
- protected virtual CosmosAnnotations Annotations { get; }
-
- protected virtual IEntityType EntityType => (IEntityType)Annotations.Metadata;
-
- protected virtual CosmosModelAnnotations GetAnnotations(IModel model)
- => new CosmosModelAnnotations(model);
-
- protected virtual CosmosEntityTypeAnnotations GetAnnotations([NotNull] IEntityType entityType)
- => new CosmosEntityTypeAnnotations(entityType);
-
- public virtual string ContainerName
- {
- get => EntityType.BaseType != null
- ? GetAnnotations(EntityType.RootType()).ContainerName
- : ((string)Annotations.Metadata[CosmosAnnotationNames.ContainerName])
- ?? GetDefaultContainerName();
-
- [param: CanBeNull] set => SetContainerName(value);
- }
-
- private string GetDefaultContainerName() => GetAnnotations(EntityType.Model).DefaultContainerName
- ?? EntityType.ShortName();
-
- protected virtual bool SetContainerName([CanBeNull] string value)
- => Annotations.SetAnnotation(
- CosmosAnnotationNames.ContainerName,
- Check.NullButNotEmpty(value, nameof(value)));
-
- public virtual IProperty DiscriminatorProperty
- {
- get
- {
- if (EntityType.BaseType != null)
- {
- return GetAnnotations(EntityType.RootType()).DiscriminatorProperty;
- }
-
- var propertyName = (string)Annotations.Metadata[CosmosAnnotationNames.DiscriminatorProperty];
-
- return propertyName == null ? null : EntityType.FindProperty(propertyName);
- }
- [param: CanBeNull] set => SetDiscriminatorProperty(value);
- }
-
- protected virtual bool SetDiscriminatorProperty([CanBeNull] IProperty value)
- => SetDiscriminatorProperty(value, DiscriminatorProperty?.ClrType);
-
- protected virtual bool SetDiscriminatorProperty([CanBeNull] IProperty value, [CanBeNull] Type oldDiscriminatorType)
- {
- if (value != null)
- {
- if (EntityType != EntityType.RootType())
- {
- // TODO: Throw an exception
- //throw new InvalidOperationException(
- // RelationalStrings.DiscriminatorPropertyMustBeOnRoot(EntityType.DisplayName()));
- }
-
- if (value.DeclaringEntityType != EntityType)
- {
- // TODO: Throw an exception
- //throw new InvalidOperationException(
- // RelationalStrings.DiscriminatorPropertyNotFound(value.Name, EntityType.DisplayName()));
- }
- }
-
- if (value == null
- || value.ClrType != oldDiscriminatorType)
- {
- foreach (var derivedType in EntityType.GetDerivedTypesInclusive())
- {
- GetAnnotations(derivedType).RemoveDiscriminatorValue();
- }
- }
-
- return Annotations.SetAnnotation(
- CosmosAnnotationNames.DiscriminatorProperty,
- value?.Name);
- }
-
- protected virtual bool RemoveDiscriminatorValue()
- => Annotations.RemoveAnnotation(CosmosAnnotationNames.DiscriminatorValue);
-
- public virtual object DiscriminatorValue
- {
- get => Annotations.Metadata[CosmosAnnotationNames.DiscriminatorValue];
- [param: CanBeNull] set => SetDiscriminatorValue(value);
- }
-
- protected virtual bool SetDiscriminatorValue([CanBeNull] object value)
- {
- if (value != null
- && DiscriminatorProperty == null)
- {
- // TODO: Throw an exception
- //throw new InvalidOperationException(
- // RelationalStrings.NoDiscriminatorForValue(EntityType.DisplayName(), EntityType.RootType().DisplayName()));
- }
-
- if (value != null
- && !DiscriminatorProperty.ClrType.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()))
- {
- // TODO: Throw an exception
- //throw new InvalidOperationException(
- // RelationalStrings.DiscriminatorValueIncompatible(
- // value, DiscriminatorProperty.Name, DiscriminatorProperty.ClrType));
- }
-
- return Annotations.SetAnnotation(CosmosAnnotationNames.DiscriminatorValue, value);
- }
-
- public string ContainingPropertyName
- {
- get => Annotations.Metadata[CosmosAnnotationNames.PropertyName] as string
- ?? GetDefaultContainingPropertyName();
-
- [param: CanBeNull] set => SetPropertyName(value);
- }
-
- private string GetDefaultContainingPropertyName()
- => EntityType.FindOwnership()?.PrincipalToDependent.Name;
-
- protected virtual bool SetPropertyName([CanBeNull] string value)
- => Annotations.SetAnnotation(
- CosmosAnnotationNames.PropertyName,
- Check.NullButNotEmpty(value, nameof(value)));
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/CosmosModelAnnotations.cs b/src/EFCore.Cosmos/Metadata/CosmosModelAnnotations.cs
deleted file mode 100644
index f3e8f98e5d3..00000000000
--- a/src/EFCore.Cosmos/Metadata/CosmosModelAnnotations.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Utilities;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public class CosmosModelAnnotations : ICosmosModelAnnotations
- {
- public CosmosModelAnnotations(IModel model)
- : this(new CosmosAnnotations(model))
- {
- }
-
- protected CosmosModelAnnotations(CosmosAnnotations annotations) => Annotations = annotations;
-
- protected virtual CosmosAnnotations Annotations { get; }
-
- protected virtual IModel Model => (IModel)Annotations.Metadata;
-
- public virtual string DefaultContainerName
- {
- get => (string)Annotations.Metadata[CosmosAnnotationNames.ContainerName];
-
- [param: CanBeNull] set => SetDefaultContainerName(value);
- }
-
- protected virtual bool SetDefaultContainerName([CanBeNull] string value)
- => Annotations.SetAnnotation(
- CosmosAnnotationNames.ContainerName,
- Check.NullButNotEmpty(value, nameof(value)));
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/CosmosPropertyAnnotations.cs b/src/EFCore.Cosmos/Metadata/CosmosPropertyAnnotations.cs
deleted file mode 100644
index 84354595e15..00000000000
--- a/src/EFCore.Cosmos/Metadata/CosmosPropertyAnnotations.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Metadata;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public class CosmosPropertyAnnotations : ICosmosPropertyAnnotations
- {
- public CosmosPropertyAnnotations(IProperty property)
- : this(new CosmosAnnotations(property))
- {
- }
-
- protected CosmosPropertyAnnotations(CosmosAnnotations annotations) => Annotations = annotations;
-
- protected virtual CosmosAnnotations Annotations { get; }
-
- protected virtual IProperty Property => (IProperty)Annotations.Metadata;
-
- public virtual string PropertyName
- {
- get => ((string)Annotations.Metadata[CosmosAnnotationNames.PropertyName])
- ?? Property.Name;
-
- [param: CanBeNull] set => SetPropertyName(value);
- }
-
- protected virtual bool SetPropertyName([CanBeNull] string value)
- => Annotations.SetAnnotation(
- CosmosAnnotationNames.PropertyName,
- value);
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/ICosmosEntityTypeAnnotations.cs b/src/EFCore.Cosmos/Metadata/ICosmosEntityTypeAnnotations.cs
deleted file mode 100644
index 17cdc6ec48d..00000000000
--- a/src/EFCore.Cosmos/Metadata/ICosmosEntityTypeAnnotations.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 Microsoft.EntityFrameworkCore.Metadata;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public interface ICosmosEntityTypeAnnotations
- {
- string ContainerName { get; }
- IProperty DiscriminatorProperty { get; }
- object DiscriminatorValue { get; }
- string ContainingPropertyName { get; }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/ICosmosModelAnnotations.cs b/src/EFCore.Cosmos/Metadata/ICosmosModelAnnotations.cs
deleted file mode 100644
index 47b79283024..00000000000
--- a/src/EFCore.Cosmos/Metadata/ICosmosModelAnnotations.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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.
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public interface ICosmosModelAnnotations
- {
- string DefaultContainerName { get; }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/ICosmosPropertyAnnotations.cs b/src/EFCore.Cosmos/Metadata/ICosmosPropertyAnnotations.cs
deleted file mode 100644
index fe0dea5748f..00000000000
--- a/src/EFCore.Cosmos/Metadata/ICosmosPropertyAnnotations.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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.
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata
-{
- public interface ICosmosPropertyAnnotations
- {
- string PropertyName { get; }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs
index 789dfaa2f93..b4bc86ffd9f 100644
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs
+++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs
@@ -3,12 +3,16 @@
namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
{
+ ///
+ /// 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.
+ ///
public static class CosmosAnnotationNames
{
public const string Prefix = "Cosmos:";
public const string ContainerName = Prefix + "ContainerName";
public const string PropertyName = Prefix + "PropertyName";
- public const string DiscriminatorProperty = Prefix + "DiscriminatorProperty";
- public const string DiscriminatorValue = Prefix + "DiscriminatorValue";
}
}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotations.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotations.cs
deleted file mode 100644
index 34ba1717997..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotations.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Utilities;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- public class CosmosAnnotations
- {
- public CosmosAnnotations([NotNull] IAnnotatable metadata)
- {
- Check.NotNull(metadata, nameof(metadata));
-
- Metadata = metadata;
- }
-
- public virtual IAnnotatable Metadata { get; }
-
- public virtual bool SetAnnotation(
- [NotNull] string annotationName,
- [CanBeNull] object value)
- {
- ((IMutableAnnotatable)Metadata)[annotationName] = value;
-
- return true;
- }
-
- public virtual bool CanSetAnnotation(
- [NotNull] string relationalAnnotationName,
- [CanBeNull] object value)
- => true;
-
- public virtual bool RemoveAnnotation([NotNull] string annotationName)
- {
- ((IMutableAnnotatable)Metadata).RemoveAnnotation(annotationName);
-
- return true;
- }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeBuilderAnnotations.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeBuilderAnnotations.cs
deleted file mode 100644
index 4bb5c2cad1b..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeBuilderAnnotations.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Utilities;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- public class CosmosEntityTypeBuilderAnnotations : CosmosEntityTypeAnnotations
- {
- ///
- /// 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.
- ///
- public CosmosEntityTypeBuilderAnnotations(
- [NotNull] InternalEntityTypeBuilder internalBuilder,
- ConfigurationSource configurationSource)
- : base(new CosmosAnnotationsBuilder(internalBuilder, configurationSource))
- {
- }
-
- ///
- /// 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.
- ///
- protected new virtual CosmosAnnotationsBuilder Annotations => (CosmosAnnotationsBuilder)base.Annotations;
-
- ///
- /// 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.
- ///
- protected virtual InternalEntityTypeBuilder EntityTypeBuilder => (InternalEntityTypeBuilder)Annotations.MetadataBuilder;
-
- ///
- /// 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.
- ///
- protected override CosmosModelAnnotations GetAnnotations(IModel model)
- => new CosmosModelBuilderAnnotations(
- ((Model)model).Builder,
- Annotations.ConfigurationSource);
-
- ///
- /// 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.
- ///
- protected override CosmosEntityTypeAnnotations GetAnnotations(IEntityType entityType)
- => new CosmosEntityTypeBuilderAnnotations(
- ((EntityType)entityType).Builder,
- Annotations.ConfigurationSource);
-
- ///
- /// 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.
- ///
- public virtual bool ToContainer([CanBeNull] string name)
- {
- Check.NullButNotEmpty(name, nameof(name));
-
- return SetContainerName(name);
- }
-
- ///
- /// 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.
- ///
- public virtual bool ToProperty([CanBeNull] string name)
- {
- Check.NullButNotEmpty(name, nameof(name));
-
- return SetPropertyName(name);
- }
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs
new file mode 100644
index 00000000000..17e2d61ec40
--- /dev/null
+++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosEntityTypeExtensions.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.EntityFrameworkCore.Metadata;
+
+namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
+{
+ ///
+ /// 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.
+ ///
+ public static class CosmosEntityTypeExtensions
+ {
+ ///
+ /// 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.
+ ///
+ public static bool IsDocumentRoot(this IEntityType entityType)
+ => entityType.BaseType?.IsDocumentRoot() ?? !entityType.IsOwned()
+ || entityType[CosmosAnnotationNames.ContainerName] != null;
+ }
+}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosInternalMetadataBuilderExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosInternalMetadataBuilderExtensions.cs
deleted file mode 100644
index a99d73e45cd..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosInternalMetadataBuilderExtensions.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- ///
- /// 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.
- ///
- public static class CosmosInternalMetadataBuilderExtensions
- {
- ///
- /// 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.
- ///
- public static CosmosModelBuilderAnnotations Cosmos(
- [NotNull] this InternalModelBuilder builder,
- ConfigurationSource configurationSource)
- => new CosmosModelBuilderAnnotations(builder, configurationSource);
-
- ///
- /// 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.
- ///
- public static CosmosEntityTypeBuilderAnnotations Cosmos(
- [NotNull] this InternalEntityTypeBuilder builder,
- ConfigurationSource configurationSource)
- => new CosmosEntityTypeBuilderAnnotations(builder, configurationSource);
-
- ///
- /// 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.
- ///
- public static CosmosPropertyBuilderAnnotations Cosmos(
- [NotNull] this InternalPropertyBuilder builder,
- ConfigurationSource configurationSource)
- => new CosmosPropertyBuilderAnnotations(builder, configurationSource);
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosModelBuilderAnnotations.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosModelBuilderAnnotations.cs
deleted file mode 100644
index 7417911433c..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosModelBuilderAnnotations.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- ///
- /// 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.
- ///
- public class CosmosModelBuilderAnnotations : CosmosModelAnnotations
- {
- ///
- /// 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.
- ///
- public CosmosModelBuilderAnnotations(
- [NotNull] InternalModelBuilder internalBuilder,
- ConfigurationSource configurationSource)
- : base(new CosmosAnnotationsBuilder(internalBuilder, configurationSource))
- {
- }
-
- ///
- /// 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.
- ///
- protected new virtual CosmosAnnotationsBuilder Annotations => (CosmosAnnotationsBuilder)base.Annotations;
-
- ///
- /// 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.
- ///
- protected virtual InternalModelBuilder ModelBuilder => (InternalModelBuilder)Annotations.MetadataBuilder;
-
- ///
- /// 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.
- ///
- public virtual bool HasDefaultContainerName([CanBeNull] string name) => SetDefaultContainerName(name);
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyBuilderAnnotations.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyBuilderAnnotations.cs
deleted file mode 100644
index da1f6f6e32d..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyBuilderAnnotations.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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 JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- ///
- /// 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.
- ///
- public class CosmosPropertyBuilderAnnotations : CosmosPropertyAnnotations
- {
- ///
- /// 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.
- ///
- public CosmosPropertyBuilderAnnotations(
- [NotNull] InternalPropertyBuilder internalBuilder,
- ConfigurationSource configurationSource)
- : base(new CosmosAnnotationsBuilder(internalBuilder, configurationSource))
- {
- }
-
- ///
- /// 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.
- ///
- protected new virtual CosmosAnnotationsBuilder Annotations => (CosmosAnnotationsBuilder)base.Annotations;
-
- ///
- /// 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.
- ///
- public virtual bool ToProperty([CanBeNull] string name) => SetPropertyName(name);
- }
-}
diff --git a/src/EFCore.Cosmos/Metadata/Internal/EntityTypeExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/EntityTypeExtensions.cs
deleted file mode 100644
index 1bbaeefb750..00000000000
--- a/src/EFCore.Cosmos/Metadata/Internal/EntityTypeExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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 Microsoft.EntityFrameworkCore.Metadata;
-
-namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal
-{
- public static class EntityTypeExtensions
- {
- public static bool IsDocumentRoot(this IEntityType entityType)
- => entityType.BaseType == null
- ? !entityType.IsOwned()
- || entityType[CosmosAnnotationNames.ContainerName] != null
- : entityType.BaseType.IsDocumentRoot();
- }
-}
diff --git a/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosEntityQueryableExpressionVisitor.cs b/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosEntityQueryableExpressionVisitor.cs
index 774acea0db1..1d0481d9242 100644
--- a/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosEntityQueryableExpressionVisitor.cs
+++ b/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosEntityQueryableExpressionVisitor.cs
@@ -49,7 +49,7 @@ protected override Expression VisitEntityQueryable([NotNull] Type elementType)
QueryModelVisitor.QueryCompilationContext.IsAsyncQuery,
new DocumentQueryExpression(
QueryModelVisitor.QueryCompilationContext.IsAsyncQuery,
- entityType.Cosmos().ContainerName,
+ entityType.GetCosmosContainerName(),
new SelectExpression(entityType, _querySource, _sqlGeneratorFactory)),
new EntityShaper(
entityType,
diff --git a/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosMemberAccessBindingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosMemberAccessBindingExpressionVisitor.cs
index 143542eba38..d50acc88385 100644
--- a/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosMemberAccessBindingExpressionVisitor.cs
+++ b/src/EFCore.Cosmos/Query/ExpressionVisitors/Internal/CosmosMemberAccessBindingExpressionVisitor.cs
@@ -163,7 +163,7 @@ private static Expression CreateGetValueExpression(
Expression jObjectExpression,
IProperty property)
{
- var storeName = property.Cosmos().PropertyName;
+ var storeName = property.GetCosmosPropertyName();
if (storeName.Length == 0)
{
return null;
diff --git a/src/EFCore.Cosmos/Query/Expressions/Internal/SelectExpression.cs b/src/EFCore.Cosmos/Query/Expressions/Internal/SelectExpression.cs
index 6af351e2168..f0f6e7f88f2 100644
--- a/src/EFCore.Cosmos/Query/Expressions/Internal/SelectExpression.cs
+++ b/src/EFCore.Cosmos/Query/Expressions/Internal/SelectExpression.cs
@@ -47,11 +47,11 @@ public BinaryExpression GetDiscriminatorPredicate(IEntityType entityType)
var concreteEntityTypes
= entityType.GetConcreteTypesInHierarchy().ToList();
- var discriminatorProperty = entityType.Cosmos().DiscriminatorProperty;
+ var discriminatorProperty = entityType.GetDiscriminatorProperty();
var discriminatorPredicate = Equal(
new KeyAccessExpression(discriminatorProperty, FromExpression),
- Constant(concreteEntityTypes[0].Cosmos().DiscriminatorValue, discriminatorProperty.ClrType));
+ Constant(concreteEntityTypes[0].GetDiscriminatorValue(), discriminatorProperty.ClrType));
if (concreteEntityTypes.Count > 1)
{
@@ -60,7 +60,7 @@ var concreteEntityTypes
.Skip(1)
.Select(
concreteEntityType
- => Constant(concreteEntityType.Cosmos().DiscriminatorValue, discriminatorProperty.ClrType))
+ => Constant(concreteEntityType.GetDiscriminatorValue(), discriminatorProperty.ClrType))
.Aggregate(
discriminatorPredicate, (current, discriminatorValue) =>
OrElse(
diff --git a/src/EFCore.Cosmos/Query/Internal/EntityShaper.cs b/src/EFCore.Cosmos/Query/Internal/EntityShaper.cs
index 97204f75724..aee65878169 100644
--- a/src/EFCore.Cosmos/Query/Internal/EntityShaper.cs
+++ b/src/EFCore.Cosmos/Query/Internal/EntityShaper.cs
@@ -124,11 +124,11 @@ var materializer
return Expression.Lambda(materializer, materializationContextParameter);
}
- var discriminatorProperty = firstEntityType.Cosmos().DiscriminatorProperty;
+ var discriminatorProperty = firstEntityType.GetDiscriminatorProperty();
var firstDiscriminatorValue
= Expression.Constant(
- firstEntityType.Cosmos().DiscriminatorValue,
+ firstEntityType.GetDiscriminatorValue(),
discriminatorProperty.ClrType);
var discriminatorValueVariable
@@ -191,7 +191,7 @@ var blockExpressions
var discriminatorValue
= Expression.Constant(
- concreteEntityType.Cosmos().DiscriminatorValue,
+ concreteEntityType.GetDiscriminatorValue(),
discriminatorProperty.ClrType);
materializer
@@ -294,7 +294,7 @@ private static object ShapeNestedEntities(
var nestedFk = nestedNavigation.ForeignKey;
if (nestedFk.IsUnique)
{
- if (!(jObject[nestedFk.DeclaringEntityType.Cosmos().ContainingPropertyName] is JObject nestedJObject))
+ if (!(jObject[nestedFk.DeclaringEntityType.GetCosmosContainingPropertyName()] is JObject nestedJObject))
{
continue;
}
@@ -310,7 +310,7 @@ private static object ShapeNestedEntities(
else
{
var nestedEntities = new List
public static class RelationalEntityTypeBuilderExtensions
{
- private static readonly string DefaultDiscriminatorName = "Discriminator";
-
- // ReSharper disable once InconsistentNaming
- private static readonly Type DefaultDiscriminatorType = typeof(string);
-
///
/// Configures the view or table that the entity type maps to when targeting a relational database.
///
@@ -343,354 +335,6 @@ public static EntityTypeBuilder ToView(
where TEntity : class
=> (EntityTypeBuilder)ToView((EntityTypeBuilder)entityTypeBuilder, name, schema);
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// A builder that allows the discriminator column to be configured.
- public static DiscriminatorBuilder HasDiscriminator([NotNull] this EntityTypeBuilder entityTypeBuilder)
- {
- Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
-
- var propertyBuilder = new PropertyBuilder(
- (IMutableProperty)GetOrCreateDiscriminatorProperty(
- ((IConventionEntityType)entityTypeBuilder.Metadata).Builder, null, null, true).Metadata);
- return DiscriminatorBuilder(entityTypeBuilder.Metadata, propertyBuilder);
- }
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// The name of the discriminator column.
- /// The type of values stored in the discriminator column.
- /// A builder that allows the discriminator column to be configured.
- public static DiscriminatorBuilder HasDiscriminator(
- [NotNull] this EntityTypeBuilder entityTypeBuilder,
- [NotNull] string name,
- [NotNull] Type type)
- {
- Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
- Check.NotEmpty(name, nameof(name));
- Check.NotNull(type, nameof(type));
-
- return DiscriminatorBuilder(
- entityTypeBuilder.Metadata, entityTypeBuilder.Property(type, name));
- }
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The type of values stored in the discriminator column.
- /// The builder for the entity type being configured.
- /// The name of the discriminator column.
- /// A builder that allows the discriminator column to be configured.
- public static DiscriminatorBuilder HasDiscriminator(
- [NotNull] this EntityTypeBuilder entityTypeBuilder,
- [NotNull] string name)
- {
- Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
- Check.NotEmpty(name, nameof(name));
-
- return new DiscriminatorBuilder(
- DiscriminatorBuilder(
- entityTypeBuilder.Metadata, entityTypeBuilder.Property(typeof(TDiscriminator), name)));
- }
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The entity type being configured.
- /// The type of values stored in the discriminator column.
- /// The builder for the entity type being configured.
- ///
- /// A lambda expression representing the property to be used as the discriminator (
- /// blog => blog.Discriminator).
- ///
- /// A builder that allows the discriminator column to be configured.
- public static DiscriminatorBuilder HasDiscriminator(
- [NotNull] this EntityTypeBuilder entityTypeBuilder,
- [NotNull] Expression> propertyExpression)
- where TEntity : class
- {
- Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
- Check.NotNull(propertyExpression, nameof(propertyExpression));
-
- return new DiscriminatorBuilder(
- DiscriminatorBuilder(entityTypeBuilder.Metadata, entityTypeBuilder.Property(propertyExpression)));
- }
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// Indicates whether the configuration was specified using a data annotation.
- /// A builder that allows the discriminator column to be configured.
- public static IConventionDiscriminatorBuilder HasDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, bool fromDataAnnotation = false)
- => DiscriminatorBuilder(
- entityTypeBuilder, GetOrCreateDiscriminatorProperty(entityTypeBuilder, type: null, name: null, fromDataAnnotation: false),
- fromDataAnnotation);
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// The type of values stored in the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- ///
- /// The same builder instance if the discriminator was configured,
- /// null otherwise.
- ///
- public static IConventionDiscriminatorBuilder HasDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] Type type, bool fromDataAnnotation = false)
- => CanSetDiscriminator(entityTypeBuilder, type, fromDataAnnotation)
- ? DiscriminatorBuilder(
- entityTypeBuilder, GetOrCreateDiscriminatorProperty(entityTypeBuilder, type, name: null, fromDataAnnotation),
- fromDataAnnotation)
- : null;
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// The name of the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- ///
- /// The same builder instance if the discriminator was configured,
- /// null otherwise.
- ///
- public static IConventionDiscriminatorBuilder HasDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] string name, bool fromDataAnnotation = false)
- => CanSetDiscriminator(entityTypeBuilder, name, fromDataAnnotation)
- ? DiscriminatorBuilder(
- entityTypeBuilder, GetOrCreateDiscriminatorProperty(entityTypeBuilder, type: null, name, fromDataAnnotation),
- fromDataAnnotation)
- : null;
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// The name of the discriminator column.
- /// The type of values stored in the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- ///
- /// The same builder instance if the discriminator was configured,
- /// null otherwise.
- ///
- public static IConventionDiscriminatorBuilder HasDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] string name, [NotNull] Type type,
- bool fromDataAnnotation = false)
- => CanSetDiscriminator(entityTypeBuilder, type, name, fromDataAnnotation)
- ? DiscriminatorBuilder(
- entityTypeBuilder, entityTypeBuilder.Metadata.RootType().Builder.Property(type, name, fromDataAnnotation),
- fromDataAnnotation)
- : null;
-
- ///
- /// Configures the discriminator column used to identify which entity type each row in a table represents
- /// when an inheritance hierarchy is mapped to a single table in a relational database.
- ///
- /// The builder for the entity type being configured.
- /// The property mapped to the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- ///
- /// The same builder instance if the discriminator was configured,
- /// null otherwise.
- ///
- public static IConventionDiscriminatorBuilder HasDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] MemberInfo memberInfo, bool fromDataAnnotation = false)
- => CanSetDiscriminator(entityTypeBuilder, memberInfo.GetMemberType(), memberInfo.GetSimpleMemberName(), fromDataAnnotation)
- ? DiscriminatorBuilder(
- entityTypeBuilder, entityTypeBuilder.Metadata.RootType().Builder.Property(memberInfo, fromDataAnnotation),
- fromDataAnnotation)
- : null;
-
- ///
- /// Removes the discriminator property from this entity type.
- /// This method is usually called when the entity type is no longer mapped to the same table as any other type in
- /// the hierarchy or when this entity type is no longer the root type.
- ///
- /// The builder for the entity type being configured.
- /// Indicates whether the configuration was specified using a data annotation.
- ///
- /// The same builder instance if the discriminator was configured,
- /// null otherwise.
- ///
- public static IConventionEntityTypeBuilder HasNoDeclaredDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, bool fromDataAnnotation = false)
- {
- var discriminatorName = (string)entityTypeBuilder.Metadata[RelationalAnnotationNames.DiscriminatorProperty];
- if (discriminatorName == null)
- {
- return entityTypeBuilder;
- }
-
- var discriminatorProperty = entityTypeBuilder.Metadata.FindProperty(discriminatorName);
- if (discriminatorProperty != null)
- {
- if (!CanSetDiscriminator(entityTypeBuilder, discriminatorProperty, null, null, fromDataAnnotation))
- {
- return null;
- }
-
- discriminatorProperty.DeclaringEntityType.Builder.RemoveUnusedShadowProperties(
- new[]
- {
- discriminatorProperty
- });
- }
-
- entityTypeBuilder.Metadata.SetDiscriminatorProperty(null, fromDataAnnotation);
- return entityTypeBuilder;
- }
-
- private static IConventionPropertyBuilder GetOrCreateDiscriminatorProperty(
- IConventionEntityTypeBuilder entityTypeBuilder, Type type, string name, bool fromDataAnnotation)
- {
- var discriminatorProperty = entityTypeBuilder.Metadata.GetDiscriminatorProperty();
- if ((name != null && discriminatorProperty?.Name != name)
- || (type != null && discriminatorProperty?.ClrType != type))
- {
- discriminatorProperty = null;
- }
-
- return entityTypeBuilder.Metadata.RootType().Builder.Property(
- type ?? discriminatorProperty?.ClrType ?? DefaultDiscriminatorType,
- name ?? discriminatorProperty?.Name ?? DefaultDiscriminatorName,
- setTypeConfigurationSource: type != null,
- fromDataAnnotation);
- }
-
- private static DiscriminatorBuilder DiscriminatorBuilder(
- IMutableEntityType entityType,
- [NotNull] PropertyBuilder discriminatorPropertyBuilder)
- {
- var rootTypeBuilder = new EntityTypeBuilder(entityType.RootType());
-
- var discriminatorProperty = (IConventionProperty)discriminatorPropertyBuilder.Metadata;
- // Make sure the property is on the root type
- discriminatorPropertyBuilder = discriminatorProperty.GetTypeConfigurationSource() != null
- ? rootTypeBuilder.Property(discriminatorProperty.ClrType, discriminatorProperty.Name)
- : rootTypeBuilder.Property(discriminatorProperty.Name);
-
- var oldDiscriminatorProperty = entityType.GetDiscriminatorProperty() as IConventionProperty;
- if (oldDiscriminatorProperty?.Builder != null
- && oldDiscriminatorProperty != discriminatorProperty)
- {
- oldDiscriminatorProperty.DeclaringEntityType.Builder.RemoveUnusedShadowProperties(
- new[]
- {
- oldDiscriminatorProperty
- });
- }
-
- rootTypeBuilder.Metadata.SetDiscriminatorProperty(discriminatorProperty);
- discriminatorPropertyBuilder.IsRequired();
- discriminatorPropertyBuilder.HasValueGenerator(DiscriminatorValueGenerator.Factory);
-
- return new DiscriminatorBuilder(entityType);
- }
-
- private static IConventionDiscriminatorBuilder DiscriminatorBuilder(
- IConventionEntityTypeBuilder entityTypeBuilder,
- IConventionPropertyBuilder discriminatorPropertyBuilder,
- bool fromDataAnnotation)
- {
- if (discriminatorPropertyBuilder == null)
- {
- return null;
- }
-
- var rootTypeBuilder = entityTypeBuilder.Metadata.RootType().Builder;
- var discriminatorProperty = discriminatorPropertyBuilder.Metadata;
- // Make sure the property is on the root type
- discriminatorPropertyBuilder = rootTypeBuilder.Property(
- discriminatorProperty.ClrType, discriminatorProperty.Name, setTypeConfigurationSource: false);
-
- var oldDiscriminatorProperty = entityTypeBuilder.Metadata.GetDiscriminatorProperty() as IConventionProperty;
- if (oldDiscriminatorProperty?.Builder != null
- && oldDiscriminatorProperty != discriminatorProperty)
- {
- oldDiscriminatorProperty.Builder.IsRequired(null, fromDataAnnotation);
- oldDiscriminatorProperty.Builder.HasValueGenerator((Type)null, fromDataAnnotation);
- oldDiscriminatorProperty.DeclaringEntityType.Builder.RemoveUnusedShadowProperties(
- new[]
- {
- oldDiscriminatorProperty
- });
- }
-
- rootTypeBuilder.Metadata.SetDiscriminatorProperty(discriminatorProperty, fromDataAnnotation);
- discriminatorPropertyBuilder.IsRequired(true, fromDataAnnotation);
- discriminatorPropertyBuilder.HasValueGenerator(DiscriminatorValueGenerator.Factory, fromDataAnnotation);
-
- return new DiscriminatorBuilder((IMutableEntityType)entityTypeBuilder.Metadata);
- }
-
- ///
- /// Returns a value indicating whether the discriminator column can be configured.
- ///
- /// The builder for the entity type being configured.
- /// The name of the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- /// true if the configuration can be applied.
- public static bool CanSetDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] string name, bool fromDataAnnotation = false)
- => CanSetDiscriminator(
- entityTypeBuilder, entityTypeBuilder.Metadata.GetDiscriminatorProperty(), name, discriminatorType: null,
- fromDataAnnotation);
-
- ///
- /// Returns a value indicating whether the discriminator column can be configured.
- ///
- /// The builder for the entity type being configured.
- /// The type of values stored in the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- /// true if the configuration can be applied.
- public static bool CanSetDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] Type type, bool fromDataAnnotation = false)
- => CanSetDiscriminator(
- entityTypeBuilder, entityTypeBuilder.Metadata.GetDiscriminatorProperty(), name: null, type, fromDataAnnotation);
-
- ///
- /// Returns a value indicating whether the discriminator column can be configured.
- ///
- /// The builder for the entity type being configured.
- /// The type of values stored in the discriminator column.
- /// The name of the discriminator column.
- /// Indicates whether the configuration was specified using a data annotation.
- /// true if the configuration can be applied.
- public static bool CanSetDiscriminator(
- [NotNull] this IConventionEntityTypeBuilder entityTypeBuilder,
- [NotNull] Type type,
- [NotNull] string name,
- bool fromDataAnnotation = false)
- => CanSetDiscriminator(
- entityTypeBuilder, entityTypeBuilder.Metadata.GetDiscriminatorProperty(), name, type, fromDataAnnotation);
-
- private static bool CanSetDiscriminator(
- IConventionEntityTypeBuilder entityTypeBuilder,
- IProperty discriminatorProperty,
- string name,
- Type discriminatorType,
- bool fromDataAnnotation)
- => discriminatorProperty == null
- || ((name != null || discriminatorType != null)
- && (name == null || discriminatorProperty.Name == name)
- && (discriminatorType == null || discriminatorProperty.ClrType == discriminatorType))
- || (fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention)
- .Overrides(entityTypeBuilder.Metadata.GetDiscriminatorPropertyConfigurationSource());
-
///
/// Configures a database check constraint when targeting a relational database.
///
@@ -784,7 +428,7 @@ public static IConventionEntityTypeBuilder HasCheckConstraint(
}
if (!(fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention)
- .Overrides(entityTypeBuilder.Metadata.GetDiscriminatorPropertyConfigurationSource()))
+ .Overrides(constraint.GetConfigurationSource()))
{
return null;
}
diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
index 09b3bbd0022..53880f6d37c 100644
--- a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
+++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
@@ -142,165 +142,5 @@ public static void SetSchema(
public static ConfigurationSource? GetSchemaConfigurationSource([NotNull] this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.Schema)
?.GetConfigurationSource();
-
- ///
- /// Returns the that will be used for storing a discriminator value.
- ///
- /// The entity type to get the discriminator property for.
- public static IProperty GetDiscriminatorProperty([NotNull] this IEntityType entityType)
- {
- if (entityType.BaseType != null)
- {
- return entityType.RootType().GetDiscriminatorProperty();
- }
-
- var propertyName = (string)entityType[RelationalAnnotationNames.DiscriminatorProperty];
-
- return propertyName == null ? null : entityType.FindProperty(propertyName);
- }
-
- ///
- /// Sets the that will be used for storing a discriminator value.
- ///
- /// The entity type to set the discriminator property for.
- /// The property to set.
- public static void SetDiscriminatorProperty([NotNull] this IMutableEntityType entityType, [CanBeNull] IProperty property)
- {
- CheckDiscriminatorProperty(entityType, property);
-
- var oldDiscriminatorType = entityType.GetDiscriminatorProperty()?.ClrType;
- if (property == null
- || property.ClrType != oldDiscriminatorType)
- {
- foreach (var derivedType in entityType.GetDerivedTypesInclusive())
- {
- derivedType.RemoveDiscriminatorValue();
- }
- }
-
- entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.DiscriminatorProperty, property?.Name);
- }
-
- ///
- /// Sets the that will be used for storing a discriminator value.
- ///
- /// The entity type to set the discriminator property for.
- /// The property to set.
- /// Indicates whether the configuration was specified using a data annotation.
- public static void SetDiscriminatorProperty(
- [NotNull] this IConventionEntityType entityType, [CanBeNull] IProperty property, bool fromDataAnnotation = false)
- {
- CheckDiscriminatorProperty(entityType, property);
-
- if (property != null
- && !property.ClrType.IsInstanceOfType(entityType.GetDiscriminatorValue()))
- {
- foreach (var derivedType in entityType.GetDerivedTypesInclusive())
- {
- derivedType.RemoveDiscriminatorValue();
- }
- }
-
- entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.DiscriminatorProperty, property?.Name, fromDataAnnotation);
- }
-
- private static void CheckDiscriminatorProperty(IEntityType entityType, IProperty property)
- {
- if (property != null)
- {
- if (entityType != entityType.RootType())
- {
- throw new InvalidOperationException(
- RelationalStrings.DiscriminatorPropertyMustBeOnRoot(entityType.DisplayName()));
- }
-
- if (property.DeclaringEntityType != entityType)
- {
- throw new InvalidOperationException(
- RelationalStrings.DiscriminatorPropertyNotFound(property.Name, entityType.DisplayName()));
- }
- }
- }
-
- ///
- /// Gets the for the discriminator property.
- ///
- /// The entity type to find configuration source for.
- /// The or null if no discriminator property has been set.
- public static ConfigurationSource? GetDiscriminatorPropertyConfigurationSource([NotNull] this IConventionEntityType entityType)
- => entityType.FindAnnotation(RelationalAnnotationNames.DiscriminatorProperty)
- ?.GetConfigurationSource();
-
- ///
- /// Returns the discriminator value for this entity type.
- ///
- /// The entity type to find the discriminator value for.
- /// The discriminator value for this entity type.
- public static object GetDiscriminatorValue([NotNull] this IEntityType entityType)
- => entityType[RelationalAnnotationNames.DiscriminatorValue];
-
- ///
- /// Sets the discriminator value for this entity type.
- ///
- /// The entity type to set the discriminator value for.
- /// The value to set.
- public static void SetDiscriminatorValue([NotNull] this IMutableEntityType entityType, [CanBeNull] object value)
- {
- CheckDiscriminatorValue(entityType, value);
-
- entityType.SetAnnotation(RelationalAnnotationNames.DiscriminatorValue, value);
- }
-
- ///
- /// Sets the discriminator value for this entity type.
- ///
- /// The entity type to set the discriminator value for.
- /// The value to set.
- /// Indicates whether the configuration was specified using a data annotation.
- public static void SetDiscriminatorValue(
- [NotNull] this IConventionEntityType entityType, [CanBeNull] object value, bool fromDataAnnotation = false)
- {
- CheckDiscriminatorValue(entityType, value);
-
- entityType.SetAnnotation(RelationalAnnotationNames.DiscriminatorValue, value, fromDataAnnotation);
- }
-
- private static void CheckDiscriminatorValue(IEntityType entityType, object value)
- {
- if (value != null
- && entityType.GetDiscriminatorProperty() == null)
- {
- throw new InvalidOperationException(
- RelationalStrings.NoDiscriminatorForValue(entityType.DisplayName(), entityType.RootType().DisplayName()));
- }
-
- if (value != null
- && !entityType.GetDiscriminatorProperty().ClrType.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()))
- {
- throw new InvalidOperationException(
- RelationalStrings.DiscriminatorValueIncompatible(
- value, entityType.GetDiscriminatorProperty().Name, entityType.GetDiscriminatorProperty().ClrType));
- }
- }
-
- ///
- /// Removes the discriminator value for this entity type.
- ///
- public static void RemoveDiscriminatorValue([NotNull] this IMutableEntityType entityType)
- => entityType.RemoveAnnotation(RelationalAnnotationNames.DiscriminatorValue);
-
- ///
- /// Removes the discriminator value for this entity type.
- ///
- public static void RemoveDiscriminatorValue([NotNull] this IConventionEntityType entityType)
- => entityType.RemoveAnnotation(RelationalAnnotationNames.DiscriminatorValue);
-
- ///
- /// Gets the for the discriminator value.
- ///
- /// The or null if no discriminator value has been set.
- public static ConfigurationSource? GetDiscriminatorValueConfigurationSource([NotNull] this IConventionEntityType entityType)
- => entityType.FindAnnotation(RelationalAnnotationNames.DiscriminatorValue)
- ?.GetConfigurationSource();
}
}
diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
index 82944434748..9503be768dd 100644
--- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
+++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
@@ -483,7 +483,9 @@ protected virtual void ValidateSharedIndexesCompatibility(
/// The table name.
/// The logger to use.
protected virtual void ValidateSharedKeysCompatibility(
- [NotNull] IReadOnlyList mappedTypes, [NotNull] string tableName, [NotNull] IDiagnosticsLogger logger)
+ [NotNull] IReadOnlyList mappedTypes,
+ [NotNull] string tableName,
+ [NotNull] IDiagnosticsLogger logger)
{
var keyMappings = new Dictionary();
@@ -521,11 +523,6 @@ protected virtual void ValidateSharedKeysCompatibility(
/// The logger to use.
protected virtual void ValidateInheritanceMapping([NotNull] IModel model, [NotNull] IDiagnosticsLogger logger)
{
- foreach (var rootEntityType in model.GetRootEntityTypes())
- {
- ValidateDiscriminatorValues(rootEntityType);
- }
-
foreach (var entityType in model.GetEntityTypes())
{
if (entityType.BaseType != null
@@ -539,51 +536,6 @@ protected virtual void ValidateInheritanceMapping([NotNull] IModel model, [NotNu
}
}
- private static void ValidateDiscriminator(IEntityType entityType)
- {
- if (entityType.GetDiscriminatorProperty() == null)
- {
- throw new InvalidOperationException(
- RelationalStrings.NoDiscriminatorProperty(entityType.DisplayName()));
- }
-
- if (entityType.GetDiscriminatorValue() == null)
- {
- throw new InvalidOperationException(
- RelationalStrings.NoDiscriminatorValue(entityType.DisplayName()));
- }
- }
-
- private static void ValidateDiscriminatorValues(IEntityType rootEntityType)
- {
- var discriminatorValues = new Dictionary
public const string CheckConstraints = Prefix + "CheckConstraints";
- ///
- /// The name for discriminator property annotations.
- ///
- public const string DiscriminatorProperty = Prefix + "DiscriminatorProperty";
-
- ///
- /// The name for discriminator value annotations.
- ///
- public const string DiscriminatorValue = Prefix + "DiscriminatorValue";
-
///
/// The name for filter annotations.
///
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
index 7feaf497fff..c9740772b0d 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
+++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
@@ -157,22 +157,6 @@ public static string UnableToDiscriminate([CanBeNull] object entityType)
GetString("UnableToDiscriminate", nameof(entityType)),
entityType);
- ///
- /// A discriminator property cannot be set for the entity type '{entityType}' because it is not the root of an inheritance hierarchy.
- ///
- public static string DiscriminatorPropertyMustBeOnRoot([CanBeNull] object entityType)
- => string.Format(
- GetString("DiscriminatorPropertyMustBeOnRoot", nameof(entityType)),
- entityType);
-
- ///
- /// Unable to set property '{property}' as a discriminator for entity type '{entityType}' because it is not a property of '{entityType}'.
- ///
- public static string DiscriminatorPropertyNotFound([CanBeNull] object property, [CanBeNull] object entityType)
- => string.Format(
- GetString("DiscriminatorPropertyNotFound", nameof(property), nameof(entityType)),
- property, entityType);
-
///
/// The Include operation is not supported when calling a stored procedure.
///
@@ -203,46 +187,6 @@ public static string IncompatibleTableNoRelationship([CanBeNull] object table, [
GetString("IncompatibleTableNoRelationship", nameof(table), nameof(entityType), nameof(otherEntityType)),
table, entityType, otherEntityType);
- ///
- /// Cannot configure the discriminator value for entity type '{entityType}' because it doesn't derive from '{rootEntityType}'.
- ///
- public static string DiscriminatorEntityTypeNotDerived([CanBeNull] object entityType, [CanBeNull] object rootEntityType)
- => string.Format(
- GetString("DiscriminatorEntityTypeNotDerived", nameof(entityType), nameof(rootEntityType)),
- entityType, rootEntityType);
-
- ///
- /// Cannot set discriminator value '{value}' for discriminator property '{discriminator}' because it is not assignable to property of type '{discriminatorType}'.
- ///
- public static string DiscriminatorValueIncompatible([CanBeNull] object value, [CanBeNull] object discriminator, [CanBeNull] object discriminatorType)
- => string.Format(
- GetString("DiscriminatorValueIncompatible", nameof(value), nameof(discriminator), nameof(discriminatorType)),
- value, discriminator, discriminatorType);
-
- ///
- /// Cannot set discriminator value for entity type '{entityType}' because the root entity type '{rootEntityType}' doesn't have a discriminator property set.
- ///
- public static string NoDiscriminatorForValue([CanBeNull] object entityType, [CanBeNull] object rootEntityType)
- => string.Format(
- GetString("NoDiscriminatorForValue", nameof(entityType), nameof(rootEntityType)),
- entityType, rootEntityType);
-
- ///
- /// The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator property configured.
- ///
- public static string NoDiscriminatorProperty([CanBeNull] object entityType)
- => string.Format(
- GetString("NoDiscriminatorProperty", nameof(entityType)),
- entityType);
-
- ///
- /// The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator value configured.
- ///
- public static string NoDiscriminatorValue([CanBeNull] object entityType)
- => string.Format(
- GetString("NoDiscriminatorValue", nameof(entityType)),
- entityType);
-
///
/// No value provided for required parameter '{parameter}'.
///
@@ -345,14 +289,6 @@ public static string IncorrectDefaultValueType([CanBeNull] object value, [CanBeN
GetString("IncorrectDefaultValueType", nameof(value), nameof(valueType), nameof(property), nameof(propertyType), nameof(entityType)),
value, valueType, property, propertyType, entityType);
- ///
- /// The discriminator value for '{entityType1}' is '{discriminatorValue}' which is the same for '{entityType2}'. Every concrete entity type in the hierarchy needs to have a unique discriminator value.
- ///
- public static string DuplicateDiscriminatorValue([CanBeNull] object entityType1, [CanBeNull] object discriminatorValue, [CanBeNull] object entityType2)
- => string.Format(
- GetString("DuplicateDiscriminatorValue", nameof(entityType1), nameof(discriminatorValue), nameof(entityType2)),
- entityType1, discriminatorValue, entityType2);
-
///
/// '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}' but are configured with different nullability.
///
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx
index 162bc02e51a..cc6e575c8b2 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.resx
+++ b/src/EFCore.Relational/Properties/RelationalStrings.resx
@@ -229,12 +229,6 @@
Unable to materialize entity of type '{entityType}'. No discriminators were matched.
-
- A discriminator property cannot be set for the entity type '{entityType}' because it is not the root of an inheritance hierarchy.
-
-
- Unable to set property '{property}' as a discriminator for entity type '{entityType}' because it is not a property of '{entityType}'.
-
An ambient transaction has been detected. The current provider does not support ambient transactions. See http://go.microsoft.com/fwlink/?LinkId=800142Warning RelationalEventId.AmbientTransactionWarning
@@ -291,21 +285,6 @@
Property '{property}' on entity type '{entityType}' is part of a primary or alternate key but has a constant default value set. Constant default values are not useful for primary or alternate keys since these properties must always have non-null unqiue values.Warning RelationalEventId.ModelValidationKeyDefaultValueWarning string string
-
- Cannot configure the discriminator value for entity type '{entityType}' because it doesn't derive from '{rootEntityType}'.
-
-
- Cannot set discriminator value '{value}' for discriminator property '{discriminator}' because it is not assignable to property of type '{discriminatorType}'.
-
-
- Cannot set discriminator value for entity type '{entityType}' because the root entity type '{rootEntityType}' doesn't have a discriminator property set.
-
-
- The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator property configured.
-
-
- The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator value configured.
-
The LINQ expression '{expression}' could not be translated and will be evaluated locally.Warning RelationalEventId.QueryClientEvaluationWarning object
@@ -361,9 +340,6 @@
Cannot set default value '{value}' of type '{valueType}' on property '{property}' of type '{propertyType}' in entity type '{entityType}'.
-
- The discriminator value for '{entityType1}' is '{discriminatorValue}' which is the same for '{entityType2}'. Every concrete entity type in the hierarchy needs to have a unique discriminator value.
-
'{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}' but are configured with different nullability.
diff --git a/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs b/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs
index 563c85b5b6e..1b479615a17 100644
--- a/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs
+++ b/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs
@@ -425,5 +425,55 @@ public static void SetDefiningQuery(
/// The configuration source for .
public static ConfigurationSource? GetDefiningQueryConfigurationSource([NotNull] this IConventionEntityType entityType)
=> entityType.FindAnnotation(CoreAnnotationNames.DefiningQuery)?.GetConfigurationSource();
+
+ ///
+ /// Sets the that will be used for storing a discriminator value.
+ ///
+ /// The entity type to set the discriminator property for.
+ /// The property to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetDiscriminatorProperty(
+ [NotNull] this IConventionEntityType entityType, [CanBeNull] IProperty property, bool fromDataAnnotation = false)
+ => Check.NotNull(entityType, nameof(entityType)).AsEntityType()
+ .SetDiscriminatorProperty(
+ property,
+ fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);
+
+ ///
+ /// Gets the for the discriminator property.
+ ///
+ /// The entity type to find configuration source for.
+ /// The or null if no discriminator property has been set.
+ public static ConfigurationSource? GetDiscriminatorPropertyConfigurationSource([NotNull] this IConventionEntityType entityType)
+ => entityType.FindAnnotation(CoreAnnotationNames.DiscriminatorProperty)
+ ?.GetConfigurationSource();
+
+ ///
+ /// Sets the discriminator value for this entity type.
+ ///
+ /// The entity type to set the discriminator value for.
+ /// The value to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ public static void SetDiscriminatorValue(
+ [NotNull] this IConventionEntityType entityType, [CanBeNull] object value, bool fromDataAnnotation = false)
+ {
+ entityType.AsEntityType().CheckDiscriminatorValue(entityType, value);
+
+ entityType.SetAnnotation(CoreAnnotationNames.DiscriminatorValue, value, fromDataAnnotation);
+ }
+
+ ///
+ /// Removes the discriminator value for this entity type.
+ ///
+ public static void RemoveDiscriminatorValue([NotNull] this IConventionEntityType entityType)
+ => entityType.RemoveAnnotation(CoreAnnotationNames.DiscriminatorValue);
+
+ ///
+ /// Gets the for the discriminator value.
+ ///
+ /// The or null if no discriminator value has been set.
+ public static ConfigurationSource? GetDiscriminatorValueConfigurationSource([NotNull] this IConventionEntityType entityType)
+ => entityType.FindAnnotation(CoreAnnotationNames.DiscriminatorValue)
+ ?.GetConfigurationSource();
}
}
diff --git a/src/EFCore/Extensions/EntityTypeExtensions.cs b/src/EFCore/Extensions/EntityTypeExtensions.cs
index 532c61f63f7..c0e351e4d16 100644
--- a/src/EFCore/Extensions/EntityTypeExtensions.cs
+++ b/src/EFCore/Extensions/EntityTypeExtensions.cs
@@ -9,6 +9,7 @@
using System.Reflection;
using System.Text;
using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
@@ -523,5 +524,28 @@ public static LambdaExpression GetDefiningQuery([NotNull] this IEntityType entit
return (LambdaExpression)entityType[CoreAnnotationNames.DefiningQuery];
}
+ ///
+ /// Returns the that will be used for storing a discriminator value.
+ ///
+ /// The entity type to get the discriminator property for.
+ public static IProperty GetDiscriminatorProperty([NotNull] this IEntityType entityType)
+ {
+ if (entityType.BaseType != null)
+ {
+ return entityType.RootType().GetDiscriminatorProperty();
+ }
+
+ var propertyName = (string)entityType[CoreAnnotationNames.DiscriminatorProperty];
+
+ return propertyName == null ? null : entityType.FindProperty(propertyName);
+ }
+
+ ///
+ /// Returns the discriminator value for this entity type.
+ ///
+ /// The entity type to find the discriminator value for.
+ /// The discriminator value for this entity type.
+ public static object GetDiscriminatorValue([NotNull] this IEntityType entityType)
+ => entityType[CoreAnnotationNames.DiscriminatorValue];
}
}
diff --git a/src/EFCore/Extensions/MutableEntityTypeExtensions.cs b/src/EFCore/Extensions/MutableEntityTypeExtensions.cs
index 5a172caf073..0db15c2a085 100644
--- a/src/EFCore/Extensions/MutableEntityTypeExtensions.cs
+++ b/src/EFCore/Extensions/MutableEntityTypeExtensions.cs
@@ -393,5 +393,33 @@ public static void SetDefiningQuery(
[CanBeNull] LambdaExpression definingQuery)
=> Check.NotNull(entityType, nameof(entityType)).AsEntityType()
.SetDefiningQuery(definingQuery, ConfigurationSource.Explicit);
+
+ ///
+ /// Sets the that will be used for storing a discriminator value.
+ ///
+ /// The entity type to set the discriminator property for.
+ /// The property to set.
+ public static void SetDiscriminatorProperty([NotNull] this IMutableEntityType entityType, [CanBeNull] IProperty property)
+ => Check.NotNull(entityType, nameof(entityType)).AsEntityType()
+ .SetDiscriminatorProperty(property, ConfigurationSource.Explicit);
+
+ ///
+ /// Sets the discriminator value for this entity type.
+ ///
+ /// The entity type to set the discriminator value for.
+ /// The value to set.
+ public static void SetDiscriminatorValue([NotNull] this IMutableEntityType entityType, [CanBeNull] object value)
+ {
+ entityType.AsEntityType().CheckDiscriminatorValue(entityType, value);
+
+ entityType.SetAnnotation(CoreAnnotationNames.DiscriminatorValue, value);
+ }
+
+ ///
+ /// Removes the discriminator value for this entity type.
+ ///
+ /// The entity type to remove the discriminator value for.
+ public static void RemoveDiscriminatorValue([NotNull] this IMutableEntityType entityType)
+ => entityType.RemoveAnnotation(CoreAnnotationNames.DiscriminatorValue);
}
}
diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs
index 1a03b9380a6..1afd3ac674f 100644
--- a/src/EFCore/Infrastructure/ModelValidator.cs
+++ b/src/EFCore/Infrastructure/ModelValidator.cs
@@ -64,6 +64,7 @@ public virtual void Validate(IModel model, IDiagnosticsLogger();
foreach (var entityType in model.GetEntityTypes())
{
- ValidateClrInheritance(model, entityType, validEntityTypes, logger);
+ ValidateClrInheritance(model, entityType, validEntityTypes);
}
}
private void ValidateClrInheritance(
[NotNull] IModel model,
[NotNull] IEntityType entityType,
- [NotNull] HashSet validEntityTypes,
- [NotNull] IDiagnosticsLogger logger)
+ [NotNull] HashSet validEntityTypes)
{
Check.NotNull(model, nameof(model));
Check.NotNull(entityType, nameof(entityType));
@@ -487,6 +487,64 @@ private void ValidateClrInheritance(
validEntityTypes.Add(entityType);
}
+ ///
+ /// Validates the mapping/configuration of inheritance in the model.
+ ///
+ /// The model to validate.
+ /// The logger to use.
+ protected virtual void ValidateDiscriminatorValues([NotNull] IModel model, [NotNull] IDiagnosticsLogger logger)
+ {
+ foreach (var rootEntityType in model.GetRootEntityTypes())
+ {
+ ValidateDiscriminatorValues(rootEntityType);
+ }
+ }
+
+ private static void ValidateDiscriminator(IEntityType entityType)
+ {
+ if (entityType.GetDiscriminatorProperty() == null)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.NoDiscriminatorProperty(entityType.DisplayName()));
+ }
+
+ if (entityType.GetDiscriminatorValue() == null)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.NoDiscriminatorValue(entityType.DisplayName()));
+ }
+ }
+
+ private static void ValidateDiscriminatorValues(IEntityType rootEntityType)
+ {
+ var discriminatorValues = new Dictionary