diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs
index a61e3593523..1329ff21646 100644
--- a/src/EFCore/Infrastructure/ModelValidator.cs
+++ b/src/EFCore/Infrastructure/ModelValidator.cs
@@ -99,7 +99,6 @@ protected virtual void ValidateEntityType(
ValidateInheritanceMapping(entityType, logger);
ValidateFieldMapping(entityType, logger);
ValidateQueryFilters(entityType, logger);
- ValidateConstructorBindingAutoLoaded(entityType);
foreach (var property in entityType.GetDeclaredProperties())
{
@@ -139,30 +138,6 @@ protected virtual void ValidateEntityType(
LogShadowProperties(entityType, logger);
}
- ///
- /// Validates that no constructor-bound property is configured as not auto-loaded.
- ///
- /// The structural type to validate.
- protected virtual void ValidateConstructorBindingAutoLoaded(ITypeBase structuralType)
- {
- if (structuralType.ConstructorBinding is null)
- {
- return;
- }
-
- var typeName = structuralType.DisplayName();
-
- foreach (var consumedProperty in structuralType.ConstructorBinding.ParameterBindings
- .SelectMany(p => p.ConsumedProperties))
- {
- if (consumedProperty is IProperty { IsAutoLoaded: false } property)
- {
- throw new InvalidOperationException(
- CoreStrings.AutoLoadedConstructorProperty(property.Name, typeName));
- }
- }
- }
-
///
/// Validates inheritance mapping for an entity type.
///
@@ -196,7 +171,8 @@ protected virtual void ValidateProperty(
}
///
- /// Validates that a property configured as not auto-loaded is not a key, foreign key, concurrency token or discriminator.
+ /// Validates that a property configured as not auto-loaded is not a key, foreign key, concurrency token, discriminator,
+ /// or consumed by a constructor binding.
///
/// The property to validate.
/// The structural type containing the property.
@@ -237,6 +213,18 @@ protected virtual void ValidateAutoLoaded(
throw new InvalidOperationException(
CoreStrings.AutoLoadedDiscriminatorProperty(property.Name, typeName));
}
+
+ foreach (var derivedType in structuralType.GetDerivedTypesInclusive())
+ {
+ if (derivedType.ConstructorBinding is not null
+ && derivedType.ConstructorBinding.ParameterBindings
+ .SelectMany(p => p.ConsumedProperties)
+ .Contains(property))
+ {
+ throw new InvalidOperationException(
+ CoreStrings.AutoLoadedConstructorProperty(property.Name, derivedType.DisplayName()));
+ }
+ }
}
///
@@ -251,7 +239,6 @@ protected virtual void ValidateComplexProperty(
var complexType = complexProperty.ComplexType;
ValidateChangeTrackingStrategy(complexType, logger);
- ValidateConstructorBindingAutoLoaded(complexType);
foreach (var property in complexType.GetDeclaredProperties())
{
diff --git a/src/EFCore/Query/Internal/StructuralTypeMaterializerSource.cs b/src/EFCore/Query/Internal/StructuralTypeMaterializerSource.cs
index 93a6e1b7304..2bbe52d34a4 100644
--- a/src/EFCore/Query/Internal/StructuralTypeMaterializerSource.cs
+++ b/src/EFCore/Query/Internal/StructuralTypeMaterializerSource.cs
@@ -75,7 +75,7 @@ public Expression CreateMaterializeExpression(
bindingInfo.ServiceInstances.Add(instanceVariable);
var properties = new HashSet(
- structuralType.GetProperties().Cast().Where(p => !p.IsShadowProperty() && p is not IProperty { IsAutoLoaded: false })
+ structuralType.GetProperties().Where(p => !p.IsShadowProperty() && p.IsAutoLoaded).Cast()
.Concat(structuralType.GetComplexProperties().Where(p => !p.IsShadowProperty())));
var blockExpressions = new List();
diff --git a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs
index f91c1a1297d..15de51f6f04 100644
--- a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs
+++ b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs
@@ -2392,6 +2392,27 @@ public virtual void Detects_constructor_bound_property_not_auto_loaded()
modelBuilder);
}
+ [ConditionalFact]
+ public virtual void Detects_derived_constructor_bound_property_not_auto_loaded()
+ {
+ var modelBuilder = CreateConventionModelBuilder();
+ modelBuilder.Entity(
+ eb =>
+ {
+ eb.Property(e => e.Id);
+ eb.Property(e => e.Name);
+ });
+ modelBuilder.Entity();
+
+ var model = modelBuilder.Model;
+ var property = model.FindEntityType(typeof(AutoLoadBaseEntity))!.FindProperty(nameof(AutoLoadBaseEntity.Name))!;
+ property.IsAutoLoaded = false;
+
+ VerifyError(
+ CoreStrings.AutoLoadedConstructorProperty(nameof(AutoLoadBaseEntity.Name), nameof(AutoLoadDerivedEntityWithConstructor)),
+ modelBuilder);
+ }
+
protected class AutoLoadEntity
{
public int Id { get; set; }
@@ -2420,4 +2441,18 @@ protected class AutoLoadDependent
public int Id { get; set; }
public int PrincipalId { get; set; }
}
+
+ protected class AutoLoadBaseEntity
+ {
+ public int Id { get; set; }
+ public string Name { get; set; } = null!;
+ }
+
+ protected class AutoLoadDerivedEntityWithConstructor : AutoLoadBaseEntity
+ {
+ public AutoLoadDerivedEntityWithConstructor(string name)
+ {
+ Name = name;
+ }
+ }
}