From cb2015bc7f392a8bc9721cbd75cf4734a295ac0e Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 4 Feb 2023 13:14:00 +0000 Subject: [PATCH] Throw for ad-hoc type with property that looks like collection navigation Fixes #30056 --- src/EFCore/Infrastructure/ModelValidator.cs | 8 +++++--- .../Query/SqlQueryTestBase.cs | 11 +++++++++++ .../TestModels/Northwind/UnmappedCustomer.cs | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index 0c31c05dd13..3e732be0f2d 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -206,13 +206,15 @@ protected virtual void ValidatePropertyMapping( continue; } + var isAdHoc = Equals(model.FindAnnotation(CoreAnnotationNames.AdHocModel)?.Value, true); if (targetType != null) { var targetShared = conventionModel.IsShared(targetType); targetOwned ??= IsOwned(targetType, conventionModel); // ReSharper disable CheckForReferenceEqualityInstead.1 // ReSharper disable CheckForReferenceEqualityInstead.3 - if ((!entityType.IsKeyless + if ((isAdHoc + || !entityType.IsKeyless || targetSequenceType == null) && entityType.GetDerivedTypes().All( dt => dt.GetDeclaredNavigations().FirstOrDefault(n => n.Name == clrProperty.GetSimpleMemberName()) @@ -237,7 +239,7 @@ protected virtual void ValidatePropertyMapping( } throw new InvalidOperationException( - Equals(model.FindAnnotation(CoreAnnotationNames.AdHocModel)?.Value, true) + isAdHoc ? CoreStrings.NavigationNotAddedAdHoc( entityType.DisplayName(), clrProperty.Name, propertyType.ShortDisplayName()) : CoreStrings.NavigationNotAdded( @@ -257,7 +259,7 @@ protected virtual void ValidatePropertyMapping( else { throw new InvalidOperationException( - Equals(model.FindAnnotation(CoreAnnotationNames.AdHocModel)?.Value, true) + isAdHoc ? CoreStrings.PropertyNotAddedAdHoc( entityType.DisplayName(), clrProperty.Name, propertyType.ShortDisplayName()) : CoreStrings.PropertyNotAdded( diff --git a/test/EFCore.Relational.Specification.Tests/Query/SqlQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/SqlQueryTestBase.cs index b8a29a75ba5..d53381ea2d6 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/SqlQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/SqlQueryTestBase.cs @@ -1225,6 +1225,17 @@ public virtual void Ad_hoc_type_with_reference_navigation_throws() () => context.Database.SqlQueryRaw(NormalizeDelimitersInRawString(@"SELECT * FROM [Posts]"))).Message); } + [ConditionalFact] // Issue #30056 + public virtual void Ad_hoc_type_with_collection_navigation_throws() + { + using var context = CreateContext(); + + Assert.Equal( + CoreStrings.NavigationNotAddedAdHoc("Blog", "Posts", "List"), + Assert.Throws( + () => context.Database.SqlQueryRaw(NormalizeDelimitersInRawString(@"SELECT * FROM [Blogs]"))).Message); + } + [ConditionalFact] public virtual void Ad_hoc_type_with_unmapped_property_throws() { diff --git a/test/EFCore.Specification.Tests/TestModels/Northwind/UnmappedCustomer.cs b/test/EFCore.Specification.Tests/TestModels/Northwind/UnmappedCustomer.cs index c71cfa403d1..6344b2e15e6 100644 --- a/test/EFCore.Specification.Tests/TestModels/Northwind/UnmappedCustomer.cs +++ b/test/EFCore.Specification.Tests/TestModels/Northwind/UnmappedCustomer.cs @@ -55,7 +55,7 @@ public UnmappedCustomer(string customerID) public bool IsLondon => City == "London"; - // Unmapped collection navigations are ignored for keyless entity types + [NotMapped] public virtual List? Orders { get; set; } public static UnmappedCustomer FromCustomer(Customer customer)