diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs
index fd42271c82b..2990718e5c0 100644
--- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs
+++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs
@@ -97,14 +97,14 @@ private static void ProcessEntityType(IConventionEntityTypeBuilder entityTypeBui
///
public override void ProcessDiscriminatorPropertySet(
- IConventionEntityTypeBuilder entityTypeBuilder,
+ IConventionTypeBaseBuilder structuralTypeBuilder,
string? name,
IConventionContext context)
{
- var entityType = entityTypeBuilder.Metadata;
- if (entityType.IsDocumentRoot())
+ if (structuralTypeBuilder.Metadata is not IConventionEntityType entityType
+ || entityType.IsDocumentRoot())
{
- base.ProcessDiscriminatorPropertySet(entityTypeBuilder, name, context);
+ base.ProcessDiscriminatorPropertySet(structuralTypeBuilder, name, context);
}
}
diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs
index 45d69cae227..c3748e1974c 100644
--- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs
+++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs
@@ -174,16 +174,10 @@ private void ProcessEntityType(IConventionEntityType entityType, IConventionCont
}
// Don't chain, because each of these could return null if the property has been explicitly configured with some other value.
- computedIdPropertyBuilder = computedIdPropertyBuilder.ToJsonProperty(IdPropertyJsonName)
- ?? computedIdPropertyBuilder;
-
- computedIdPropertyBuilder = computedIdPropertyBuilder.IsRequired(true)
- ?? computedIdPropertyBuilder;
-
- computedIdPropertyBuilder = computedIdPropertyBuilder.HasValueGeneratorFactory(typeof(IdValueGeneratorFactory))
- ?? computedIdPropertyBuilder;
-
+ computedIdPropertyBuilder.ToJsonProperty(IdPropertyJsonName);
+ computedIdPropertyBuilder.HasValueGeneratorFactory(typeof(IdValueGeneratorFactory));
computedIdPropertyBuilder.AfterSave(PropertySaveBehavior.Throw);
+ computedIdPropertyBuilder.IsRequired(true);
}
///
@@ -327,8 +321,13 @@ public virtual void ProcessModelAnnotationChanged(
///
public virtual void ProcessDiscriminatorPropertySet(
- IConventionEntityTypeBuilder entityTypeBuilder,
+ IConventionTypeBaseBuilder structuralTypeBuilder,
string? name,
IConventionContext context)
- => ProcessEntityType(entityTypeBuilder.Metadata, context);
+ {
+ if (structuralTypeBuilder is IConventionEntityTypeBuilder entityTypeBuilder)
+ {
+ ProcessEntityType(entityTypeBuilder.Metadata, context);
+ }
+ }
}
diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
index d5efd7f6a81..6eaa03404eb 100644
--- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
+++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
@@ -628,9 +628,60 @@ protected virtual void GenerateComplexPropertyAnnotations(
IComplexProperty property,
IndentedStringBuilder stringBuilder)
{
+ var discriminatorProperty = property.ComplexType.FindDiscriminatorProperty();
+ if (discriminatorProperty != null)
+ {
+ stringBuilder
+ .AppendLine()
+ .Append(propertyBuilderName)
+ .Append('.')
+ .Append("HasDiscriminator");
+
+ if (discriminatorProperty.DeclaringType == property.ComplexType
+ && discriminatorProperty.Name != "Discriminator")
+ {
+ var propertyClrType = FindValueConverter(discriminatorProperty)?.ProviderClrType
+ .MakeNullable(discriminatorProperty.IsNullable)
+ ?? discriminatorProperty.ClrType;
+ stringBuilder
+ .Append('<')
+ .Append(Code.Reference(propertyClrType))
+ .Append(">(")
+ .Append(Code.Literal(discriminatorProperty.Name))
+ .Append(')');
+ }
+ else
+ {
+ stringBuilder
+ .Append("()");
+ }
+
+ var discriminatorValue = property.ComplexType.GetDiscriminatorValue();
+ if (discriminatorValue != null)
+ {
+ if (discriminatorProperty != null)
+ {
+ var valueConverter = FindValueConverter(discriminatorProperty);
+ if (valueConverter != null)
+ {
+ discriminatorValue = valueConverter.ConvertToProvider(discriminatorValue);
+ }
+ }
+
+ stringBuilder
+ .Append('.')
+ .Append("HasValue")
+ .Append('(')
+ .Append(Code.UnknownLiteral(discriminatorValue))
+ .Append(')');
+ }
+
+ stringBuilder.AppendLine(";");
+ }
+
var propertyAnnotations = Dependencies.AnnotationCodeGenerator
- .FilterIgnoredAnnotations(property.GetAnnotations())
- .ToDictionary(a => a.Name, a => a);
+ .FilterIgnoredAnnotations(property.GetAnnotations())
+ .ToDictionary(a => a.Name, a => a);
var typeAnnotations = Dependencies.AnnotationCodeGenerator
.FilterIgnoredAnnotations(property.ComplexType.GetAnnotations())
diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs
index 78b54d3c672..ad23c6aacac 100644
--- a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs
+++ b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs
@@ -925,14 +925,6 @@ private void Create(IEntityType entityType, CSharpRuntimeAnnotationCodeGenerator
.Append(_code.Literal(entityType.HasSharedClrType));
}
- var discriminatorProperty = entityType.GetDiscriminatorPropertyName();
- if (discriminatorProperty != null)
- {
- mainBuilder.AppendLine(",")
- .Append("discriminatorProperty: ")
- .Append(_code.Literal(discriminatorProperty));
- }
-
var changeTrackingStrategy = entityType.GetChangeTrackingStrategy();
if (changeTrackingStrategy != ChangeTrackingStrategy.Snapshot)
{
@@ -959,6 +951,14 @@ private void Create(IEntityType entityType, CSharpRuntimeAnnotationCodeGenerator
.Append(_code.Literal(true));
}
+ var discriminatorProperty = entityType.GetDiscriminatorPropertyName();
+ if (discriminatorProperty != null)
+ {
+ mainBuilder.AppendLine(",")
+ .Append("discriminatorProperty: ")
+ .Append(_code.Literal(discriminatorProperty));
+ }
+
var discriminatorValue = entityType.GetDiscriminatorValue();
if (discriminatorValue != null)
{
@@ -2182,6 +2182,24 @@ private void CreateComplexProperty(
.Append(_code.Literal(true));
}
+ var discriminatorPropertyName = complexType.GetDiscriminatorPropertyName();
+ if (discriminatorPropertyName != null)
+ {
+ mainBuilder.AppendLine(",")
+ .Append("discriminatorProperty: ")
+ .Append(_code.Literal(discriminatorPropertyName));
+ }
+
+ var discriminatorValue = complexType.GetDiscriminatorValue();
+ if (discriminatorValue != null)
+ {
+ AddNamespace(discriminatorValue.GetType(), parameters.Namespaces);
+
+ mainBuilder.AppendLine(",")
+ .Append("discriminatorValue: ")
+ .Append(_code.UnknownLiteral(discriminatorValue));
+ }
+
mainBuilder.AppendLine(",")
.Append("propertyCount: ")
.Append(_code.Literal(complexType.GetDeclaredProperties().Count()));
diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
index a2bd60aaecc..84bf260d1ec 100644
--- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
+++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
@@ -1957,6 +1957,11 @@ protected override void ValidateInheritanceMapping(
var discriminatorValues = new Dictionary();
foreach (var derivedType in derivedTypes)
{
+ foreach (var complexProperty in derivedType.GetDeclaredComplexProperties())
+ {
+ ValidateDiscriminatorValues(complexProperty.ComplexType);
+ }
+
var discriminatorValue = derivedType.GetDiscriminatorValue();
if (!derivedType.ClrType.IsInstantiable()
|| discriminatorValue is null)
diff --git a/src/EFCore.Relational/Metadata/Conventions/DiscriminatorLengthConvention.cs b/src/EFCore.Relational/Metadata/Conventions/DiscriminatorLengthConvention.cs
index cb149ff89f4..5c9fee094a2 100644
--- a/src/EFCore.Relational/Metadata/Conventions/DiscriminatorLengthConvention.cs
+++ b/src/EFCore.Relational/Metadata/Conventions/DiscriminatorLengthConvention.cs
@@ -54,7 +54,7 @@ public virtual void ProcessModelFinalizing(IConventionModelBuilder modelBuilder,
&& !discriminatorProperty.IsForeignKey())
{
var maxDiscriminatorValueLength =
- entityType.GetDerivedTypesInclusive().Select(e => ((string)e.GetDiscriminatorValue()!).Length).Max();
+ entityType.GetDerivedTypesInclusive().Select(e => (e.GetDiscriminatorValue() as string)?.Length ?? 0).Max();
var previous = 1;
var current = 1;
diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs
index 9012bc3a4bc..a6b08037638 100644
--- a/src/EFCore/Infrastructure/ModelValidator.cs
+++ b/src/EFCore/Infrastructure/ModelValidator.cs
@@ -640,12 +640,16 @@ protected virtual void ValidateInheritanceMapping(
/// The entity type to validate.
protected virtual void ValidateDiscriminatorValues(IEntityType rootEntityType)
{
- var derivedTypes = rootEntityType.GetDerivedTypesInclusive().ToList();
+ var derivedTypes = rootEntityType.GetDerivedTypesInclusive();
var discriminatorProperty = rootEntityType.FindDiscriminatorProperty();
if (discriminatorProperty == null)
{
- if (derivedTypes.Count == 1)
+ if (!derivedTypes.Skip(1).Any())
{
+ foreach (var complexProperty in rootEntityType.GetDeclaredComplexProperties())
+ {
+ ValidateDiscriminatorValues(complexProperty.ComplexType);
+ }
return;
}
@@ -654,6 +658,68 @@ protected virtual void ValidateDiscriminatorValues(IEntityType rootEntityType)
}
var discriminatorValues = new Dictionary