From 24364e342f73374701816fc34cf00fb7b932a2dd Mon Sep 17 00:00:00 2001 From: ilmalte <17677294+ilmalte@users.noreply.github.com> Date: Fri, 6 May 2022 19:12:24 +0200 Subject: [PATCH 1/3] Capitalize database name - When scaffolding from a database the database name is modified in order to respect .NET conventions #Fixes 27886 --- .../Scaffolding/Internal/CandidateNamingService.cs | 9 +++++++++ .../Scaffolding/Internal/ICandidateNamingService.cs | 8 ++++++++ .../Internal/RelationalScaffoldingModelFactory.cs | 6 +++++- .../Internal/RelationalScaffoldingModelFactoryTest.cs | 8 ++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs index 5cb31203222..1410d2b49ca 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs @@ -32,6 +32,15 @@ public virtual string GenerateCandidateIdentifier(DatabaseTable originalTable) public virtual string GenerateCandidateIdentifier(DatabaseColumn originalColumn) => GenerateCandidateIdentifier(originalColumn.Name); + /// <summary> + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// </summary> + public virtual string GenerateCandidateIdentifier(DatabaseModel originalModel) + => GenerateCandidateIdentifier(originalModel.DatabaseName ?? "Main"); + /// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs index 45bf5e1c8c0..bbae18e6edd 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs @@ -29,6 +29,14 @@ public interface ICandidateNamingService /// </summary> string GenerateCandidateIdentifier(DatabaseColumn originalColumn); + /// <summary> + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// </summary> + string GenerateCandidateIdentifier(DatabaseModel databaseName); + /// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 839dfbcf7c4..71e4ad5fea0 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -166,7 +166,11 @@ protected virtual ModelBuilder VisitDatabaseModel(ModelBuilder modelBuilder, Dat if (!string.IsNullOrEmpty(databaseModel.DatabaseName)) { - modelBuilder.Model.SetDatabaseName(databaseModel.DatabaseName); + if (_options.UseDatabaseNames) + { + modelBuilder.Model.SetDatabaseName( + _candidateNamingService.GenerateCandidateIdentifier(databaseModel)); + } } if (!string.IsNullOrEmpty(databaseModel.Collation)) diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 6cf32d7cebf..575833b8d10 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -50,6 +50,14 @@ public RelationalScaffoldingModelFactoryTest() _reporter.Clear(); } + [ConditionalFact] + public void Capitalize_DatabaseName() + { + var database = new DatabaseModel { DatabaseName = "northwind" }; + var model = _factory.Create(database, new ModelReverseEngineerOptions { UseDatabaseNames = true }); + Assert.Equal("Northwind", model.GetDatabaseName()); + } + [ConditionalFact] public void Creates_entity_types() { From 9d458f8754edefa2321279cede4ef8d067c69b72 Mon Sep 17 00:00:00 2001 From: ilmalte <17677294+ilmalte@users.noreply.github.com> Date: Mon, 16 May 2022 17:43:15 +0200 Subject: [PATCH 2/3] Capitalize database name - When scaffolding from a database the database name is modified in order to respect .NET conventions #Fixes 27886 --- .../Internal/CandidateNamingService.cs | 17 +++++++-------- .../Internal/ICandidateNamingService.cs | 3 ++- .../RelationalScaffoldingModelFactory.cs | 9 ++++---- .../RelationalScaffoldingModelFactoryTest.cs | 21 +++++++++++++++++++ 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs index 1410d2b49ca..5570a0aaa02 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs @@ -32,15 +32,6 @@ public virtual string GenerateCandidateIdentifier(DatabaseTable originalTable) public virtual string GenerateCandidateIdentifier(DatabaseColumn originalColumn) => GenerateCandidateIdentifier(originalColumn.Name); - /// <summary> - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// </summary> - public virtual string GenerateCandidateIdentifier(DatabaseModel originalModel) - => GenerateCandidateIdentifier(originalModel.DatabaseName ?? "Main"); - /// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -74,7 +65,13 @@ public virtual string GetPrincipalEndCandidateNavigationPropertyName( : foreignKey.DeclaringEntityType.ShortName(); } - private static string GenerateCandidateIdentifier(string originalIdentifier) + /// <summary> + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// </summary> + public virtual string GenerateCandidateIdentifier(string originalIdentifier) { var candidateStringBuilder = new StringBuilder(); var previousLetterCharInWordIsLowerCase = false; diff --git a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs index bbae18e6edd..16a22718321 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs @@ -35,7 +35,8 @@ public interface ICandidateNamingService /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> - string GenerateCandidateIdentifier(DatabaseModel databaseName); + string GenerateCandidateIdentifier(string databaseName); + /// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 71e4ad5fea0..e0c2fc90d7f 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -166,11 +166,10 @@ protected virtual ModelBuilder VisitDatabaseModel(ModelBuilder modelBuilder, Dat if (!string.IsNullOrEmpty(databaseModel.DatabaseName)) { - if (_options.UseDatabaseNames) - { - modelBuilder.Model.SetDatabaseName( - _candidateNamingService.GenerateCandidateIdentifier(databaseModel)); - } + modelBuilder.Model.SetDatabaseName( + _options.UseDatabaseNames && !string.IsNullOrEmpty(databaseModel.DatabaseName) + ? _candidateNamingService.GenerateCandidateIdentifier(databaseModel.DatabaseName) + : databaseModel.DatabaseName); } if (!string.IsNullOrEmpty(databaseModel.Collation)) diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 575833b8d10..47ceb9167af 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -139,6 +139,27 @@ public void Creates_entity_types_case_insensitive() Assert.Equal(2, model.GetEntityTypes().Select(et => et.Name).Distinct(StringComparer.OrdinalIgnoreCase).Count()); } + [ConditionalTheory] + [InlineData("PascalCase")] + [InlineData("camelCase")] + [InlineData("snake-case")] + [InlineData("MixedCASE")] + [InlineData("separated_by_underscores")] + [InlineData("PascalCase_withUnderscore")] + [InlineData("ALL_CAPS")] + [InlineData("numbers0Dont1Affect23Upper45Case678To9LowerCase10Boundary999")] + [InlineData("We1!*~&%rdCh@r^act()0rs")] + public void Get_DatabaseName(string expectedValue) + { + var options = new ModelReverseEngineerOptions { UseDatabaseNames = false }; + + var database = new DatabaseModel { DatabaseName = expectedValue }; + var model = _factory.Create(database, options); + Assert.Equal(expectedValue, model.GetDatabaseName()); + + } + + [ConditionalFact] public void Loads_column_types() { From 0cdf4334829b759dbd5dad3df056f1edf7137005 Mon Sep 17 00:00:00 2001 From: "Maltese, Daniele" <daniele.maltese@swatchgroup.com> Date: Wed, 18 May 2022 18:16:29 +0200 Subject: [PATCH 3/3] Capitalize database name - When scaffolding from a database the database name is modified in order to respect .NET conventions #Fixes 27886 --- .../Scaffolding/Internal/RelationalScaffoldingModelFactory.cs | 2 +- .../Internal/RelationalScaffoldingModelFactoryTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index e0c2fc90d7f..2ce3b6ab19e 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -167,7 +167,7 @@ protected virtual ModelBuilder VisitDatabaseModel(ModelBuilder modelBuilder, Dat if (!string.IsNullOrEmpty(databaseModel.DatabaseName)) { modelBuilder.Model.SetDatabaseName( - _options.UseDatabaseNames && !string.IsNullOrEmpty(databaseModel.DatabaseName) + !_options.UseDatabaseNames && !string.IsNullOrEmpty(databaseModel.DatabaseName) ? _candidateNamingService.GenerateCandidateIdentifier(databaseModel.DatabaseName) : databaseModel.DatabaseName); } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 47ceb9167af..2741df760e7 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -54,7 +54,7 @@ public RelationalScaffoldingModelFactoryTest() public void Capitalize_DatabaseName() { var database = new DatabaseModel { DatabaseName = "northwind" }; - var model = _factory.Create(database, new ModelReverseEngineerOptions { UseDatabaseNames = true }); + var model = _factory.Create(database, new ModelReverseEngineerOptions { UseDatabaseNames = false }); Assert.Equal("Northwind", model.GetDatabaseName()); } @@ -151,7 +151,7 @@ public void Creates_entity_types_case_insensitive() [InlineData("We1!*~&%rdCh@r^act()0rs")] public void Get_DatabaseName(string expectedValue) { - var options = new ModelReverseEngineerOptions { UseDatabaseNames = false }; + var options = new ModelReverseEngineerOptions { UseDatabaseNames = true }; var database = new DatabaseModel { DatabaseName = expectedValue }; var model = _factory.Create(database, options);