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);