diff --git a/src/EFCore/Metadata/ContextParameterBinding.cs b/src/EFCore/Metadata/ContextParameterBinding.cs index 891ac18ef97..bf64f074872 100644 --- a/src/EFCore/Metadata/ContextParameterBinding.cs +++ b/src/EFCore/Metadata/ContextParameterBinding.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -57,7 +55,7 @@ var propertyExpression /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) - => new ContextParameterBinding(ParameterType, consumedProperties.SingleOrDefault()); + public override ParameterBinding With(IPropertyBase[] consumedProperties) + => new ContextParameterBinding(ParameterType, consumedProperties); } } diff --git a/src/EFCore/Metadata/Conventions/SlimModelConvention.cs b/src/EFCore/Metadata/Conventions/SlimModelConvention.cs index 19535629e47..dbca447aecf 100644 --- a/src/EFCore/Metadata/Conventions/SlimModelConvention.cs +++ b/src/EFCore/Metadata/Conventions/SlimModelConvention.cs @@ -222,7 +222,7 @@ private ParameterBinding Create(ParameterBinding parameterBinding, SlimEntityTyp (entityType.FindProperty(property.Name) ?? entityType.FindServiceProperty(property.Name) ?? entityType.FindNavigation(property.Name) - ?? (IPropertyBase?)entityType.FindSkipNavigation(property.Name))!).ToList()); + ?? (IPropertyBase?)entityType.FindSkipNavigation(property.Name))!).ToArray()); private InstantiationBinding? Create(InstantiationBinding? instantiationBinding, SlimEntityType entityType) => instantiationBinding?.With(instantiationBinding.ParameterBindings.Select(binding => Create(binding, entityType)).ToList()); diff --git a/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs b/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs index 14f2e2b5dfb..75442fe9264 100644 --- a/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs +++ b/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs @@ -89,7 +89,7 @@ public override Expression BindToParameter( /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) - => new DependencyInjectionMethodParameterBinding(ParameterType, ServiceType, Method, consumedProperties.SingleOrDefault()); + public override ParameterBinding With(IPropertyBase[] consumedProperties) + => new DependencyInjectionMethodParameterBinding(ParameterType, ServiceType, Method, consumedProperties); } } diff --git a/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs b/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs index ece99ddb8d8..ad9e27a6fb3 100644 --- a/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs +++ b/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -65,7 +63,7 @@ public override Expression BindToParameter( /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) - => new DependencyInjectionParameterBinding(ParameterType, ServiceType, consumedProperties.SingleOrDefault()); + public override ParameterBinding With(IPropertyBase[] consumedProperties) + => new DependencyInjectionParameterBinding(ParameterType, ServiceType, consumedProperties); } } diff --git a/src/EFCore/Metadata/EntityTypeParameterBinding.cs b/src/EFCore/Metadata/EntityTypeParameterBinding.cs index 1b807653c4b..e65b1b48e50 100644 --- a/src/EFCore/Metadata/EntityTypeParameterBinding.cs +++ b/src/EFCore/Metadata/EntityTypeParameterBinding.cs @@ -1,8 +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 System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Utilities; @@ -40,7 +38,7 @@ public override Expression BindToParameter( /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) - => new EntityTypeParameterBinding(consumedProperties.SingleOrDefault()); + public override ParameterBinding With(IPropertyBase[] consumedProperties) + => new EntityTypeParameterBinding(consumedProperties); } } diff --git a/src/EFCore/Metadata/ObjectArrayParameterBinding.cs b/src/EFCore/Metadata/ObjectArrayParameterBinding.cs index 93a377b9eb2..a8388b1e969 100644 --- a/src/EFCore/Metadata/ObjectArrayParameterBinding.cs +++ b/src/EFCore/Metadata/ObjectArrayParameterBinding.cs @@ -57,13 +57,13 @@ public override Expression BindToParameter(ParameterBindingInfo bindingInfo) /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) + public override ParameterBinding With(IPropertyBase[] consumedProperties) { var newBindings = new List(_bindings.Count); var propertyCount = 0; foreach (var binding in _bindings) { - var newBinding = binding.With(consumedProperties.Skip(propertyCount).Take(binding.ConsumedProperties.Count).ToList()); + var newBinding = binding.With(consumedProperties.Skip(propertyCount).Take(binding.ConsumedProperties.Count).ToArray()); newBindings.Add(newBinding); propertyCount += binding.ConsumedProperties.Count; } diff --git a/src/EFCore/Metadata/ParameterBinding.cs b/src/EFCore/Metadata/ParameterBinding.cs index 2dbbf777c19..fc38720d3cf 100644 --- a/src/EFCore/Metadata/ParameterBinding.cs +++ b/src/EFCore/Metadata/ParameterBinding.cs @@ -52,6 +52,6 @@ protected ParameterBinding( /// /// The new consumed properties. /// A copy with replaced consumed properties. - public abstract ParameterBinding With(IReadOnlyList consumedProperties); + public abstract ParameterBinding With(IPropertyBase[] consumedProperties); } } diff --git a/src/EFCore/Metadata/PropertyParameterBinding.cs b/src/EFCore/Metadata/PropertyParameterBinding.cs index 9bdf9ad1abe..ea75b3dd5da 100644 --- a/src/EFCore/Metadata/PropertyParameterBinding.cs +++ b/src/EFCore/Metadata/PropertyParameterBinding.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 System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -43,7 +42,7 @@ public override Expression BindToParameter(ParameterBindingInfo bindingInfo) /// /// The new consumed properties. /// A copy with replaced consumed properties. - public override ParameterBinding With(IReadOnlyList consumedProperties) + public override ParameterBinding With(IPropertyBase[] consumedProperties) => new PropertyParameterBinding((IProperty)consumedProperties.Single()); } } diff --git a/test/EFCore.Tests/Metadata/Conventions/ServicePropertyDiscoveryConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/ServicePropertyDiscoveryConventionTest.cs index e6275e0f5d9..e5e6026572e 100644 --- a/test/EFCore.Tests/Metadata/Conventions/ServicePropertyDiscoveryConventionTest.cs +++ b/test/EFCore.Tests/Metadata/Conventions/ServicePropertyDiscoveryConventionTest.cs @@ -31,7 +31,7 @@ public void Finds_service_properties_in_hierarchy() using (var context = new ServicePropertiesContext()) { var entityTypes = context.Model.GetEntityTypes().ToList(); - Assert.Equal(10, entityTypes.Count); + Assert.Equal(13, entityTypes.Count); foreach (var entityType in entityTypes) { @@ -93,9 +93,13 @@ public void Finds_service_properties_in_hierarchy() foreach (var entry in context.ChangeTracker.Entries()) { var clrType = entry.Metadata.ClrType; - while (clrType!.BaseType != typeof(object)) + + if (!clrType.Name.StartsWith("PrivateWithDuplicates", StringComparison.Ordinal)) { - clrType = clrType.BaseType; + while (clrType!.BaseType != typeof(object)) + { + clrType = clrType.BaseType; + } } if (clrType == typeof(PublicUnmappedBaseSuper)) @@ -247,6 +251,15 @@ public DbSet PublicMappedBaseSupers public DbSet PublicMappedBaseSubs => Set(); + public DbSet PrivateWithDuplicatesBases + => Set(); + + public DbSet PrivateWithDuplicatesSupers + => Set(); + + public DbSet PrivateWithDuplicatesSubs + => Set(); + protected internal override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity( @@ -412,6 +425,40 @@ protected class PublicMappedBaseSuper : PublicMappedBase protected class PublicMappedBaseSub : PublicMappedBaseSuper { } + + protected class PrivateWithDuplicatesBase + { + public int Id { get; set; } + private DbContext? Context { get; set; } + private DbContext? Context2 { get; set; } + private IEntityType? EntityType { get; set; } + private IEntityType? EntityType2 { get; set; } + private ILazyLoader? ALazyLoader { get; set; } + private ILazyLoader? ALazyLoader2 { get; set; } + private Action? LazyLoader { get; set; } + } + + protected class PrivateWithDuplicatesSuper : PrivateWithDuplicatesBase + { + private DbContext? Context { get; set; } + private DbContext? Context2 { get; set; } + private IEntityType? EntityType { get; set; } + private IEntityType? EntityType2 { get; set; } + private ILazyLoader? ALazyLoader { get; set; } + private ILazyLoader? ALazyLoader2 { get; set; } + private Action? LazyLoader { get; set; } + } + + protected class PrivateWithDuplicatesSub : PrivateWithDuplicatesSuper + { + private DbContext? Context { get; set; } + private DbContext? Context2 { get; set; } + private IEntityType? EntityType { get; set; } + private IEntityType? EntityType2 { get; set; } + private ILazyLoader? ALazyLoader { get; set; } + private ILazyLoader? ALazyLoader2 { get; set; } + private Action? LazyLoader { get; set; } + } } }