From 6f6354333c2b5de7c43d97fcdd5991117b6530ef Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 14 Sep 2022 17:41:40 -0700 Subject: [PATCH] Scaffolding: Generate better navigation name when FK property ends with guid Resolves #26990 --- .../Internal/CandidateNamingService.cs | 9 +- .../RelationalScaffoldingModelFactoryTest.cs | 148 ++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs index 5570a0aaa02..9b752e43526 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs @@ -145,8 +145,15 @@ private static string StripId(string commonPrefix) return commonPrefix; } + var ignoredCharacterCount = 2; + if (commonPrefix.Length > 4 + && commonPrefix.EndsWith("guid", StringComparison.OrdinalIgnoreCase)) + { + ignoredCharacterCount = 4; + } + int i; - for (i = commonPrefix.Length - 3; i >= 0; i--) + for (i = commonPrefix.Length - ignoredCharacterCount - 1; i >= 0; i--) { if (char.IsLetterOrDigit(commonPrefix[i])) { diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 4ed24857daa..abbd3bea032 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -2452,4 +2452,152 @@ public void Scaffold_skip_navigation_for_many_to_many_join_table_self_ref() Assert.Equal(2, t2.GetForeignKeys().Count()); }); } + + [ConditionalFact] + public void Fk_property_ending_in_guid_navigation_name() + { + var blogTable = new DatabaseTable + { + Database = Database, + Name = "Blog", + Columns = { IdColumn }, + PrimaryKey = IdPrimaryKey + }; + var postTable = new DatabaseTable + { + Database = Database, + Name = "Post", + Columns = + { + IdColumn, + new DatabaseColumn + { + Table = Table, + Name = "BlogGuid", + StoreType = "int", + IsNullable = true + } + }, + PrimaryKey = IdPrimaryKey + }; + + postTable.ForeignKeys.Add( + new DatabaseForeignKey + { + Table = postTable, + Name = "FK_Foo", + Columns = { postTable.Columns.ElementAt(1) }, + PrincipalTable = blogTable, + PrincipalColumns = { blogTable.Columns.ElementAt(0) }, + OnDelete = ReferentialAction.Cascade + }); + + var info = new DatabaseModel { Tables = { blogTable, postTable } }; + + var model = _factory.Create(info, new ModelReverseEngineerOptions()); + + Assert.Collection( + model.GetEntityTypes().OrderBy(t => t.Name).Cast(), + entity => + { + Assert.Equal("Blog", entity.Name); + Assert.Equal("Posts", entity.GetNavigations().Single().Name); + }, + entity => + { + Assert.Equal("Post", entity.Name); + Assert.Equal("Blog", entity.GetNavigations().Single().Name); + } + ); + } + + [ConditionalFact] + public void Composite_fk_property_ending_in_guid_navigation_name() + { + var blogTable = new DatabaseTable + { + Database = Database, + Name = "Blog", + Columns = + { + IdColumn, + new DatabaseColumn + { + Table = Table, + Name = "BlogGuid1", + StoreType = "int", + IsNullable = false + }, + new DatabaseColumn + { + Table = Table, + Name = "BlogGuid2", + StoreType = "int", + IsNullable = false + } + }, + PrimaryKey = IdPrimaryKey + }; + var postTable = new DatabaseTable + { + Database = Database, + Name = "Post", + Columns = + { + IdColumn, + new DatabaseColumn + { + Table = Table, + Name = "BlogGuid1", + StoreType = "int", + IsNullable = true + }, + new DatabaseColumn + { + Table = Table, + Name = "BlogGuid2", + StoreType = "int", + IsNullable = true + } + }, + PrimaryKey = IdPrimaryKey + }; + + blogTable.UniqueConstraints.Add( + new DatabaseUniqueConstraint + { + Table = blogTable, + Name = "AK_Foo", + Columns = { blogTable.Columns.ElementAt(1), blogTable.Columns.ElementAt(2) } + }); + + postTable.ForeignKeys.Add( + new DatabaseForeignKey + { + Table = postTable, + Name = "FK_Foo", + Columns = { postTable.Columns.ElementAt(1), postTable.Columns.ElementAt(2) }, + PrincipalTable = blogTable, + PrincipalColumns = { blogTable.Columns.ElementAt(1), blogTable.Columns.ElementAt(2) }, + OnDelete = ReferentialAction.Cascade + }); + + var info = new DatabaseModel { Tables = { blogTable, postTable } }; + + var model = _factory.Create(info, new ModelReverseEngineerOptions()); + + Assert.Collection( + model.GetEntityTypes().OrderBy(t => t.Name).Cast(), + entity => + { + Assert.Equal("Blog", entity.Name); + Assert.Equal("Posts", entity.GetNavigations().Single().Name); + }, + entity => + { + Assert.Equal("Post", entity.Name); + Assert.Equal("Blog", entity.GetNavigations().Single().Name); + } + ); + } }