From 3f1b2f7ef9d037ff28a866071e532949c0f53b9e Mon Sep 17 00:00:00 2001 From: ErikEJ Date: Sun, 19 Apr 2020 14:03:22 +0200 Subject: [PATCH 1/2] Default to using Humanizer.Core as reverse engineeer pluralizer Fix test localization bug fixes #11160 --- .github/dependabot.yml | 1 + .../DesignTimeServiceCollectionExtensions.cs | 2 +- .../Design/Internal/HumanizerPluralizer.cs | 38 +++++++++++++++++++ src/EFCore.Design/EFCore.Design.csproj | 1 + .../Scaffolding/Internal/CSharpNamerTest.cs | 9 +++-- .../Internal/CSharpUniqueNamerTest.cs | 9 +++-- .../Internal/HumanizerPluralizerTest.cs | 31 +++++++++++++++ .../RelationalScaffoldingModelFactoryTest.cs | 23 ++--------- 8 files changed, 86 insertions(+), 28 deletions(-) create mode 100644 src/EFCore.Design/Design/Internal/HumanizerPluralizer.cs create mode 100644 test/EFCore.Design.Tests/Scaffolding/Internal/HumanizerPluralizerTest.cs diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 201632420b7..18c1e7019cc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,6 +6,7 @@ updates: interval: weekly allow: - dependency-name: Castle.Core + - dependency-name: Humanizer.Core - dependency-name: IdentityServer4.EntityFramework - dependency-name: Microsoft.Azure.Cosmos - dependency-name: Microsoft.CSharp diff --git a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs index 78dafa7d9ad..cc677a97990 100644 --- a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs +++ b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs @@ -77,7 +77,7 @@ public static IServiceCollection AddEntityFrameworkDesignTimeServices( .AddSingleton( new DesignTimeConnectionStringResolver(applicationServiceProviderAccessor)) .AddSingleton(reporter) - .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/EFCore.Design/Design/Internal/HumanizerPluralizer.cs b/src/EFCore.Design/Design/Internal/HumanizerPluralizer.cs new file mode 100644 index 00000000000..f228bdd962d --- /dev/null +++ b/src/EFCore.Design/Design/Internal/HumanizerPluralizer.cs @@ -0,0 +1,38 @@ +// 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 Humanizer; + +namespace Microsoft.EntityFrameworkCore.Design.Internal +{ + /// + /// 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. + /// + public class HumanizerPluralizer : IPluralizer + { + /// + /// 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. + /// + public virtual string Pluralize(string name) + { + return name?.Pluralize(inputIsKnownToBeSingular: false); + } + + /// + /// 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. + /// + public virtual string Singularize(string name) + { + return name?.Singularize(inputIsKnownToBePlural: false); + } + } +} diff --git a/src/EFCore.Design/EFCore.Design.csproj b/src/EFCore.Design/EFCore.Design.csproj index ab8b1601d28..9b7b5afd76a 100644 --- a/src/EFCore.Design/EFCore.Design.csproj +++ b/src/EFCore.Design/EFCore.Design.csproj @@ -30,6 +30,7 @@ + diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpNamerTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpNamerTest.cs index 9cd28ad5853..20dcdb974a4 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpNamerTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpNamerTest.cs @@ -1,6 +1,7 @@ // 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 Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; using Xunit; @@ -24,8 +25,8 @@ public void Sanitizes_name_with_no_singularize_or_pluralize(string input, string [InlineData("Name with no s at end", "Name_with_no_s_at_end")] public void Sanitizes_name_with_singularizer(string input, string output) { - var fakePluralizer = new RelationalDatabaseModelFactoryTest.FakePluralizer(); - Assert.Equal(output, new CSharpNamer(s => s, new CSharpUtilities(), fakePluralizer.Singularize).GetName(input)); + var pluralizer = new HumanizerPluralizer(); + Assert.Equal(output, new CSharpNamer(s => s, new CSharpUtilities(), pluralizer.Singularize).GetName(input)); } [ConditionalTheory] @@ -33,8 +34,8 @@ public void Sanitizes_name_with_singularizer(string input, string output) [InlineData("Name with no s at end", "Name_with_no_s_at_ends")] public void Sanitizes_name_with_pluralizer(string input, string output) { - var fakePluralizer = new RelationalDatabaseModelFactoryTest.FakePluralizer(); - Assert.Equal(output, new CSharpNamer(s => s, new CSharpUtilities(), fakePluralizer.Pluralize).GetName(input)); + var pluralizer = new HumanizerPluralizer(); + Assert.Equal(output, new CSharpNamer(s => s, new CSharpUtilities(), pluralizer.Pluralize).GetName(input)); } } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs index a6bad78905a..3aa970491f3 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs @@ -1,6 +1,7 @@ // 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 Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; @@ -40,8 +41,8 @@ public void Uses_comparer() [InlineData("Name with no s at end", "Name_with_no_s_at_end")] public void Singularizes_names(string input, string output) { - var fakePluralizer = new RelationalDatabaseModelFactoryTest.FakePluralizer(); - var namer = new CSharpUniqueNamer(t => t.Name, new CSharpUtilities(), fakePluralizer.Singularize); + var pluralizer = new HumanizerPluralizer(); + var namer = new CSharpUniqueNamer(t => t.Name, new CSharpUtilities(), pluralizer.Singularize); var table = new DatabaseTable { Database = new DatabaseModel(), Name = input }; Assert.Equal(output, namer.GetName(table)); } @@ -51,8 +52,8 @@ public void Singularizes_names(string input, string output) [InlineData("Name with no s at end", "Name_with_no_s_at_ends")] public void Pluralizes_names(string input, string output) { - var fakePluralizer = new RelationalDatabaseModelFactoryTest.FakePluralizer(); - var namer = new CSharpUniqueNamer(t => t.Name, new CSharpUtilities(), fakePluralizer.Pluralize); + var pluralizer = new HumanizerPluralizer(); + var namer = new CSharpUniqueNamer(t => t.Name, new CSharpUtilities(), pluralizer.Pluralize); var table = new DatabaseTable { Database = new DatabaseModel(), Name = input }; Assert.Equal(output, namer.GetName(table)); } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/HumanizerPluralizerTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/HumanizerPluralizerTest.cs new file mode 100644 index 00000000000..235dd40cbe9 --- /dev/null +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/HumanizerPluralizerTest.cs @@ -0,0 +1,31 @@ +// 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 Microsoft.EntityFrameworkCore.Design.Internal; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public class HumanizerPluralizerTest + { + [ConditionalTheory] + [InlineData("Unicorn", "Unicorns")] + [InlineData("Ox", "Oxen")] + [InlineData(null, null)] + public void Returns_expected_pluralized_name(string word, string inflected) + { + var pluralizer = new HumanizerPluralizer(); + Assert.Equal(inflected, pluralizer.Pluralize(word)); + } + + [ConditionalTheory] + [InlineData("Unicorns", "Unicorn")] + [InlineData("Oxen", "Ox")] + [InlineData(null, null)] + public void Returns_expected_singularized_name(string word, string inflected) + { + var pluralizer = new HumanizerPluralizer(); + Assert.Equal(inflected, pluralizer.Singularize(word)); + } + } +} diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 88699a5055a..551df60fd0c 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations; @@ -45,6 +46,7 @@ public RelationalDatabaseModelFactoryTest() var services = new ServiceCollection() .AddEntityFrameworkDesignTimeServices(_reporter) + .AddSingleton() .AddSingleton(); new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); @@ -1202,7 +1204,7 @@ public void Pluralization_of_entity_and_DbSet() var services = new ServiceCollection() .AddEntityFrameworkDesignTimeServices(_reporter) - .AddSingleton() + .AddSingleton() .AddSingleton(); new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); @@ -1290,7 +1292,7 @@ public void Pluralization_of_collection_navigations() var services = new ServiceCollection() .AddEntityFrameworkDesignTimeServices(_reporter) - .AddSingleton() + .AddSingleton() .AddSingleton(); new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); @@ -1526,22 +1528,5 @@ public void Column_and_table_comments() var column = model.FindEntityType("Table").GetProperty("Column"); Assert.Equal("An int column", column.GetComment()); } - - public class FakePluralizer : IPluralizer - { - public string Pluralize(string name) - { - return name.EndsWith("s") - ? name - : name + "s"; - } - - public string Singularize(string name) - { - return name.EndsWith("s") - ? name[..^1] - : name; - } - } } } From fde7352b9a2c0ed78bea249887ebc0592b725f5d Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Thu, 14 May 2020 14:56:12 -0700 Subject: [PATCH 2/2] Tools: Add --no-pluralize option --- .../Design/Internal/DatabaseOperations.cs | 5 +- .../Design/Internal/NullPluralizer.cs | 36 --- src/EFCore.Design/Design/OperationExecutor.cs | 9 +- .../Internal/IScaffoldingModelFactory.cs | 2 +- .../RelationalScaffoldingModelFactory.cs | 21 +- .../Internal/ReverseEngineerScaffolder.cs | 2 +- .../ModelReverseEngineerOptions.cs | 6 + .../tools/EntityFrameworkCore.PS2.psm1 | 6 +- .../tools/EntityFrameworkCore.psm1 | 9 + .../Properties/Resources.Designer.cs | 6 + src/dotnet-ef/Properties/Resources.resx | 3 + .../DbContextScaffoldCommand.Configure.cs | 2 + src/ef/Commands/DbContextScaffoldCommand.cs | 3 +- src/ef/IOperationExecutor.cs | 3 +- src/ef/OperationExecutorBase.cs | 6 +- src/ef/Properties/Resources.Designer.cs | 6 + src/ef/Properties/Resources.resx | 3 + .../Internal/NullPluralizerTest.cs | 28 --- .../RelationalScaffoldingModelFactoryTest.cs | 205 +++++++++++++++--- .../FakeScaffoldingModelFactory.cs | 5 +- 20 files changed, 246 insertions(+), 120 deletions(-) delete mode 100644 src/EFCore.Design/Design/Internal/NullPluralizer.cs delete mode 100644 test/EFCore.Design.Tests/Scaffolding/Internal/NullPluralizerTest.cs diff --git a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs index c076491d9d6..cc36ade6aab 100644 --- a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs +++ b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs @@ -77,7 +77,8 @@ public virtual SavedModelFiles ScaffoldContext( bool useDataAnnotations, bool overwriteFiles, bool useDatabaseNames, - bool suppressOnConfiguring) + bool suppressOnConfiguring, + bool noPluralize) { Check.NotEmpty(provider, nameof(provider)); Check.NotEmpty(connectionString, nameof(connectionString)); @@ -105,7 +106,7 @@ public virtual SavedModelFiles ScaffoldContext( var scaffoldedModel = scaffolder.ScaffoldModel( connectionString, new DatabaseModelFactoryOptions(tables, schemas), - new ModelReverseEngineerOptions { UseDatabaseNames = useDatabaseNames }, + new ModelReverseEngineerOptions { UseDatabaseNames = useDatabaseNames, NoPluralize = noPluralize }, new ModelCodeGenerationOptions { UseDataAnnotations = useDataAnnotations, diff --git a/src/EFCore.Design/Design/Internal/NullPluralizer.cs b/src/EFCore.Design/Design/Internal/NullPluralizer.cs deleted file mode 100644 index e4048758b3d..00000000000 --- a/src/EFCore.Design/Design/Internal/NullPluralizer.cs +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -namespace Microsoft.EntityFrameworkCore.Design.Internal -{ - /// - /// 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. - /// - public class NullPluralizer : IPluralizer - { - /// - /// 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. - /// - public virtual string Pluralize(string identifier) - { - return identifier; - } - - /// - /// 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. - /// - public virtual string Singularize(string identifier) - { - return identifier; - } - } -} diff --git a/src/EFCore.Design/Design/OperationExecutor.cs b/src/EFCore.Design/Design/OperationExecutor.cs index bc7996021a9..889bce8b665 100644 --- a/src/EFCore.Design/Design/OperationExecutor.cs +++ b/src/EFCore.Design/Design/OperationExecutor.cs @@ -448,6 +448,7 @@ public class ScaffoldContext : OperationBase /// useDatabaseNames--Use table and column names directly from the database. /// modelNamespace--Specify to override the namespace of the generated entity types. /// contextNamespace--Specify to override the namespace of the generated DbContext class. + /// noPluralize--Don't use the pluralizer. /// /// The operation executor. /// The . @@ -472,12 +473,13 @@ public ScaffoldContext( var overwriteFiles = (bool)args["overwriteFiles"]; var useDatabaseNames = (bool)args["useDatabaseNames"]; var suppressOnConfiguring = (bool)(args["suppressOnConfiguring"] ?? false); + var noPluralize = (bool)(args["noPluralize"] ?? false); Execute( () => executor.ScaffoldContextImpl( provider, connectionString, outputDir, outputDbContextDir, dbContextClassName, schemaFilters, tableFilters, modelNamespace, contextNamespace, useDataAnnotations, - overwriteFiles, useDatabaseNames, suppressOnConfiguring)); + overwriteFiles, useDatabaseNames, suppressOnConfiguring, noPluralize)); } } @@ -494,7 +496,8 @@ private IDictionary ScaffoldContextImpl( bool useDataAnnotations, bool overwriteFiles, bool useDatabaseNames, - bool suppressOnConfiguring) + bool suppressOnConfiguring, + bool noPluarlize) { Check.NotNull(provider, nameof(provider)); Check.NotNull(connectionString, nameof(connectionString)); @@ -504,7 +507,7 @@ private IDictionary ScaffoldContextImpl( var files = DatabaseOperations.ScaffoldContext( provider, connectionString, outputDir, outputDbContextDir, dbContextClassName, schemaFilters, tableFilters, modelNamespace, contextNamespace, useDataAnnotations, - overwriteFiles, useDatabaseNames, suppressOnConfiguring); + overwriteFiles, useDatabaseNames, suppressOnConfiguring, noPluarlize); return new Hashtable { ["ContextFile"] = files.ContextFile, ["EntityTypeFiles"] = files.AdditionalFiles.ToArray() }; } diff --git a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs index dd9f6e1882c..d1af9c6ed3a 100644 --- a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs @@ -23,6 +23,6 @@ public interface IScaffoldingModelFactory /// 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. /// - IModel Create([NotNull] DatabaseModel databaseModel, bool useDatabaseNames); + IModel Create([NotNull] DatabaseModel databaseModel, [NotNull] ModelReverseEngineerOptions options); } } diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 0bcbd093fb0..83f2e2689d9 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -35,7 +35,7 @@ public class RelationalScaffoldingModelFactory : IScaffoldingModelFactory private readonly IOperationReporter _reporter; private readonly ICandidateNamingService _candidateNamingService; private Dictionary> _columnNamers; - private bool _useDatabaseNames; + private ModelReverseEngineerOptions _options; private readonly DatabaseTable _nullTable = new DatabaseTable(); private CSharpUniqueNamer _tableNamer; private CSharpUniqueNamer _dbSetNamer; @@ -80,30 +80,31 @@ public RelationalScaffoldingModelFactory( /// 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. /// - public virtual IModel Create(DatabaseModel databaseModel, bool useDatabaseNames) + public virtual IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options) { Check.NotNull(databaseModel, nameof(databaseModel)); + Check.NotNull(options, nameof(options)); var modelBuilder = new ModelBuilder(new ConventionSet()); _tableNamer = new CSharpUniqueNamer( - useDatabaseNames + options.UseDatabaseNames ? (Func)(t => t.Name) : t => _candidateNamingService.GenerateCandidateIdentifier(t), _cSharpUtilities, - useDatabaseNames + options.UseDatabaseNames || options.NoPluralize ? (Func)null : _pluralizer.Singularize); _dbSetNamer = new CSharpUniqueNamer( - useDatabaseNames + options.UseDatabaseNames ? (Func)(t => t.Name) : t => _candidateNamingService.GenerateCandidateIdentifier(t), _cSharpUtilities, - useDatabaseNames + options.UseDatabaseNames || options.NoPluralize ? (Func)null : _pluralizer.Pluralize); _columnNamers = new Dictionary>(); - _useDatabaseNames = useDatabaseNames; + _options = options; VisitDatabaseModel(modelBuilder, databaseModel); @@ -147,7 +148,7 @@ protected virtual string GetPropertyName([NotNull] DatabaseColumn column) if (!_columnNamers.ContainsKey(table)) { - if (_useDatabaseNames) + if (_options.UseDatabaseNames) { _columnNamers.Add( table, @@ -893,7 +894,9 @@ protected virtual void AddNavigationProperties([NotNull] IMutableForeignKey fore if (!foreignKey.IsUnique && !foreignKey.IsSelfReferencing()) { - principalEndNavigationPropertyCandidateName = _pluralizer.Pluralize(principalEndNavigationPropertyCandidateName); + principalEndNavigationPropertyCandidateName = _options.NoPluralize + ? principalEndNavigationPropertyCandidateName + : _pluralizer.Pluralize(principalEndNavigationPropertyCandidateName); } var principalEndNavigationPropertyName = diff --git a/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs b/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs index 5ab7443cdd1..4105096ea30 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs @@ -125,7 +125,7 @@ public virtual ScaffoldedModel ScaffoldModel( databaseModel.RemoveAnnotation(ScaffoldingAnnotationNames.ConnectionString); } - var model = _factory.Create(databaseModel, modelOptions.UseDatabaseNames); + var model = _factory.Create(databaseModel, modelOptions); if (model == null) { diff --git a/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs b/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs index ff1e629b476..9d03ee26caa 100644 --- a/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs +++ b/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs @@ -15,5 +15,11 @@ public class ModelReverseEngineerOptions /// /// A value indicating whether to use the database schema names directly. public virtual bool UseDatabaseNames { get; set; } + + /// + /// Gets or sets a value indicating whether to use the pluralizer. + /// + /// A value indicating whether to use the pluralizer. + public virtual bool NoPluralize { get; set; } } } diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.PS2.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.PS2.psm1 index 1392590c9b0..8358ace05c7 100644 --- a/src/EFCore.Tools/tools/EntityFrameworkCore.PS2.psm1 +++ b/src/EFCore.Tools/tools/EntityFrameworkCore.PS2.psm1 @@ -190,6 +190,9 @@ function Remove-Migration( .PARAMETER ContextNamespace Specify to override the namespace for the DbContext class. +.PARAMETER NoPluralize + Don't use the pluralizer. + .LINK about_EntityFrameworkCore #> @@ -208,7 +211,8 @@ function Scaffold-DbContext( $Project, $StartupProject, $Namespace, - $ContextNamespace) + $ContextNamespace, + [switch] $NoPluralize) { throw $UpdatePowerShell } diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 index 5e813b711e7..71890671c1b 100644 --- a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 +++ b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 @@ -350,6 +350,9 @@ Register-TabExpansion Scaffold-DbContext @{ .PARAMETER ContextNamespace Specify to override the namespace for the DbContext class. +.PARAMETER NoPluralize + Don't use the pluralizer. + .PARAMETER Args Arguments passed to the application. @@ -377,6 +380,7 @@ function Scaffold-DbContext [string] $StartupProject, [string] $Namespace, [string] $ContextNamespace, + [switch] $NoPluralize, [string] $Args) $dteProject = GetProject $Project @@ -432,6 +436,11 @@ function Scaffold-DbContext $params += '--no-onconfiguring' } + if ($NoPluralize) + { + $params += '--no-pluralize' + } + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 $result = (EF $dteProject $dteStartupProject $params $Args) -join "`n" | ConvertFrom-Json diff --git a/src/dotnet-ef/Properties/Resources.Designer.cs b/src/dotnet-ef/Properties/Resources.Designer.cs index 14f40068f8f..fca960cf90a 100644 --- a/src/dotnet-ef/Properties/Resources.Designer.cs +++ b/src/dotnet-ef/Properties/Resources.Designer.cs @@ -476,6 +476,12 @@ public static string MigrationsNamespaceDescription public static string SuppressOnConfiguringDescription => GetString("SuppressOnConfiguringDescription"); + /// + /// Don't use the pluralizer. + /// + public static string NoPluralizeDescription + => GetString("NoPluralizeDescription"); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/dotnet-ef/Properties/Resources.resx b/src/dotnet-ef/Properties/Resources.resx index 77f83f97764..7ed7c08806a 100644 --- a/src/dotnet-ef/Properties/Resources.resx +++ b/src/dotnet-ef/Properties/Resources.resx @@ -333,4 +333,7 @@ Suppress generation of the DbContext.OnConfiguring() method. + + Don't use the pluralizer. + \ No newline at end of file diff --git a/src/ef/Commands/DbContextScaffoldCommand.Configure.cs b/src/ef/Commands/DbContextScaffoldCommand.Configure.cs index 63d6b189ec4..51979859c76 100644 --- a/src/ef/Commands/DbContextScaffoldCommand.Configure.cs +++ b/src/ef/Commands/DbContextScaffoldCommand.Configure.cs @@ -22,6 +22,7 @@ internal partial class DbContextScaffoldCommand : ProjectCommandBase private CommandOption _namespace; private CommandOption _contextNamespace; private CommandOption _suppressOnConfiguring; + private CommandOption _noPluralize; public override void Configure(CommandLineApplication command) { @@ -42,6 +43,7 @@ public override void Configure(CommandLineApplication command) _namespace = command.Option("-n|--namespace ", Resources.NamespaceDescription); _contextNamespace = command.Option("--context-namespace ", Resources.ContextNamespaceDescription); _suppressOnConfiguring = command.Option("--no-onconfiguring", Resources.SuppressOnConfiguringDescription); + _noPluralize = command.Option("--no-pluralize", Resources.NoPluralizeDescription); base.Configure(command); } diff --git a/src/ef/Commands/DbContextScaffoldCommand.cs b/src/ef/Commands/DbContextScaffoldCommand.cs index 642c9346778..c0a7202a400 100644 --- a/src/ef/Commands/DbContextScaffoldCommand.cs +++ b/src/ef/Commands/DbContextScaffoldCommand.cs @@ -40,7 +40,8 @@ protected override int Execute(string[] args) _useDatabaseNames.HasValue(), _namespace.Value(), _contextNamespace.Value(), - _suppressOnConfiguring.HasValue()); + _suppressOnConfiguring.HasValue(), + _noPluralize.HasValue()); if (_json.HasValue()) { ReportJsonResults(result); diff --git a/src/ef/IOperationExecutor.cs b/src/ef/IOperationExecutor.cs index 284a9a282d1..ad1300631a7 100644 --- a/src/ef/IOperationExecutor.cs +++ b/src/ef/IOperationExecutor.cs @@ -30,7 +30,8 @@ IDictionary ScaffoldContext( bool useDatabaseNames, string entityNamespace, string dbContextNamespace, - bool suppressOnConfiguring); + bool suppressOnConfiguring, + bool noPluralize); string ScriptMigration(string fromMigration, string toMigration, bool idempotent, string contextType); diff --git a/src/ef/OperationExecutorBase.cs b/src/ef/OperationExecutorBase.cs index dfbfc42eba1..3af6cff186e 100644 --- a/src/ef/OperationExecutorBase.cs +++ b/src/ef/OperationExecutorBase.cs @@ -145,7 +145,8 @@ public IDictionary ScaffoldContext( bool useDatabaseNames, string modelNamespace, string contextNamespace, - bool suppressOnConfiguring) + bool suppressOnConfiguring, + bool noPluralize) => InvokeOperation( "ScaffoldContext", new Dictionary @@ -162,7 +163,8 @@ public IDictionary ScaffoldContext( ["useDatabaseNames"] = useDatabaseNames, ["modelNamespace"] = modelNamespace, ["contextNamespace"] = contextNamespace, - ["suppressOnConfiguring"] = suppressOnConfiguring + ["suppressOnConfiguring"] = suppressOnConfiguring, + ["noPluralize"] = noPluralize }); public string ScriptMigration( diff --git a/src/ef/Properties/Resources.Designer.cs b/src/ef/Properties/Resources.Designer.cs index a4f24eab042..a31d23d62ff 100644 --- a/src/ef/Properties/Resources.Designer.cs +++ b/src/ef/Properties/Resources.Designer.cs @@ -528,6 +528,12 @@ public static string RemainingArguments([CanBeNull] object remainingArguments) public static string SuppressOnConfiguringDescription => GetString("SuppressOnConfiguringDescription"); + /// + /// Don't use the pluralizer. + /// + public static string NoPluralizeDescription + => GetString("NoPluralizeDescription"); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/ef/Properties/Resources.resx b/src/ef/Properties/Resources.resx index 5856e335f41..0de651fdc50 100644 --- a/src/ef/Properties/Resources.resx +++ b/src/ef/Properties/Resources.resx @@ -348,4 +348,7 @@ Suppress generation of the DbContext.OnConfiguring() method. + + Don't use the pluralizer. + \ No newline at end of file diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/NullPluralizerTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/NullPluralizerTest.cs deleted file mode 100644 index 746a791cf1e..00000000000 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/NullPluralizerTest.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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 Microsoft.EntityFrameworkCore.Design.Internal; -using Xunit; - -namespace Microsoft.EntityFrameworkCore -{ - public class NullPluralizerTest - { - [ConditionalFact] - public void Returns_same_name() - { - var pluralizer = new NullPluralizer(); - var name = "blogs"; - Assert.Equal(name, pluralizer.Pluralize(name)); - Assert.Equal(name, pluralizer.Singularize(name)); - } - - [ConditionalFact] - public void Returns_same_name_when_null() - { - var pluralizer = new NullPluralizer(); - Assert.Null(pluralizer.Pluralize(null)); - Assert.Null(pluralizer.Singularize(null)); - } - } -} diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index 551df60fd0c..14731dd14aa 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Scaffolding; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal; @@ -46,7 +47,6 @@ public RelationalDatabaseModelFactoryTest() var services = new ServiceCollection() .AddEntityFrameworkDesignTimeServices(_reporter) - .AddSingleton() .AddSingleton(); new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); @@ -81,7 +81,7 @@ public void Creates_entity_types() new DatabaseView { Database = Database, Name = "view" } } }; - var model = _factory.Create(info, false); + var model = _factory.Create(info, new ModelReverseEngineerOptions()); Assert.Collection( model.GetEntityTypes().OrderBy(t => t.Name).Cast(), vwtable => @@ -132,7 +132,7 @@ public void Creates_entity_types_case_insensitive() } } }; - var model = _factory.Create(info, false); + var model = _factory.Create(info, new ModelReverseEngineerOptions()); Assert.Equal(2, model.GetEntityTypes().Select(et => et.Name).Distinct(StringComparer.OrdinalIgnoreCase).Count()); } @@ -191,7 +191,7 @@ public void Loads_column_types() } }; - var entityType = (EntityType)_factory.Create(info, false).FindEntityType("Jobs"); + var entityType = (EntityType)_factory.Create(info, new ModelReverseEngineerOptions { NoPluralize = true }).FindEntityType("Jobs"); Assert.Collection( entityType.GetProperties(), @@ -256,7 +256,7 @@ public void Use_database_names_for_columns() } }; - var entityType = _factory.Create(info, useDatabaseNames: true).FindEntityType("NaturalProducts"); + var entityType = _factory.Create(info, new ModelReverseEngineerOptions { UseDatabaseNames = true }).FindEntityType("NaturalProducts"); Assert.Collection( entityType.GetProperties(), @@ -289,7 +289,7 @@ public void Do_not_use_database_names_for_columns() } }; - var entityType = _factory.Create(info, useDatabaseNames: false).FindEntityType("NaturalProducts"); + var entityType = _factory.Create(info, new ModelReverseEngineerOptions { NoPluralize = true }).FindEntityType("NaturalProducts"); Assert.Collection( entityType.GetProperties(), @@ -325,7 +325,7 @@ public void Column_type_annotation(string StoreType, string expectedColumnType) } }; - var property = (Property)_factory.Create(info, false).FindEntityType("A").FindProperty("Col"); + var property = (Property)_factory.Create(info, new ModelReverseEngineerOptions()).FindEntityType("A").FindProperty("Col"); Assert.Equal(expectedColumnType, property.GetColumnType()); } @@ -358,7 +358,7 @@ public void Column_ordinal_annotation() } }; - var entityTypeA = _factory.Create(info, false).FindEntityType("A"); + var entityTypeA = _factory.Create(info, new ModelReverseEngineerOptions()).FindEntityType("A"); var property1 = (Property)entityTypeA.FindProperty("Col1"); var property2 = (Property)entityTypeA.FindProperty("Col2"); var property3 = (Property)entityTypeA.FindProperty("Col3"); @@ -394,7 +394,7 @@ public void Unmappable_column_type(string StoreType) StoreType = StoreType }); - Assert.Single(_factory.Create(info, false).FindEntityType("E").GetProperties()); + Assert.Single(_factory.Create(info, new ModelReverseEngineerOptions()).FindEntityType("E").GetProperties()); Assert.Single(_reporter.Messages, t => t.Contains(DesignStrings.CannotFindTypeMappingForColumn("E.Coli", StoreType))); } @@ -428,7 +428,7 @@ public void Primary_key(string[] keyProps, int length) info.Tables[0].PrimaryKey.Columns.Add(column); } - var model = (EntityType)_factory.Create(info, false).GetEntityTypes().Single(); + var model = (EntityType)_factory.Create(info, new ModelReverseEngineerOptions()).GetEntityTypes().Single(); Assert.Equal("MyPk", model.FindPrimaryKey().GetName()); Assert.Equal(keyProps, model.FindPrimaryKey().Properties.Select(p => p.GetColumnName()).ToArray()); @@ -462,7 +462,7 @@ public void Unique_constraint() } }; - var entityType = (EntityType)_factory.Create(databaseModel, false).GetEntityTypes().Single(); + var entityType = (EntityType)_factory.Create(databaseModel, new ModelReverseEngineerOptions()).GetEntityTypes().Single(); var index = entityType.GetIndexes().Single(); Assert.True(index.IsUnique); @@ -525,7 +525,7 @@ public void Indexes_and_alternate_keys() var info = new DatabaseModel { Tables = { table } }; - var entityType = (EntityType)_factory.Create(info, false).GetEntityTypes().Single(); + var entityType = (EntityType)_factory.Create(info, new ModelReverseEngineerOptions()).GetEntityTypes().Single(); Assert.Collection( entityType.GetIndexes(), @@ -596,7 +596,7 @@ public void Foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions { NoPluralize = true }); var parent = (EntityType)model.FindEntityType("Parent"); @@ -641,7 +641,7 @@ public void Foreign_key_from_keyless_table() }); databaseModel.Tables.Add(detailTable); - var model = _factory.Create(databaseModel, useDatabaseNames: false); + var model = _factory.Create(databaseModel, new ModelReverseEngineerOptions()); var detail = model.FindEntityType("Detail"); var foreignKey = Assert.Single(detail.GetForeignKeys()); @@ -697,7 +697,7 @@ public void Foreign_key_to_unique_constraint() var model = _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions { NoPluralize = true }); var parent = (EntityType)model.FindEntityType("Parent"); @@ -744,7 +744,7 @@ public void Unique_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions { NoPluralize = true }); var children = (EntityType)model.FindEntityType("Children"); @@ -795,7 +795,7 @@ public void Composite_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions { NoPluralize = true }); var parent = (EntityType)model.FindEntityType("Parent"); @@ -846,7 +846,7 @@ public void It_loads_self_referencing_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { table } }, - false); + new ModelReverseEngineerOptions()); var list = model.FindEntityType("ItemsList"); Assert.NotEmpty(list.GetReferencingForeignKeys()); @@ -886,7 +886,7 @@ public void It_logs_warning_for_bad_foreign_key() _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions()); Assert.Single( _reporter.Messages, t => t.Contains( @@ -935,7 +935,7 @@ public void Unique_nullable_index_unused_by_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { table } }, - false).FindEntityType("Friends"); + new ModelReverseEngineerOptions { NoPluralize = true }).FindEntityType("Friends"); var buddyIdProperty = model.FindProperty("BuddyId"); Assert.NotNull(buddyIdProperty); @@ -988,7 +988,7 @@ public void Unique_nullable_index_used_by_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { table } }, - false).FindEntityType("Friends"); + new ModelReverseEngineerOptions { NoPluralize = true }).FindEntityType("Friends"); var buddyIdProperty = model.FindProperty("BuddyId"); Assert.NotNull(buddyIdProperty); @@ -1055,7 +1055,7 @@ public void Unique_index_composite_foreign_key() var model = _factory.Create( new DatabaseModel { Tables = { parentTable, childrenTable } }, - false); + new ModelReverseEngineerOptions { NoPluralize = true }); var parent = model.FindEntityType("Parent"); var children = model.FindEntityType("Children"); @@ -1094,7 +1094,7 @@ public void Unique_names() } }; - var model = _factory.Create(info, false); + var model = _factory.Create(info, new ModelReverseEngineerOptions()); Assert.Collection( model.GetEntityTypes().Cast(), @@ -1142,7 +1142,7 @@ public void Sequences() } }; - var model = _factory.Create(info, false); + var model = _factory.Create(info, new ModelReverseEngineerOptions()); Assert.Collection( model.GetSequences(), first => @@ -1174,7 +1174,7 @@ public void DbSet_annotation_is_set() } }; - var model = _factory.Create(info, false); + var model = _factory.Create(info, new ModelReverseEngineerOptions { NoPluralize = true }); Assert.Equal("Blog", model.GetEntityTypes().Single().GetDbSetName()); } @@ -1212,7 +1212,7 @@ public void Pluralization_of_entity_and_DbSet() .BuildServiceProvider() .GetRequiredService(); - var model = factory.Create(info, false); + var model = factory.Create(info, new ModelReverseEngineerOptions()); Assert.Collection( model.GetEntityTypes().OrderBy(t => t.Name).Cast(), @@ -1230,7 +1230,78 @@ public void Pluralization_of_entity_and_DbSet() } ); - model = factory.Create(info, true); + model = factory.Create(info, new ModelReverseEngineerOptions { UseDatabaseNames = true }); + + Assert.Collection( + model.GetEntityTypes().OrderBy(t => t.Name).Cast(), + entity => + { + Assert.Equal("Blog", entity.GetTableName()); + Assert.Equal("Blog", entity.Name); + Assert.Equal("Blog", entity.GetDbSetName()); + }, + entity => + { + Assert.Equal("Posts", entity.GetTableName()); + Assert.Equal("Posts", entity.Name); + Assert.Equal("Posts", entity.GetDbSetName()); + } + ); + } + + [ConditionalFact] + public void Pluralization_of_entity_and_DbSet_noPluralize() + { + var info = new DatabaseModel + { + Tables = + { + new DatabaseTable + { + Database = Database, + Name = "Blog", + Columns = { IdColumn }, + PrimaryKey = IdPrimaryKey + }, + new DatabaseTable + { + Database = Database, + Name = "Posts", + Columns = { IdColumn }, + PrimaryKey = IdPrimaryKey + } + } + }; + + var services = new ServiceCollection() + .AddEntityFrameworkDesignTimeServices(_reporter) + .AddSingleton() + .AddSingleton(); + new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); + + var factory = services + .BuildServiceProvider() + .GetRequiredService(); + + var model = factory.Create(info, new ModelReverseEngineerOptions { NoPluralize = true }); + + Assert.Collection( + model.GetEntityTypes().OrderBy(t => t.Name).Cast(), + entity => + { + Assert.Equal("Blog", entity.GetTableName()); + Assert.Equal("Blog", entity.Name); + Assert.Equal("Blog", entity.GetDbSetName()); + }, + entity => + { + Assert.Equal("Posts", entity.GetTableName()); + Assert.Equal("Posts", entity.Name); + Assert.Equal("Posts", entity.GetDbSetName()); + } + ); + + model = factory.Create(info, new ModelReverseEngineerOptions { UseDatabaseNames = true, NoPluralize = true }); Assert.Collection( model.GetEntityTypes().OrderBy(t => t.Name).Cast(), @@ -1300,7 +1371,7 @@ public void Pluralization_of_collection_navigations() .BuildServiceProvider() .GetRequiredService(); - var model = factory.Create(info, false); + var model = factory.Create(info, new ModelReverseEngineerOptions()); Assert.Collection( model.GetEntityTypes().OrderBy(t => t.Name).Cast(), @@ -1317,6 +1388,74 @@ public void Pluralization_of_collection_navigations() ); } + [ConditionalFact] + public void Pluralization_of_collection_navigations_noPluralize() + { + 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 = "BlogId", + 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 services = new ServiceCollection() + .AddEntityFrameworkDesignTimeServices(_reporter) + .AddSingleton() + .AddSingleton(); + new SqlServerDesignTimeServices().ConfigureDesignTimeServices(services); + + var factory = services + .BuildServiceProvider() + .GetRequiredService(); + + var model = factory.Create(info, new ModelReverseEngineerOptions { NoPluralize = true }); + + Assert.Collection( + model.GetEntityTypes().OrderBy(t => t.Name).Cast(), + entity => + { + Assert.Equal("Blog", entity.Name); + Assert.Equal("Post", entity.GetNavigations().Single().Name); + }, + entity => + { + Assert.Equal("Post", entity.Name); + Assert.Equal("Blog", entity.GetNavigations().Single().Name); + } + ); + } + [ConditionalFact] public void Not_null_bool_column_with_default_value_is_made_nullable() { @@ -1352,7 +1491,7 @@ public void Not_null_bool_column_with_default_value_is_made_nullable() } }; - var model = _factory.Create(dbModel, false); + var model = _factory.Create(dbModel, new ModelReverseEngineerOptions()); var columns = model.FindEntityType("Table").GetProperties().ToList(); @@ -1391,7 +1530,7 @@ public void Nullable_column_with_default_value_sql_does_not_generate_warning() } }; - var model = _factory.Create(dbModel, false); + var model = _factory.Create(dbModel, new ModelReverseEngineerOptions()); var columns = model.FindEntityType("Table").GetProperties().ToList(); @@ -1458,7 +1597,7 @@ public void Correct_arguments_to_scaffolding_typemapper() var dbModel = new DatabaseModel { Tables = { principalTable, dependentTable } }; - var model = _factory.Create(dbModel, false); + var model = _factory.Create(dbModel, new ModelReverseEngineerOptions()); Assert.Null(model.FindEntityType("Principal").FindProperty("PrimaryKey").GetColumnType()); Assert.Null(model.FindEntityType("Principal").FindProperty("AlternateKey").GetColumnType()); @@ -1486,7 +1625,7 @@ public void Unmapped_column_is_ignored() } }; - var model = _factory.Create(dbModel, false); + var model = _factory.Create(dbModel, new ModelReverseEngineerOptions()); var columns = model.FindEntityType("Table").GetProperties().ToList(); @@ -1520,7 +1659,7 @@ public void Column_and_table_comments() } }; - var model = _factory.Create(database, useDatabaseNames: false); + var model = _factory.Create(database, new ModelReverseEngineerOptions()); var table = model.FindEntityType("Table"); Assert.Equal("A table", table.GetComment()); diff --git a/test/EFCore.Design.Tests/TestUtilities/FakeScaffoldingModelFactory.cs b/test/EFCore.Design.Tests/TestUtilities/FakeScaffoldingModelFactory.cs index 85e1e75b0b1..6fbeae95790 100644 --- a/test/EFCore.Design.Tests/TestUtilities/FakeScaffoldingModelFactory.cs +++ b/test/EFCore.Design.Tests/TestUtilities/FakeScaffoldingModelFactory.cs @@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Scaffolding; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; @@ -24,7 +25,7 @@ public FakeScaffoldingModelFactory( { } - public override IModel Create(DatabaseModel databaseModel, bool useDatabaseNames) + public override IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options) { foreach (var sequence in databaseModel.Sequences) { @@ -67,7 +68,7 @@ public override IModel Create(DatabaseModel databaseModel, bool useDatabaseNames } } - return base.Create(databaseModel, useDatabaseNames); + return base.Create(databaseModel, options); } private static void FixupColumns(DatabaseTable table, IList columns)