From 547e38c7124273d759835cf868787b164285f630 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sat, 14 Dec 2019 12:30:06 +0100 Subject: [PATCH] Nullability annotation for scaffolding Resubmitting after reverted by cb686e849b448ebbafe9dfee5288d4610bc9823c (cherry picked from commit eab93affafa766d446ea5d530574c82e6a558359) --- .../Scaffolding/IModelCodeGenerator.cs | 2 + .../IModelCodeGeneratorSelector.cs | 4 +- .../Scaffolding/IReverseEngineerScaffolder.cs | 4 +- .../Internal/CSharpDbContextGenerator.cs | 6 +- .../Internal/CSharpEntityTypeGenerator.cs | 4 +- .../Internal/CSharpModelGenerator.cs | 33 +- .../Scaffolding/Internal/CSharpNamer.cs | 6 +- .../Scaffolding/Internal/CSharpUniqueNamer.cs | 8 +- .../Scaffolding/Internal/CSharpUtilities.cs | 16 +- .../Internal/CandidateNamingService.cs | 10 +- .../Internal/ICSharpDbContextGenerator.cs | 4 +- .../Internal/ICSharpEntityTypeGenerator.cs | 2 + .../Scaffolding/Internal/ICSharpUtilities.cs | 12 +- .../Internal/ICandidateNamingService.cs | 2 + .../Internal/IScaffoldingModelFactory.cs | 2 + .../Internal/IScaffoldingTypeMapper.cs | 4 +- .../Internal/ModelCodeGeneratorSelector.cs | 2 + .../RelationalScaffoldingModelFactory.cs | 9 +- .../Internal/ReverseEngineerScaffolder.cs | 4 + .../Internal/ScaffoldingTypeMapper.cs | 4 +- .../Internal/TypeScaffoldingInfo.cs | 2 + .../Internal/DatabaseColumnExtensions.cs | 7 +- .../Internal/DatabaseForeignKeyExtensions.cs | 4 +- .../Internal/DatabaseTableExtensions.cs | 2 + .../Scaffolding/ModelCodeGenerationOptions.cs | 16 +- .../Scaffolding/ModelCodeGenerator.cs | 2 + .../ModelCodeGeneratorDependencies.cs | 2 + .../ModelReverseEngineerOptions.cs | 2 + .../Scaffolding/SavedModelFiles.cs | 2 + .../Scaffolding/ScaffoldedFile.cs | 8 + .../Scaffolding/ScaffoldedModel.cs | 7 + .../Scaffolding/DatabaseModelFactory.cs | 2 + .../DatabaseModelFactoryOptions.cs | 4 +- .../Scaffolding/IDatabaseModelFactory.cs | 2 + .../IProviderCodeGeneratorPlugin.cs | 6 +- .../IProviderConfigurationCodeGenerator.cs | 8 +- .../Scaffolding/Metadata/DatabaseColumn.cs | 17 +- .../Metadata/DatabaseForeignKey.cs | 24 +- .../Scaffolding/Metadata/DatabaseIndex.cs | 15 +- .../Scaffolding/Metadata/DatabaseModel.cs | 6 +- .../Metadata/DatabasePrimaryKey.cs | 13 +- .../Scaffolding/Metadata/DatabaseSequence.cs | 12 +- .../Scaffolding/Metadata/DatabaseTable.cs | 26 +- .../Metadata/DatabaseUniqueConstraint.cs | 13 +- .../Scaffolding/Metadata/DatabaseView.cs | 8 + .../Scaffolding/ProviderCodeGenerator.cs | 12 +- .../ProviderCodeGeneratorDependencies.cs | 2 + .../ProviderCodeGeneratorPlugin.cs | 6 +- .../Internal/SqlDataReaderExtension.cs | 20 +- .../Internal/SqlServerCodeGenerator.cs | 4 +- .../Internal/SqlServerDatabaseModelFactory.cs | 99 ++--- .../Internal/SqliteCodeGenerator.cs | 4 +- .../Internal/SqliteDatabaseModelFactory.cs | 223 +++++----- .../Internal/CSharpUniqueNamerTest.cs | 14 +- .../Internal/CandidateNamingServiceTest.cs | 2 +- .../RelationalScaffoldingModelFactoryTest.cs | 388 ++++++------------ .../Internal/ReverseEngineerScaffolderTest.cs | 22 +- 57 files changed, 583 insertions(+), 561 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs index d518e19dcef..0f9abec94f8 100644 --- a/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs b/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs index 46de04887fe..f81edc330e3 100644 --- a/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs +++ b/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -15,6 +17,6 @@ public interface IModelCodeGeneratorSelector /// /// The programming language. /// The . - IModelCodeGenerator Select([CanBeNull] string language); + IModelCodeGenerator Select([CanBeNull] string? language); } } diff --git a/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs b/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs index 6ddccb99c6b..38aa4616713 100644 --- a/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs +++ b/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -33,7 +35,7 @@ ScaffoldedModel ScaffoldModel( /// The model files. SavedModelFiles Save( [NotNull] ScaffoldedModel scaffoldedModel, - [CanBeNull] string outputDir, + [NotNull] string outputDir, bool overwriteFiles); } } diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs index 924c5e76d08..406e2ae7059 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs @@ -15,6 +15,8 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -31,7 +33,7 @@ public class CSharpDbContextGenerator : ICSharpDbContextGenerator private readonly ICSharpHelper _code; private readonly IProviderConfigurationCodeGenerator _providerConfigurationCodeGenerator; private readonly IAnnotationCodeGenerator _annotationCodeGenerator; - private IndentedStringBuilder _sb; + private IndentedStringBuilder _sb = null!; private bool _entityTypeBuilderInitialized; /// @@ -64,7 +66,7 @@ public virtual string WriteCode( IModel model, string contextName, string connectionString, - string contextNamespace, + string? contextNamespace, string modelNamespace, bool useDataAnnotations, bool suppressConnectionStringWarning) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs index 01a3c02d0f8..85cc555c21b 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs @@ -14,6 +14,8 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -26,7 +28,7 @@ public class CSharpEntityTypeGenerator : ICSharpEntityTypeGenerator { private readonly ICSharpHelper _code; - private IndentedStringBuilder _sb; + private IndentedStringBuilder _sb = null!; private bool _useDataAnnotations; /// diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpModelGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpModelGenerator.cs index 7b3c038789b..e5035711312 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpModelGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpModelGenerator.cs @@ -1,11 +1,14 @@ // 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 System; using System.IO; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -74,7 +77,20 @@ public override ScaffoldedModel GenerateModel( Check.NotNull(model, nameof(model)); Check.NotNull(options, nameof(options)); - var resultingFiles = new ScaffoldedModel(); + if (options.ContextName == null) + { + throw new ArgumentException($"{nameof(options.ContextName)} cannot be null", nameof(options)); + } + + if (options.ConnectionString == null) + { + throw new ArgumentException($"{nameof(options.ConnectionString)} cannot be null", nameof(options)); + } + + if (options.ModelNamespace == null) + { + throw new ArgumentException($"{nameof(options.ModelNamespace)} cannot be null", nameof(options)); + } var generatedCode = CSharpDbContextGenerator.WriteCode( model, @@ -87,13 +103,12 @@ public override ScaffoldedModel GenerateModel( // output DbContext .cs file var dbContextFileName = options.ContextName + FileExtension; - resultingFiles.ContextFile = new ScaffoldedFile - { - Path = options.ContextDir != null - ? Path.Combine(options.ContextDir, dbContextFileName) - : dbContextFileName, - Code = generatedCode - }; + var resultingFiles = new ScaffoldedModel( + new ScaffoldedFile( + options.ContextDir != null + ? Path.Combine(options.ContextDir, dbContextFileName) + : dbContextFileName, + generatedCode)); foreach (var entityType in model.GetEntityTypes()) { @@ -102,7 +117,7 @@ public override ScaffoldedModel GenerateModel( // output EntityType poco .cs file var entityTypeFileName = entityType.DisplayName() + FileExtension; resultingFiles.AdditionalFiles.Add( - new ScaffoldedFile { Path = entityTypeFileName, Code = generatedCode }); + new ScaffoldedFile(entityTypeFileName, generatedCode)); } return resultingFiles; diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpNamer.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpNamer.cs index c1360dac86d..e652888e230 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpNamer.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpNamer.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -18,7 +20,7 @@ public class CSharpNamer { private readonly Func _nameGetter; private readonly ICSharpUtilities _cSharpUtilities; - private readonly Func _singularizePluralizer; + private readonly Func? _singularizePluralizer; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -37,7 +39,7 @@ public class CSharpNamer public CSharpNamer( [NotNull] Func nameGetter, [NotNull] ICSharpUtilities cSharpUtilities, - [CanBeNull] Func singularizePluralizer) + [CanBeNull] Func? singularizePluralizer) { Check.NotNull(nameGetter, nameof(nameGetter)); Check.NotNull(cSharpUtilities, nameof(cSharpUtilities)); diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpUniqueNamer.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpUniqueNamer.cs index b05c7a2d1d0..7e832373135 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpUniqueNamer.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpUniqueNamer.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -26,7 +28,7 @@ public class CSharpUniqueNamer : CSharpNamer public CSharpUniqueNamer( [NotNull] Func nameGetter, [NotNull] ICSharpUtilities cSharpUtilities, - [CanBeNull] Func singularizePluralizer) + [CanBeNull] Func? singularizePluralizer) : this(nameGetter, null, cSharpUtilities, singularizePluralizer) { } @@ -39,9 +41,9 @@ public CSharpUniqueNamer( /// public CSharpUniqueNamer( [NotNull] Func nameGetter, - [CanBeNull] IEnumerable usedNames, + [CanBeNull] IEnumerable? usedNames, [NotNull] ICSharpUtilities cSharpUtilities, - [CanBeNull] Func singularizePluralizer) + [CanBeNull] Func? singularizePluralizer) : base(nameGetter, cSharpUtilities, singularizePluralizer) { if (usedNames != null) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs index 637039bce31..f0c9f329f5c 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpUtilities.cs @@ -8,6 +8,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -122,8 +124,8 @@ public virtual bool IsCSharpKeyword(string identifier) /// public virtual string GenerateCSharpIdentifier( string identifier, - ICollection existingIdentifiers, - Func singularizePluralizer) + ICollection? existingIdentifiers, + Func? singularizePluralizer) => GenerateCSharpIdentifier(identifier, existingIdentifiers, singularizePluralizer, Uniquifier); /// @@ -134,9 +136,9 @@ public virtual string GenerateCSharpIdentifier( /// public virtual string GenerateCSharpIdentifier( string identifier, - ICollection existingIdentifiers, - Func singularizePluralizer, - Func, string> uniquifier) + ICollection? existingIdentifiers, + Func? singularizePluralizer, + Func?, string> uniquifier) { Check.NotNull(identifier, nameof(identifier)); Check.NotNull(uniquifier, nameof(uniquifier)); @@ -177,7 +179,7 @@ public virtual string GenerateCSharpIdentifier( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual string Uniquifier( - [NotNull] string proposedIdentifier, [CanBeNull] ICollection existingIdentifiers) + [NotNull] string proposedIdentifier, [CanBeNull] ICollection? existingIdentifiers) { Check.NotEmpty(proposedIdentifier, nameof(proposedIdentifier)); @@ -203,7 +205,7 @@ public virtual string Uniquifier( /// 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 bool IsValidIdentifier(string name) + public virtual bool IsValidIdentifier(string? name) { if (string.IsNullOrEmpty(name)) { diff --git a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs index e8f50874bee..cdbfadacc6f 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CandidateNamingService.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -26,9 +28,7 @@ public class CandidateNamingService : ICandidateNamingService /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual string GenerateCandidateIdentifier(DatabaseTable originalTable) - { - return GenerateCandidateIdentifier(originalTable.Name); - } + => GenerateCandidateIdentifier(originalTable.Name); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -37,9 +37,7 @@ public virtual string GenerateCandidateIdentifier(DatabaseTable originalTable) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual string GenerateCandidateIdentifier(DatabaseColumn originalColumn) - { - return GenerateCandidateIdentifier(originalColumn.Name); - } + => GenerateCandidateIdentifier(originalColumn.Name); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs index 59378ed88d5..5504b5feabf 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICSharpDbContextGenerator.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -24,7 +26,7 @@ string WriteCode( [NotNull] IModel model, [NotNull] string contextName, [NotNull] string connectionString, - [NotNull] string contextNamespace, + [CanBeNull] string? contextNamespace, [NotNull] string modelNamespace, bool useDataAnnotations, bool suppressConnectionStringWarning); diff --git a/src/EFCore.Design/Scaffolding/Internal/ICSharpEntityTypeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/ICSharpEntityTypeGenerator.cs index 3bc6ea0fcd8..a494517220b 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICSharpEntityTypeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICSharpEntityTypeGenerator.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/Internal/ICSharpUtilities.cs b/src/EFCore.Design/Scaffolding/Internal/ICSharpUtilities.cs index b9c278d543a..b2b7c7f7e05 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICSharpUtilities.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICSharpUtilities.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -22,8 +24,8 @@ public interface ICSharpUtilities /// doing so can result in application failures when updating to a new Entity Framework Core release. /// string GenerateCSharpIdentifier( - [NotNull] string identifier, [CanBeNull] ICollection existingIdentifiers, - [CanBeNull] Func singularizePluralizer); + [NotNull] string identifier, [CanBeNull] ICollection? existingIdentifiers, + [CanBeNull] Func? singularizePluralizer); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -32,8 +34,8 @@ string GenerateCSharpIdentifier( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// string GenerateCSharpIdentifier( - [NotNull] string identifier, [CanBeNull] ICollection existingIdentifiers, - [CanBeNull] Func singularizePluralizer, [NotNull] Func, string> uniquifier); + [NotNull] string identifier, [CanBeNull] ICollection? existingIdentifiers, + [CanBeNull] Func? singularizePluralizer, [NotNull] Func?, string> uniquifier); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -49,6 +51,6 @@ string GenerateCSharpIdentifier( /// 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. /// - bool IsValidIdentifier([CanBeNull] string name); + bool IsValidIdentifier([CanBeNull] string? name); } } diff --git a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs index 6897c0f62b4..8765255feed 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ICandidateNamingService.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs index 9c13e8bd54e..dd9f6e1882c 100644 --- a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingModelFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingTypeMapper.cs b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingTypeMapper.cs index cce7a6eb0c0..9e7d10697c7 100644 --- a/src/EFCore.Design/Scaffolding/Internal/IScaffoldingTypeMapper.cs +++ b/src/EFCore.Design/Scaffolding/Internal/IScaffoldingTypeMapper.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -19,6 +21,6 @@ public interface IScaffoldingTypeMapper /// 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. /// - TypeScaffoldingInfo FindMapping([NotNull] string storeType, bool keyOrIndex, bool rowVersion); + TypeScaffoldingInfo? FindMapping([NotNull] string storeType, bool keyOrIndex, bool rowVersion); } } diff --git a/src/EFCore.Design/Scaffolding/Internal/ModelCodeGeneratorSelector.cs b/src/EFCore.Design/Scaffolding/Internal/ModelCodeGeneratorSelector.cs index dc01f69a7f3..5bbd2fa7b21 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ModelCodeGeneratorSelector.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ModelCodeGeneratorSelector.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Design.Internal; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 5f43665105a..d85751c9799 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -36,7 +36,6 @@ public class RelationalScaffoldingModelFactory : IScaffoldingModelFactory private readonly ICandidateNamingService _candidateNamingService; private Dictionary> _columnNamers; private bool _useDatabaseNames; - private readonly DatabaseTable _nullTable = new DatabaseTable(); private CSharpUniqueNamer _tableNamer; private CSharpUniqueNamer _dbSetNamer; private readonly HashSet _unmappedColumns = new HashSet(); @@ -138,12 +137,8 @@ protected virtual string GetPropertyName([NotNull] DatabaseColumn column) { Check.NotNull(column, nameof(column)); - var table = column.Table ?? _nullTable; - var usedNames = new List(); - if (column.Table != null) - { - usedNames.Add(GetEntityTypeName(table)); - } + var table = column.Table; + var usedNames = new List { GetEntityTypeName(table) }; if (!_columnNamers.ContainsKey(table)) { diff --git a/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs b/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs index 3aed6b2e3dd..f4f37147ef7 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs @@ -15,6 +15,8 @@ using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -50,7 +52,9 @@ public ReverseEngineerScaffolder( Check.NotNull(databaseModelFactory, nameof(databaseModelFactory)); Check.NotNull(scaffoldingModelFactory, nameof(scaffoldingModelFactory)); Check.NotNull(modelCodeGeneratorSelector, nameof(modelCodeGeneratorSelector)); + Check.NotNull(cSharpUtilities, nameof(cSharpUtilities)); Check.NotNull(cSharpHelper, nameof(cSharpHelper)); + Check.NotNull(connectionStringResolver, nameof(connectionStringResolver)); _databaseModelFactory = databaseModelFactory; _factory = scaffoldingModelFactory; diff --git a/src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs b/src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs index ec7518babff..4bdc90a0c3c 100644 --- a/src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs +++ b/src/EFCore.Design/Scaffolding/Internal/ScaffoldingTypeMapper.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// @@ -37,7 +39,7 @@ public ScaffoldingTypeMapper([NotNull] IRelationalTypeMappingSource typeMappingS /// 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 TypeScaffoldingInfo FindMapping( + public virtual TypeScaffoldingInfo? FindMapping( string storeType, bool keyOrIndex, bool rowVersion) diff --git a/src/EFCore.Design/Scaffolding/Internal/TypeScaffoldingInfo.cs b/src/EFCore.Design/Scaffolding/Internal/TypeScaffoldingInfo.cs index 8decdb9a7e9..6baa1219495 100644 --- a/src/EFCore.Design/Scaffolding/Internal/TypeScaffoldingInfo.cs +++ b/src/EFCore.Design/Scaffolding/Internal/TypeScaffoldingInfo.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseColumnExtensions.cs b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseColumnExtensions.cs index 1cf7bbe3698..2a3174758ba 100644 --- a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseColumnExtensions.cs +++ b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseColumnExtensions.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal { /// @@ -23,10 +25,7 @@ public static class DatabaseColumnExtensions /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static string DisplayName([NotNull] this DatabaseColumn column) - { - var tablePrefix = column.Table?.DisplayName(); - return (!string.IsNullOrEmpty(tablePrefix) ? tablePrefix + "." : "") + column.Name; - } + => column.Table.DisplayName() + "." + column.Name; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseForeignKeyExtensions.cs b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseForeignKeyExtensions.cs index 808ae435b46..e94dda70d51 100644 --- a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseForeignKeyExtensions.cs +++ b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseForeignKeyExtensions.cs @@ -4,6 +4,8 @@ using System.Linq; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal { /// @@ -21,6 +23,6 @@ public static class DatabaseForeignKeyExtensions /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static string DisplayName([NotNull] this DatabaseForeignKey foreignKey) - => foreignKey.Table?.DisplayName() + "(" + string.Join(",", foreignKey.Columns.Select(f => f.Name)) + ")"; + => foreignKey.Table.DisplayName() + "(" + string.Join(",", foreignKey.Columns.Select(f => f.Name)) + ")"; } } diff --git a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseTableExtensions.cs b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseTableExtensions.cs index 048cef1f1b0..f81a2911507 100644 --- a/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseTableExtensions.cs +++ b/src/EFCore.Design/Scaffolding/Metadata/Internal/DatabaseTableExtensions.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal { /// diff --git a/src/EFCore.Design/Scaffolding/ModelCodeGenerationOptions.cs b/src/EFCore.Design/Scaffolding/ModelCodeGenerationOptions.cs index 0472df26887..0b2320efc05 100644 --- a/src/EFCore.Design/Scaffolding/ModelCodeGenerationOptions.cs +++ b/src/EFCore.Design/Scaffolding/ModelCodeGenerationOptions.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -26,42 +28,42 @@ public class ModelCodeGenerationOptions /// Gets or sets the namespace of the project. /// /// The namespace of the project. - public virtual string RootNamespace { get; [param: CanBeNull] set; } + public virtual string? RootNamespace { get; [param: CanBeNull] set; } /// /// Gets or sets the namespace for model classes. /// /// The namespace for model classes. - public virtual string ModelNamespace { get; [param: CanBeNull] set; } + public virtual string? ModelNamespace { get; [param: CanBeNull] set; } /// /// Gets or sets the namespace for context class. /// /// The namespace for context class. - public virtual string ContextNamespace { get; [param: CanBeNull] set; } + public virtual string? ContextNamespace { get; [param: CanBeNull] set; } /// /// Gets or sets the programming language to scaffold for. /// /// The programming language to scaffold for. - public virtual string Language { get; [param: CanBeNull] set; } + public virtual string? Language { get; [param: CanBeNull] set; } /// /// Gets or sets the DbContext output directory. /// /// The DbContext output directory. - public virtual string ContextDir { get; [param: CanBeNull] set; } + public virtual string? ContextDir { get; [param: CanBeNull] set; } /// /// Gets or sets the name. /// /// The name. - public virtual string ContextName { get; [param: CanBeNull] set; } + public virtual string? ContextName { get; [param: CanBeNull] set; } /// /// Gets or sets the connection string. /// /// The connection string. - public virtual string ConnectionString { get; [param: CanBeNull] set; } + public virtual string? ConnectionString { get; [param: CanBeNull] set; } } } diff --git a/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs index bcb5100c1e2..6cd483c0009 100644 --- a/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs b/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs index fd082781cc9..9e0a8301fb7 100644 --- a/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs +++ b/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs @@ -3,6 +3,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs b/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs index 5d15c60383b..ff1e629b476 100644 --- a/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs +++ b/src/EFCore.Design/Scaffolding/ModelReverseEngineerOptions.cs @@ -1,6 +1,8 @@ // 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. +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Design/Scaffolding/SavedModelFiles.cs b/src/EFCore.Design/Scaffolding/SavedModelFiles.cs index 111e08a937a..9d819a6af75 100644 --- a/src/EFCore.Design/Scaffolding/SavedModelFiles.cs +++ b/src/EFCore.Design/Scaffolding/SavedModelFiles.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Design/Scaffolding/ScaffoldedFile.cs b/src/EFCore.Design/Scaffolding/ScaffoldedFile.cs index 0de071738a2..74f075faffb 100644 --- a/src/EFCore.Design/Scaffolding/ScaffoldedFile.cs +++ b/src/EFCore.Design/Scaffolding/ScaffoldedFile.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -10,6 +12,12 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// public class ScaffoldedFile { + public ScaffoldedFile([NotNull] string path, [NotNull] string code) + { + Path = path; + Code = code; + } + /// /// Gets or sets the path. /// diff --git a/src/EFCore.Design/Scaffolding/ScaffoldedModel.cs b/src/EFCore.Design/Scaffolding/ScaffoldedModel.cs index d8041c17e43..7c55b54254e 100644 --- a/src/EFCore.Design/Scaffolding/ScaffoldedModel.cs +++ b/src/EFCore.Design/Scaffolding/ScaffoldedModel.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -11,6 +13,11 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// public class ScaffoldedModel { + public ScaffoldedModel([NotNull] ScaffoldedFile contextFile) + { + ContextFile = contextFile; + } + /// /// Gets or sets the generated file containing the . /// diff --git a/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs b/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs index 5eddcdd829f..711069444ee 100644 --- a/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs +++ b/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs @@ -4,6 +4,8 @@ using System.Data.Common; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs index cd6ccd990bb..f070ce0df46 100644 --- a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs +++ b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs @@ -5,6 +5,8 @@ using System.Linq; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -17,7 +19,7 @@ public class DatabaseModelFactoryOptions /// /// A list of tables to include. Empty to include all tables. /// A list of schemas to include. Empty to include all schemas. - public DatabaseModelFactoryOptions([CanBeNull] IEnumerable tables = null, [CanBeNull] IEnumerable schemas = null) + public DatabaseModelFactoryOptions([CanBeNull] IEnumerable? tables = null, [CanBeNull] IEnumerable? schemas = null) { Tables = tables ?? Enumerable.Empty(); Schemas = schemas ?? Enumerable.Empty(); diff --git a/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs b/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs index 0113420c000..0b0163b9273 100644 --- a/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs +++ b/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs b/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs index d203069dad2..3ae09504f4b 100644 --- a/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs +++ b/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs @@ -3,6 +3,8 @@ using Microsoft.EntityFrameworkCore.Design; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -14,12 +16,12 @@ public interface IProviderCodeGeneratorPlugin /// Generates a method chain used to configure provider-specific options. /// /// The method chain. May be null. - MethodCallCodeFragment GenerateProviderOptions(); + MethodCallCodeFragment? GenerateProviderOptions(); /// /// Generates a method chain to configure additional context options. /// /// The method chain. May be null. - MethodCallCodeFragment GenerateContextOptions(); + MethodCallCodeFragment? GenerateContextOptions(); } } diff --git a/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs b/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs index a64fd02ff88..d07e83cf0a0 100644 --- a/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs +++ b/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Design; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -16,7 +18,7 @@ public interface IProviderConfigurationCodeGenerator /// Generates a method chain used to configure provider-specific options. /// /// The method chain. May be null. - MethodCallCodeFragment GenerateProviderOptions(); + MethodCallCodeFragment? GenerateProviderOptions(); /// /// Generates a code fragment like .UseSqlServer("Database=Foo") which can be used in @@ -27,12 +29,12 @@ public interface IProviderConfigurationCodeGenerator /// The code fragment. MethodCallCodeFragment GenerateUseProvider( [NotNull] string connectionString, - [CanBeNull] MethodCallCodeFragment providerOptions); + [CanBeNull] MethodCallCodeFragment? providerOptions); /// /// Generates a method chain to configure additional context options. /// /// The method chain. May be null. - MethodCallCodeFragment GenerateContextOptions(); + MethodCallCodeFragment? GenerateContextOptions(); } } diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs index 0620eb872a7..a463e9df03b 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -12,6 +14,13 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseColumn : Annotatable { + public DatabaseColumn([NotNull] DatabaseTable table, [NotNull] string name, [NotNull] string storeType) + { + Table = table; + Name = name; + StoreType = storeType; + } + /// /// The table that contains this column. /// @@ -30,22 +39,22 @@ public class DatabaseColumn : Annotatable /// /// The database/store type of the column. /// - public virtual string StoreType { get; [param: CanBeNull] set; } + public virtual string StoreType { get; [param: NotNull] set; } /// /// The default constraint for the column, or null if none. /// - public virtual string DefaultValueSql { get; [param: CanBeNull] set; } + public virtual string? DefaultValueSql { get; [param: CanBeNull] set; } /// /// The SQL expression that computes the value of the column, or null if this is not a computed column. /// - public virtual string ComputedColumnSql { get; [param: CanBeNull] set; } + public virtual string? ComputedColumnSql { get; [param: CanBeNull] set; } /// /// The column comment, or null if none is set. /// - public virtual string Comment { get; [param: CanBeNull] set; } + public virtual string? Comment { get; [param: CanBeNull] set; } /// /// Indicates when values will be generated by the database for this column, or null if diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs index d719d3e7097..b749ce1f7e9 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -13,31 +15,43 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseForeignKey : Annotatable { + public DatabaseForeignKey( + [NotNull] DatabaseTable table, + [NotNull] string name, + [NotNull] DatabaseTable principalTable) + { + Table = table; + Name = name; + PrincipalTable = principalTable; + Columns = new List(); + PrincipalColumns = new List(); + } + /// /// The table that contains the foreign key constraint. /// - public virtual DatabaseTable Table { get; [param: CanBeNull] set; } + public virtual DatabaseTable Table { get; [param: NotNull] set; } /// /// The table to which the columns are constrained. /// - public virtual DatabaseTable PrincipalTable { get; [param: CanBeNull] set; } + public virtual DatabaseTable PrincipalTable { get; [param: NotNull] set; } /// /// The ordered list of columns that are constrained. /// - public virtual IList Columns { get; } = new List(); + public virtual IList Columns { get; } /// /// The ordered list of columns in the to which the /// of the foreign key are constrained. /// - public virtual IList PrincipalColumns { get; } = new List(); + public virtual IList PrincipalColumns { get; } /// /// The foreign key constraint name. /// - public virtual string Name { get; [param: CanBeNull] set; } + public virtual string Name { get; [param: NotNull] set; } /// /// The action performed by the database when a row constrained by this foreign key diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs index 60e110e5271..d1c2ef278a4 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -12,10 +14,17 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseIndex : Annotatable { + public DatabaseIndex([NotNull] DatabaseTable table, [NotNull] string name) + { + Table = table; + Name = name; + Columns = new List(); + } + /// /// The table that contains the index. /// - public virtual DatabaseTable Table { get; [param: CanBeNull] set; } + public virtual DatabaseTable Table { get; [param: NotNull] set; } /// /// The index name. @@ -25,7 +34,7 @@ public class DatabaseIndex : Annotatable /// /// The ordered list of columns that make up the index. /// - public virtual IList Columns { get; } = new List(); + public virtual IList Columns { get; } /// /// Indicates whether or not the index constrains uniqueness. @@ -35,6 +44,6 @@ public class DatabaseIndex : Annotatable /// /// The filter expression, or null if the index has no filter. /// - public virtual string Filter { get; [param: CanBeNull] set; } + public virtual string? Filter { get; [param: CanBeNull] set; } } } diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs index 55acbbe0d26..c2ad8f2e9e4 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -15,12 +17,12 @@ public class DatabaseModel : Annotatable /// /// The database name, or null if none is set. /// - public virtual string DatabaseName { get; [param: CanBeNull] set; } + public virtual string? DatabaseName { get; [param: CanBeNull] set; } /// /// The database schema, or null to use the default schema. /// - public virtual string DefaultSchema { get; [param: CanBeNull] set; } + public virtual string? DefaultSchema { get; [param: CanBeNull] set; } /// /// The list of tables in the database. diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs index 4e7eca6bd12..175840bb830 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -12,10 +14,17 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabasePrimaryKey : Annotatable { + public DatabasePrimaryKey([NotNull] DatabaseTable table, [NotNull] string name) + { + Table = table; + Name = name; + Columns = new List(); + } + /// /// The table on which the primary key is defined. /// - public virtual DatabaseTable Table { get; [param: CanBeNull] set; } + public virtual DatabaseTable Table { get; [param: NotNull] set; } /// /// The name of the primary key. @@ -25,6 +34,6 @@ public class DatabasePrimaryKey : Annotatable /// /// The ordered list of columns that make up the primary key. /// - public virtual IList Columns { get; } = new List(); + public virtual IList Columns { get; } } } diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs index 1422ffa82d0..f1bd6b2ff25 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -11,6 +13,12 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseSequence : Annotatable { + public DatabaseSequence([NotNull] DatabaseModel database, [NotNull] string name) + { + Database = database; + Name = name; + } + /// /// The database that contains the sequence. /// @@ -24,12 +32,12 @@ public class DatabaseSequence : Annotatable /// /// The schema that contains the sequence, or null to use the default schema. /// - public virtual string Schema { get; [param: CanBeNull] set; } + public virtual string? Schema { get; [param: CanBeNull] set; } /// /// The database/store type of the sequence, or null if not set. /// - public virtual string StoreType { get; [param: CanBeNull] set; } + public virtual string? StoreType { get; [param: CanBeNull] set; } /// /// The start value for the sequence, or null if not set. diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs index 2b6ac004ac3..c85a2098122 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -12,6 +14,16 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseTable : Annotatable { + public DatabaseTable([NotNull] DatabaseModel database, [NotNull] string name) + { + Database = database; + Name = name; + Columns = new List(); + UniqueConstraints = new List(); + Indexes = new List(); + ForeignKeys = new List(); + } + /// /// The database that contains the table. /// @@ -25,36 +37,36 @@ public class DatabaseTable : Annotatable /// /// The table schema, or null to use the default schema. /// - public virtual string Schema { get; [param: CanBeNull] set; } + public virtual string? Schema { get; [param: CanBeNull] set; } /// /// The table comment, or null if none is set. /// - public virtual string Comment { get; [param: CanBeNull] set; } + public virtual string? Comment { get; [param: CanBeNull] set; } /// /// The primary key of the table. /// - public virtual DatabasePrimaryKey PrimaryKey { get; [param: CanBeNull] set; } + public virtual DatabasePrimaryKey? PrimaryKey { get; [param: CanBeNull] set; } /// /// The ordered list of columns in the table. /// - public virtual IList Columns { get; } = new List(); + public virtual IList Columns { get; } /// /// The list of unique constraints defined on the table. /// - public virtual IList UniqueConstraints { get; } = new List(); + public virtual IList UniqueConstraints { get; } /// /// The list of indexes defined on the table. /// - public virtual IList Indexes { get; } = new List(); + public virtual IList Indexes { get; } /// /// The list of foreign key constraints defined on the table. /// - public virtual IList ForeignKeys { get; } = new List(); + public virtual IList ForeignKeys { get; } } } diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs index 074354b7d26..6dac16ac7ec 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -12,10 +14,17 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseUniqueConstraint : Annotatable { + public DatabaseUniqueConstraint([NotNull] DatabaseTable table, [NotNull] string name) + { + Table = table; + Name = name; + Columns = new List(); + } + /// /// The table on which the unique constraint is defined. /// - public virtual DatabaseTable Table { get; [param: CanBeNull] set; } + public virtual DatabaseTable Table { get; [param: NotNull] set; } /// /// The name of the constraint. @@ -25,6 +34,6 @@ public class DatabaseUniqueConstraint : Annotatable /// /// The ordered list of columns that make up the constraint. /// - public virtual IList Columns { get; } = new List(); + public virtual IList Columns { get; } } } diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs index 1f936e7ad18..1723bd37cf2 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs @@ -1,6 +1,10 @@ // 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 JetBrains.Annotations; + +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata { /// @@ -8,5 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// public class DatabaseView : DatabaseTable { + public DatabaseView([NotNull] DatabaseModel database, [NotNull] string name) + : base(database, name) + { + } } } diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs index f48a8815497..fd6ee40905d 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -28,9 +30,9 @@ protected ProviderCodeGenerator([NotNull] ProviderCodeGeneratorDependencies depe /// Generates a method chain used to configure provider-specific options. /// /// The method chain. May be null. - public virtual MethodCallCodeFragment GenerateProviderOptions() + public virtual MethodCallCodeFragment? GenerateProviderOptions() { - MethodCallCodeFragment providerOptions = null; + MethodCallCodeFragment? providerOptions = null; foreach (var plugin in Dependencies.Plugins) { @@ -55,15 +57,15 @@ public virtual MethodCallCodeFragment GenerateProviderOptions() /// The code fragment. public abstract MethodCallCodeFragment GenerateUseProvider( string connectionString, - MethodCallCodeFragment providerOptions); + MethodCallCodeFragment? providerOptions); /// /// Generates a method chain to configure additional context options. /// /// The method chain. May be null. - public virtual MethodCallCodeFragment GenerateContextOptions() + public virtual MethodCallCodeFragment? GenerateContextOptions() { - MethodCallCodeFragment contextOptions = null; + MethodCallCodeFragment? contextOptions = null; foreach (var plugin in Dependencies.Plugins) { diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs index 6b5f40b1c4d..97a7e7b912e 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs index 472d9ab6174..eae9aff7fca 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs @@ -3,6 +3,8 @@ using Microsoft.EntityFrameworkCore.Design; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -14,14 +16,14 @@ public class ProviderCodeGeneratorPlugin : IProviderCodeGeneratorPlugin /// Generates a method chain used to configure provider-specific options. /// /// The method chain. May be null. - public virtual MethodCallCodeFragment GenerateContextOptions() + public virtual MethodCallCodeFragment? GenerateContextOptions() => null; /// /// Generates a method chain to configure additional context options. /// /// The method chain. May be null. - public virtual MethodCallCodeFragment GenerateProviderOptions() + public virtual MethodCallCodeFragment? GenerateProviderOptions() => null; } } diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlDataReaderExtension.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlDataReaderExtension.cs index 282fecd9616..d497bf8ff00 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlDataReaderExtension.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlDataReaderExtension.cs @@ -2,7 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Data.Common; -using JetBrains.Annotations; +using System.Diagnostics.CodeAnalysis; +using JB = JetBrains.Annotations; + +#nullable enable namespace Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal { @@ -20,7 +23,8 @@ public static class SqlDataReaderExtension /// 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 static T GetValueOrDefault([NotNull] this DbDataReader reader, [NotNull] string name) + [return: MaybeNull] + public static T GetValueOrDefault([JB.NotNull] this DbDataReader reader, [JB.NotNull] string name) { var idx = reader.GetOrdinal(name); return reader.IsDBNull(idx) @@ -34,12 +38,22 @@ public static T GetValueOrDefault([NotNull] this DbDataReader reader, [NotNul /// 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 static T GetValueOrDefault([NotNull] this DbDataRecord record, [NotNull] string name) + [return: MaybeNull] + public static T GetValueOrDefault([JB.NotNull] this DbDataRecord record, [JB.NotNull] string name) { var idx = record.GetOrdinal(name); return record.IsDBNull(idx) ? default : (T)record.GetValue(idx); } + + /// + /// 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 static T GetFieldValue([JB.NotNull] this DbDataRecord record, [JB.NotNull] string name) + => (T)record.GetValue(record.GetOrdinal(name)); } } diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerCodeGenerator.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerCodeGenerator.cs index 044de83b72c..da6e9d7e4cb 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerCodeGenerator.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerCodeGenerator.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Scaffolding; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal { /// @@ -32,7 +34,7 @@ public SqlServerCodeGenerator([NotNull] ProviderCodeGeneratorDependencies depend /// public override MethodCallCodeFragment GenerateUseProvider( string connectionString, - MethodCallCodeFragment providerOptions) + MethodCallCodeFragment? providerOptions) => new MethodCallCodeFragment( nameof(SqlServerDbContextOptionsExtensions.UseSqlServer), providerOptions == null diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index bf0902e2fb7..c2a3ee262b5 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -20,6 +20,8 @@ using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal { /// @@ -135,18 +137,10 @@ public override DatabaseModel Create(DbConnection connection, DatabaseModelFacto if (SupportsSequences(connection)) { - foreach (var sequence in GetSequences(connection, schemaFilter, typeAliases)) - { - sequence.Database = databaseModel; - databaseModel.Sequences.Add(sequence); - } + GetSequences(connection, databaseModel, schemaFilter, typeAliases); } - foreach (var table in GetTables(connection, tableFilter, typeAliases)) - { - table.Database = databaseModel; - databaseModel.Tables.Add(table); - } + GetTables(connection, databaseModel, tableFilter, typeAliases); foreach (var schema in schemaList .Except( @@ -179,7 +173,7 @@ public override DatabaseModel Create(DbConnection connection, DatabaseModelFacto } } - private string GetDefaultSchema(DbConnection connection) + private string? GetDefaultSchema(DbConnection connection) { using var command = connection.CreateCommand(); command.CommandText = "SELECT SCHEMA_NAME()"; @@ -194,7 +188,7 @@ private string GetDefaultSchema(DbConnection connection) return null; } - private static Func GenerateSchemaFilter(IReadOnlyList schemas) + private static Func? GenerateSchemaFilter(IReadOnlyList schemas) { return schemas.Count > 0 ? (s => @@ -206,10 +200,10 @@ private static Func GenerateSchemaFilter(IReadOnlyList s schemaFilterBuilder.Append(")"); return schemaFilterBuilder.ToString(); }) - : (Func)null; + : (Func?)null; } - private static (string Schema, string Table) Parse(string table) + private static (string? Schema, string Table) Parse(string table) { var match = _partExtractor.Match(table.Trim()); @@ -224,9 +218,9 @@ private static (string Schema, string Table) Parse(string table) return string.IsNullOrEmpty(part2) ? (null, part1) : (part1, part2); } - private static Func GenerateTableFilter( - IReadOnlyList<(string Schema, string Table)> tables, - Func schemaFilter) + private static Func? GenerateTableFilter( + IReadOnlyList<(string? Schema, string Table)> tables, + Func? schemaFilter) => schemaFilter != null || tables.Count > 0 ? ((s, t) => @@ -293,7 +287,7 @@ private static Func GenerateTableFilter( return tableFilterBuilder.ToString(); }) - : (Func)null; + : (Func?)null; private static string EscapeLiteral(string s) => $"N'{s}'"; @@ -319,8 +313,8 @@ FROM [sys].[types] AS [t] while (reader.Read()) { var schema = reader.GetValueOrDefault("schema_name"); - var userType = reader.GetValueOrDefault("type_name"); - var systemType = reader.GetValueOrDefault("underlying_system_type"); + var userType = reader.GetFieldValue("type_name"); + var systemType = reader.GetFieldValue("underlying_system_type"); var maxLength = reader.GetValueOrDefault("max_length"); var precision = reader.GetValueOrDefault("precision"); var scale = reader.GetValueOrDefault("scale"); @@ -336,9 +330,10 @@ FROM [sys].[types] AS [t] return typeAliasMap; } - private IEnumerable GetSequences( + private void GetSequences( DbConnection connection, - Func schemaFilter, + DatabaseModel databaseModel, + Func? schemaFilter, IReadOnlyDictionary typeAliases) { using var command = connection.CreateCommand(); @@ -369,9 +364,9 @@ FROM [sys].[sequences] AS [s] while (reader.Read()) { var schema = reader.GetValueOrDefault("schema_name"); - var name = reader.GetValueOrDefault("name"); + var name = reader.GetString("name"); var storeTypeSchema = reader.GetValueOrDefault("type_schema"); - var storeType = reader.GetValueOrDefault("type_name"); + var storeType = reader.GetString("type_name"); var precision = reader.GetValueOrDefault("precision"); var scale = reader.GetValueOrDefault("scale"); var isCyclic = reader.GetValueOrDefault("is_cycling"); @@ -390,10 +385,9 @@ FROM [sys].[sequences] AS [s] _logger.SequenceFound(DisplayName(schema, name), storeType, isCyclic, incrementBy, startValue, minValue, maxValue); - var sequence = new DatabaseSequence + var sequence = new DatabaseSequence(databaseModel, name) { Schema = schema, - Name = name, StoreType = storeType, IsCyclic = isCyclic, IncrementBy = incrementBy, @@ -413,13 +407,14 @@ FROM [sys].[sequences] AS [s] : sequence.MaxValue; } - yield return sequence; + databaseModel.Sequences.Add(sequence); } } - private IEnumerable GetTables( + private void GetTables( DbConnection connection, - Func tableFilter, + DatabaseModel databaseModel, + Func? tableFilter, IReadOnlyDictionary typeAliases) { using var command = connection.CreateCommand(); @@ -515,18 +510,17 @@ FROM [sys].[views] AS [v] while (reader.Read()) { var schema = reader.GetValueOrDefault("schema"); - var name = reader.GetValueOrDefault("name"); + var name = reader.GetString("name"); var comment = reader.GetValueOrDefault("comment"); - var type = reader.GetValueOrDefault("type"); + var type = reader.GetString("type"); _logger.TableFound(DisplayName(schema, name)); var table = type == "table" - ? new DatabaseTable() - : new DatabaseView(); + ? new DatabaseTable(databaseModel, name) + : new DatabaseView(databaseModel, name); table.Schema = schema; - table.Name = name; table.Comment = comment; if (supportsMemoryOptimizedTable) @@ -546,7 +540,10 @@ FROM [sys].[views] AS [v] GetIndexes(connection, tables, filter); GetForeignKeys(connection, tables, filter); - return tables; + foreach (var table in tables) + { + databaseModel.Tables.Add(table); + } } private void GetColumns( @@ -620,10 +617,10 @@ UNION ALL foreach (var dataRecord in tableColumnGroup) { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var ordinal = dataRecord.GetValueOrDefault("ordinal"); + var columnName = dataRecord.GetFieldValue("column_name"); + var ordinal = dataRecord.GetFieldValue("ordinal"); var dataTypeSchemaName = dataRecord.GetValueOrDefault("type_schema"); - var dataTypeName = dataRecord.GetValueOrDefault("type_name"); + var dataTypeName = dataRecord.GetFieldValue("type_name"); var maxLength = dataRecord.GetValueOrDefault("max_length"); var precision = dataRecord.GetValueOrDefault("precision"); var scale = dataRecord.GetValueOrDefault("scale"); @@ -663,11 +660,8 @@ UNION ALL defaultValue = FilterClrDefaults(systemTypeName, nullable, defaultValue); - var column = new DatabaseColumn + var column = new DatabaseColumn(table, columnName, storeType) { - Table = table, - Name = columnName, - StoreType = storeType, IsNullable = nullable, DefaultValueSql = defaultValue, ComputedColumnSql = computedValue, @@ -692,7 +686,7 @@ UNION ALL } } - private static string FilterClrDefaults(string dataTypeName, bool nullable, string defaultValue) + private static string? FilterClrDefaults(string dataTypeName, bool nullable, string? defaultValue) { if (defaultValue == null || defaultValue == "(NULL)") @@ -849,7 +843,7 @@ FROM [sys].[indexes] i .Where(ddr => ddr.GetValueOrDefault("is_primary_key")) .GroupBy( ddr => - (Name: ddr.GetValueOrDefault("index_name"), + (Name: ddr.GetFieldValue("index_name"), TypeDesc: ddr.GetValueOrDefault("type_desc"))) .ToArray(); @@ -859,7 +853,7 @@ FROM [sys].[indexes] i _logger.PrimaryKeyFound(primaryKeyGroup.Key.Name, DisplayName(tableSchema, tableName)); - var primaryKey = new DatabasePrimaryKey { Table = table, Name = primaryKeyGroup.Key.Name }; + var primaryKey = new DatabasePrimaryKey(table, primaryKeyGroup.Key.Name); if (primaryKeyGroup.Key.TypeDesc == "NONCLUSTERED") { @@ -892,7 +886,7 @@ FROM [sys].[indexes] i { _logger.UniqueConstraintFound(uniqueConstraintGroup.Key.Name, DisplayName(tableSchema, tableName)); - var uniqueConstraint = new DatabaseUniqueConstraint { Table = table, Name = uniqueConstraintGroup.Key.Name }; + var uniqueConstraint = new DatabaseUniqueConstraint(table, uniqueConstraintGroup.Key.Name); if (uniqueConstraintGroup.Key.TypeDesc == "CLUSTERED") { @@ -930,10 +924,8 @@ FROM [sys].[indexes] i { _logger.IndexFound(indexGroup.Key.Name, DisplayName(tableSchema, tableName), indexGroup.Key.IsUnique); - var index = new DatabaseIndex + var index = new DatabaseIndex(table, indexGroup.Key.Name) { - Table = table, - Name = indexGroup.Key.Name, IsUnique = indexGroup.Key.IsUnique, Filter = indexGroup.Key.HasFilter ? indexGroup.Key.FilterDefinition : null }; @@ -1017,7 +1009,7 @@ FROM [sys].[foreign_keys] AS [f] t => t.Schema == principalTableSchema && t.Name == principalTableName) ?? tables.FirstOrDefault( - t => t.Schema.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) + t => t.Schema?.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) == true && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); if (principalTable == null) @@ -1030,11 +1022,8 @@ FROM [sys].[foreign_keys] AS [f] continue; } - var foreignKey = new DatabaseForeignKey + var foreignKey = new DatabaseForeignKey(table, fkName, principalTable) { - Name = fkName, - Table = table, - PrincipalTable = principalTable, OnDelete = ConvertToReferentialAction(onDeleteAction) }; @@ -1119,7 +1108,7 @@ FROM sys.databases return result != null ? Convert.ToByte(result) : (byte)0; } - private static string DisplayName(string schema, string name) + private static string DisplayName(string? schema, string name) => (!string.IsNullOrEmpty(schema) ? schema + "." : "") + name; private static ReferentialAction? ConvertToReferentialAction(string onDeleteAction) diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteCodeGenerator.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteCodeGenerator.cs index 58ac03204c0..1d59b4444e4 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteCodeGenerator.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteCodeGenerator.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Scaffolding; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Scaffolding.Internal { /// @@ -32,7 +34,7 @@ public SqliteCodeGenerator([NotNull] ProviderCodeGeneratorDependencies dependenc /// public override MethodCallCodeFragment GenerateUseProvider( string connectionString, - MethodCallCodeFragment providerOptions) + MethodCallCodeFragment? providerOptions) => new MethodCallCodeFragment( nameof(SqliteDbContextOptionsBuilderExtensions.UseSqlite), providerOptions == null diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index 094a0895b25..4d66c5b4e31 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -19,6 +19,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Scaffolding.Internal { /// @@ -94,23 +96,15 @@ public override DatabaseModel Create(DbConnection connection, DatabaseModelFacto { databaseModel.DatabaseName = GetDatabaseName(connection); - foreach (var table in GetTables(connection, options.Tables)) - { - table.Database = databaseModel; - databaseModel.Tables.Add(table); - } + GetTables(connection, databaseModel, options.Tables); foreach (var table in databaseModel.Tables) { - foreach (var foreignKey in GetForeignKeys(connection, table, databaseModel.Tables)) - { - foreignKey.Table = table; - table.ForeignKeys.Add(foreignKey); - } + GetForeignKeys(connection, table, databaseModel.Tables); } var nullableKeyColumns = databaseModel.Tables - .Where(t => t.PrimaryKey != null).SelectMany(t => t.PrimaryKey.Columns) + .SelectMany(t => t.PrimaryKey?.Columns ?? Array.Empty()) .Concat(databaseModel.Tables.SelectMany(t => t.ForeignKeys).SelectMany(fk => fk.PrincipalColumns)) .Where(c => c.IsNullable) .Distinct(); @@ -142,7 +136,7 @@ private static string GetDatabaseName(DbConnection connection) return name; } - private IEnumerable GetTables(DbConnection connection, IEnumerable tables) + private void GetTables(DbConnection connection, DatabaseModel databaseModel, IEnumerable tables) { var tablesToSelect = new HashSet(tables.ToList(), StringComparer.OrdinalIgnoreCase); var selectedTables = new HashSet(StringComparer.OrdinalIgnoreCase); @@ -177,37 +171,15 @@ private IEnumerable GetTables(DbConnection connection, IEnumerabl var type = reader.GetString(1); var table = type == "table" - ? new DatabaseTable() - : new DatabaseView(); - - table.Name = name; - - foreach (var column in GetColumns(connection, name)) - { - column.Table = table; - table.Columns.Add(column); - } - - var primaryKey = GetPrimaryKey(connection, name, table.Columns); - if (primaryKey != null) - { - primaryKey.Table = table; - table.PrimaryKey = primaryKey; - } - - foreach (var uniqueConstraints in GetUniqueConstraints(connection, name, table.Columns)) - { - uniqueConstraints.Table = table; - table.UniqueConstraints.Add(uniqueConstraints); - } + ? new DatabaseTable(databaseModel, name) + : new DatabaseView(databaseModel, name); - foreach (var index in GetIndexes(connection, name, table.Columns)) - { - index.Table = table; - table.Indexes.Add(index); - } + GetColumns(connection, table); + GetPrimaryKey(connection, table); + GetUniqueConstraints(connection, table); + GetIndexes(connection, table); - yield return table; + databaseModel.Tables.Add(table); } } @@ -233,7 +205,7 @@ private static bool AllowsTable(HashSet tables, HashSet selected return false; } - private IEnumerable GetColumns(DbConnection connection, string table) + private void GetColumns(DbConnection connection, DatabaseTable table) { using var command = connection.CreateCommand(); command.CommandText = new StringBuilder() @@ -244,7 +216,7 @@ private IEnumerable GetColumns(DbConnection connection, string t var parameter = command.CreateParameter(); parameter.ParameterName = "@table"; - parameter.Value = table; + parameter.Value = table.Name; command.Parameters.Add(parameter); using var reader = command.ExecuteReader(); @@ -257,19 +229,17 @@ private IEnumerable GetColumns(DbConnection connection, string t ? FilterClrDefaults(dataType, notNull, reader.GetString(3)) : null; - _logger.ColumnFound(table, columnName, dataType, notNull, defaultValue); + _logger.ColumnFound(table.Name, columnName, dataType, notNull, defaultValue); - yield return new DatabaseColumn + table.Columns.Add(new DatabaseColumn(table, columnName, dataType) { - Name = columnName, - StoreType = dataType, IsNullable = !notNull, DefaultValueSql = defaultValue - }; + }); } } - private string FilterClrDefaults(string dataType, bool notNull, string defaultValue) + private string? FilterClrDefaults(string dataType, bool notNull, string defaultValue) { if (string.Equals(defaultValue, "null", StringComparison.OrdinalIgnoreCase)) { @@ -289,65 +259,62 @@ private string FilterClrDefaults(string dataType, bool notNull, string defaultVa return defaultValue; } - private DatabasePrimaryKey GetPrimaryKey(DbConnection connection, string table, IList columns) + private void GetPrimaryKey(DbConnection connection, DatabaseTable table) { - var primaryKey = new DatabasePrimaryKey(); - - using (var command = connection.CreateCommand()) - { - command.CommandText = new StringBuilder() - .AppendLine("SELECT \"name\"") - .AppendLine("FROM pragma_index_list(@table)") - .AppendLine("WHERE \"origin\" = 'pk'") - .AppendLine("ORDER BY \"seq\";") - .ToString(); + using var command = connection.CreateCommand(); + command.CommandText = new StringBuilder() + .AppendLine("SELECT \"name\"") + .AppendLine("FROM pragma_index_list(@table)") + .AppendLine("WHERE \"origin\" = 'pk'") + .AppendLine("ORDER BY \"seq\";") + .ToString(); - var parameter = command.CreateParameter(); - parameter.ParameterName = "@table"; - parameter.Value = table; - command.Parameters.Add(parameter); + var parameter = command.CreateParameter(); + parameter.ParameterName = "@table"; + parameter.Value = table.Name; + command.Parameters.Add(parameter); - var name = (string)command.ExecuteScalar(); - if (name == null) - { - return GetRowidPrimaryKey(connection, table, columns); - } + var name = (string)command.ExecuteScalar(); + if (name == null) + { + GetRowidPrimaryKey(connection, table); + return; + } - if (!name.StartsWith("sqlite_", StringComparison.Ordinal)) - { - primaryKey.Name = name; - } + var primaryKey = new DatabasePrimaryKey( + table, + name.StartsWith("sqlite_", StringComparison.Ordinal) + ? string.Empty + : name); - _logger.PrimaryKeyFound(name, table); + _logger.PrimaryKeyFound(name, table.Name); - command.CommandText = new StringBuilder() - .AppendLine("SELECT \"name\"") - .AppendLine("FROM pragma_index_info(@index)") - .AppendLine("ORDER BY \"seqno\";") - .ToString(); + command.CommandText = new StringBuilder() + .AppendLine("SELECT \"name\"") + .AppendLine("FROM pragma_index_info(@index)") + .AppendLine("ORDER BY \"seqno\";") + .ToString(); - parameter.ParameterName = "@index"; - parameter.Value = name; + parameter.ParameterName = "@index"; + parameter.Value = name; - using var reader = command.ExecuteReader(); - while (reader.Read()) - { - var columnName = reader.GetString(0); - var column = columns.FirstOrDefault(c => c.Name == columnName) - ?? columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); - Check.DebugAssert(column != null, "column is null."); + using var reader = command.ExecuteReader(); + while (reader.Read()) + { + var columnName = reader.GetString(0); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + Check.DebugAssert(column != null, "column is null."); - primaryKey.Columns.Add(column); - } + primaryKey.Columns.Add(column); } - return primaryKey; + table.PrimaryKey = primaryKey; } - private static DatabasePrimaryKey GetRowidPrimaryKey( + private static void GetRowidPrimaryKey( DbConnection connection, - string table, - IList columns) + DatabaseTable table) { using var command = connection.CreateCommand(); command.CommandText = new StringBuilder() @@ -358,29 +325,26 @@ private static DatabasePrimaryKey GetRowidPrimaryKey( var parameter = command.CreateParameter(); parameter.ParameterName = "@table"; - parameter.Value = table; + parameter.Value = table.Name; command.Parameters.Add(parameter); using var reader = command.ExecuteReader(); if (!reader.Read()) { - return null; + return; } var columnName = reader.GetString(0); - var column = columns.FirstOrDefault(c => c.Name == columnName) - ?? columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); Check.DebugAssert(column != null, "column is null."); Check.DebugAssert(!reader.Read(), "Unexpected composite primary key."); - return new DatabasePrimaryKey { Columns = { column } }; + table.PrimaryKey = new DatabasePrimaryKey(table, string.Empty) { Columns = { column } }; } - private IEnumerable GetUniqueConstraints( - DbConnection connection, - string table, - IList columns) + private void GetUniqueConstraints(DbConnection connection, DatabaseTable table) { using var command1 = connection.CreateCommand(); command1.CommandText = new StringBuilder() @@ -392,20 +356,20 @@ private IEnumerable GetUniqueConstraints( var parameter1 = command1.CreateParameter(); parameter1.ParameterName = "@table"; - parameter1.Value = table; + parameter1.Value = table.Name; command1.Parameters.Add(parameter1); using var reader1 = command1.ExecuteReader(); while (reader1.Read()) { - var uniqueConstraint = new DatabaseUniqueConstraint(); - var name = reader1.GetString(0); - if (!name.StartsWith("sqlite_", StringComparison.Ordinal)) - { - uniqueConstraint.Name = name; - } + var constraintName = reader1.GetString(0); + var uniqueConstraint = new DatabaseUniqueConstraint( + table, + constraintName.StartsWith("sqlite_", StringComparison.Ordinal) + ? string.Empty + : constraintName); - _logger.UniqueConstraintFound(name, table); + _logger.UniqueConstraintFound(constraintName, table.Name); using (var command2 = connection.CreateCommand()) { @@ -417,15 +381,15 @@ private IEnumerable GetUniqueConstraints( var parameter2 = command2.CreateParameter(); parameter2.ParameterName = "@index"; - parameter2.Value = name; + parameter2.Value = constraintName; command2.Parameters.Add(parameter2); using var reader2 = command2.ExecuteReader(); while (reader2.Read()) { var columnName = reader2.GetString(0); - var column = columns.FirstOrDefault(c => c.Name == columnName) - ?? columns.FirstOrDefault( + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault( c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); Check.DebugAssert(column != null, "column is null."); @@ -433,14 +397,11 @@ private IEnumerable GetUniqueConstraints( } } - yield return uniqueConstraint; + table.UniqueConstraints.Add(uniqueConstraint); } } - private IEnumerable GetIndexes( - DbConnection connection, - string table, - IList columns) + private void GetIndexes(DbConnection connection, DatabaseTable table) { using var command1 = connection.CreateCommand(); command1.CommandText = new StringBuilder() @@ -452,15 +413,15 @@ private IEnumerable GetIndexes( var parameter1 = command1.CreateParameter(); parameter1.ParameterName = "@table"; - parameter1.Value = table; + parameter1.Value = table.Name; command1.Parameters.Add(parameter1); using var reader1 = command1.ExecuteReader(); while (reader1.Read()) { - var index = new DatabaseIndex { Name = reader1.GetString(0), IsUnique = reader1.GetBoolean(1) }; + var index = new DatabaseIndex(table, reader1.GetString(0)) { IsUnique = reader1.GetBoolean(1) }; - _logger.IndexFound(index.Name, table, index.IsUnique); + _logger.IndexFound(index.Name, table.Name, index.IsUnique); using (var command2 = connection.CreateCommand()) { @@ -479,19 +440,19 @@ private IEnumerable GetIndexes( while (reader2.Read()) { var name = reader2.GetString(0); - var column = columns.FirstOrDefault(c => c.Name == name) - ?? columns.FirstOrDefault(c => c.Name.Equals(name, StringComparison.Ordinal)); + var column = table.Columns.FirstOrDefault(c => c.Name == name) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(name, StringComparison.Ordinal)); Check.DebugAssert(column != null, "column is null."); index.Columns.Add(column); } } - yield return index; + table.Indexes.Add(index); } } - private IEnumerable GetForeignKeys(DbConnection connection, DatabaseTable table, IList tables) + private void GetForeignKeys(DbConnection connection, DatabaseTable table, IList tables) { using var command1 = connection.CreateCommand(); command1.CommandText = new StringBuilder() @@ -511,11 +472,11 @@ private IEnumerable GetForeignKeys(DbConnection connection, var id = reader1.GetInt64(0); var principalTableName = reader1.GetString(1); var onDelete = reader1.GetString(2); - var foreignKey = new DatabaseForeignKey + var principalTable = tables.FirstOrDefault(t => t.Name == principalTableName) + ?? tables.FirstOrDefault( + t => t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); + var foreignKey = new DatabaseForeignKey(table, string.Empty, principalTable) { - PrincipalTable = tables.FirstOrDefault(t => t.Name == principalTableName) - ?? tables.FirstOrDefault( - t => t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)), OnDelete = ConvertToReferentialAction(onDelete) }; @@ -577,7 +538,7 @@ private IEnumerable GetForeignKeys(DbConnection connection, if (!invalid) { - yield return foreignKey; + table.ForeignKeys.Add(foreignKey); } } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs index 4fd7960f44d..a2bd78d65a7 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpUniqueNamerTest.cs @@ -14,8 +14,9 @@ public class CSharpUniqueNamerTest public void Returns_unique_name_for_type() { var namer = new CSharpUniqueNamer(s => s.Name, new CSharpUtilities(), null); - var input1 = new DatabaseColumn { Name = "Id" }; - var input2 = new DatabaseColumn { Name = "Id" }; + var table = new DatabaseTable(new DatabaseModel(), "foo"); + var input1 = new DatabaseColumn(table, "Id", "int"); + var input2 = new DatabaseColumn(table, "Id", "int"); Assert.Equal("Id", namer.GetName(input1)); Assert.Equal("Id", namer.GetName(input1)); @@ -27,8 +28,9 @@ public void Returns_unique_name_for_type() public void Uses_comparer() { var namer = new CSharpUniqueNamer(t => t.Name, new CSharpUtilities(), null); - var table1 = new DatabaseTable { Name = "A B C" }; - var table2 = new DatabaseTable { Name = "A_B_C" }; + var database = new DatabaseModel(); + var table1 = new DatabaseTable(database, "A B C"); + var table2 = new DatabaseTable(database, "A_B_C"); Assert.Equal("A_B_C", namer.GetName(table1)); Assert.Equal("A_B_C1", namer.GetName(table2)); } @@ -40,7 +42,7 @@ 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 table = new DatabaseTable { Name = input }; + var table = new DatabaseTable(new DatabaseModel(), input); Assert.Equal(output, namer.GetName(table)); } @@ -51,7 +53,7 @@ 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 table = new DatabaseTable { Name = input }; + var table = new DatabaseTable(new DatabaseModel(), input); Assert.Equal(output, namer.GetName(table)); } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CandidateNamingServiceTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CandidateNamingServiceTest.cs index fd9a41fe9a5..615a8020863 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CandidateNamingServiceTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CandidateNamingServiceTest.cs @@ -24,7 +24,7 @@ public void Generates_candidate_identifiers(string input, string output) { Assert.Equal( output, new CandidateNamingService().GenerateCandidateIdentifier( - new DatabaseTable { Name = input })); + new DatabaseTable(new DatabaseModel(), input))); } } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index bb60acd1b8a..7552acfa95b 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -22,9 +22,18 @@ public class RelationalDatabaseModelFactoryTest private readonly IScaffoldingModelFactory _factory; private readonly TestOperationReporter _reporter; - private static DatabaseColumn IdColumn => new DatabaseColumn { Name = "Id", StoreType = "int" }; + private static readonly DatabaseModel Database; + private static readonly DatabaseTable Table; + private static readonly DatabaseColumn IdColumn; + private static readonly DatabasePrimaryKey IdPrimaryKey; - private static readonly DatabasePrimaryKey IdPrimaryKey = new DatabasePrimaryKey { Columns = { IdColumn } }; + static RelationalDatabaseModelFactoryTest() + { + Database = new DatabaseModel(); + Table = new DatabaseTable(Database, "Foo"); + IdColumn = new DatabaseColumn(Table, "Id", "int"); + IdPrimaryKey = new DatabasePrimaryKey(Table, "IdPrimaryKey") { Columns = { IdColumn } }; + } public RelationalDatabaseModelFactoryTest() { @@ -47,21 +56,19 @@ public void Creates_entity_types() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "tableWithSchema") { - Name = "tableWithSchema", Schema = "public", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }, - new DatabaseTable + new DatabaseTable(Database, "noSchema") { - Name = "noSchema", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }, - new DatabaseTable { Name = "noPrimaryKey" }, - new DatabaseView { Name = "view" } + new DatabaseTable(Database, "noPrimaryKey"), + new DatabaseView(Database, "view") } }; var model = _factory.Create(info, false); @@ -98,15 +105,13 @@ public void Creates_entity_types_case_insensitive() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "TestTable") { - Name = "TestTable", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }, - new DatabaseTable + new DatabaseTable(Database, "TESTTABLE") { - Name = "TESTTABLE", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey } @@ -123,41 +128,30 @@ public void Loads_column_types() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Jobs") { - Name = "Jobs", Columns = { IdColumn, - new DatabaseColumn + new DatabaseColumn(Table, "occupation", "nvarchar(max)") { - Name = "occupation", - StoreType = "nvarchar(max)", DefaultValueSql = "\"dev\"" }, - new DatabaseColumn + new DatabaseColumn(Table, "salary", "int") { - Name = "salary", - StoreType = "int", IsNullable = true }, - new DatabaseColumn + new DatabaseColumn(Table, "modified", "nvarchar(max)") { - Name = "modified", - StoreType = "nvarchar(max)", IsNullable = false, ValueGenerated = ValueGenerated.OnAddOrUpdate }, - new DatabaseColumn + new DatabaseColumn(Table, "created", "nvarchar(max)") { - Name = "created", - StoreType = "nvarchar(max)", ValueGenerated = ValueGenerated.OnAdd }, - new DatabaseColumn + new DatabaseColumn(Table, "current", "nvarchar(max)") { - Name = "current", - StoreType = "nvarchar(max)", ComputedColumnSql = "compute_this()" } }, @@ -215,15 +209,14 @@ public void Use_database_names_for_columns() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "NaturalProducts") { - Name = "NaturalProducts", Columns = { IdColumn, - new DatabaseColumn { Name = "ProductSKU", StoreType = "nvarchar(max)" }, - new DatabaseColumn { Name = "supplierID", StoreType = "nvarchar(max)" }, - new DatabaseColumn { Name = "Vendor_Discount", StoreType = "nvarchar(max)" } + new DatabaseColumn(Table, "ProductSKU", "nvarchar(max)"), + new DatabaseColumn(Table, "supplierID", "nvarchar(max)"), + new DatabaseColumn(Table, "Vendor_Discount", "nvarchar(max)") }, PrimaryKey = IdPrimaryKey } @@ -247,15 +240,14 @@ public void Do_not_use_database_names_for_columns() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "NaturalProducts") { - Name = "NaturalProducts", Columns = { IdColumn, - new DatabaseColumn { Name = "ProductSKU", StoreType = "nvarchar(max)" }, - new DatabaseColumn { Name = "supplierID", StoreType = "nvarchar(max)" }, - new DatabaseColumn { Name = "Vendor_Discount", StoreType = "nvarchar(max)" } + new DatabaseColumn(Table, "ProductSKU", "nvarchar(max)"), + new DatabaseColumn(Table, "supplierID", "nvarchar(max)"), + new DatabaseColumn(Table, "Vendor_Discount", "nvarchar(max)") }, PrimaryKey = IdPrimaryKey } @@ -277,17 +269,16 @@ public void Do_not_use_database_names_for_columns() [InlineData("datetime2(4)", "datetime2(4)")] public void Column_type_annotation(string StoreType, string expectedColumnType) { - var column = new DatabaseColumn { Name = "Col", StoreType = StoreType }; + var column = new DatabaseColumn(Table, "Col", StoreType); var info = new DatabaseModel { Tables = { - new DatabaseTable + new DatabaseTable(Database, "A") { - Name = "A", Columns = { column }, - PrimaryKey = new DatabasePrimaryKey { Columns = { column } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { column } } } } }; @@ -300,21 +291,20 @@ public void Column_type_annotation(string StoreType, string expectedColumnType) [ConditionalFact] public void Column_ordinal_annotation() { - var col1 = new DatabaseColumn { Name = "Col1", StoreType = "nvarchar(max)" }; + var col1 = new DatabaseColumn(Table, "Col1", "nvarchar(max)"); var info = new DatabaseModel { Tables = { - new DatabaseTable + new DatabaseTable(Database, "A") { - Name = "A", Columns = { col1, - new DatabaseColumn { Name = "Col2", StoreType = "nvarchar(max)" }, - new DatabaseColumn { Name = "Col3", StoreType = "nvarchar(max)" } + new DatabaseColumn(Table, "Col2", "nvarchar(max)"), + new DatabaseColumn(Table, "Col3", "nvarchar(max)") }, - PrimaryKey = new DatabasePrimaryKey { Columns = { col1 } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { col1 } } } } }; @@ -338,23 +328,15 @@ public void Unmappable_column_type(string StoreType) { Tables = { - new DatabaseTable + new DatabaseTable(Database, "E") { - Name = "E", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey } } }; - info.Tables.First() - .Columns.Add( - new DatabaseColumn - { - Table = info.Tables.First(), - Name = "Coli", - StoreType = StoreType - }); + info.Tables.First().Columns.Add(new DatabaseColumn(info.Tables.First(), "Coli", StoreType)); Assert.Single(_factory.Create(info, false).FindEntityType("E").GetProperties()); Assert.Single(_reporter.Messages, t => t.Contains(DesignStrings.CannotFindTypeMappingForColumn("E.Coli", StoreType))); @@ -370,10 +352,9 @@ public void Primary_key(string[] keyProps, int length) { var info = new DatabaseModel { - Tables = { new DatabaseTable { Name = "PkTable", PrimaryKey = new DatabasePrimaryKey { Name = "MyPk" } } } + Tables = { new DatabaseTable(Database, "PkTable") { PrimaryKey = new DatabasePrimaryKey(Table, "MyPk") } } }; - foreach (var column in keyProps.Select( - k => new DatabaseColumn { Name = k, StoreType = "int" })) + foreach (var column in keyProps.Select(k => new DatabaseColumn(Table, k, "int"))) { info.Tables[0].Columns.Add(column); info.Tables[0].PrimaryKey.Columns.Add(column); @@ -388,18 +369,17 @@ public void Primary_key(string[] keyProps, int length) [ConditionalFact] public void Unique_constraint() { - var myColumn = new DatabaseColumn { Name = "MyColumn", StoreType = "int" }; + var myColumn = new DatabaseColumn(Table, "MyColumn", "int"); var databaseModel = new DatabaseModel { Tables = { - new DatabaseTable + new DatabaseTable(Database, "MyTable") { - Name = "MyTable", Columns = { IdColumn, myColumn }, PrimaryKey = IdPrimaryKey, - UniqueConstraints = { new DatabaseUniqueConstraint { Name = "MyUniqueConstraint", Columns = { myColumn } } } + UniqueConstraints = { new DatabaseUniqueConstraint(Table, "MyUniqueConstraint") { Columns = { myColumn } } } } } }; @@ -415,43 +395,38 @@ public void Unique_constraint() [ConditionalFact] public void Indexes_and_alternate_keys() { - var c1 = new DatabaseColumn { Name = "C1", StoreType = "int" }; - var table = new DatabaseTable + var c1 = new DatabaseColumn(Table, "C1", "int"); + var table = new DatabaseTable(Database, "T") { - Name = "T", Columns = { c1, - new DatabaseColumn { Name = "C2", StoreType = "int" }, - new DatabaseColumn { Name = "C3", StoreType = "int" } + new DatabaseColumn(Table, "C2", "int"), + new DatabaseColumn(Table, "C3", "int") }, - PrimaryKey = new DatabasePrimaryKey { Columns = { c1 } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { c1 } } }; table.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "IDX_C1") { - Name = "IDX_C1", Columns = { table.Columns.ElementAt(0) }, IsUnique = false }); table.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "UNQ_C2") { - Name = "UNQ_C2", Columns = { table.Columns.ElementAt(1) }, IsUnique = true }); table.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "IDX_C2_C1") { - Name = "IDX_C2_C1", Columns = { table.Columns.ElementAt(1), table.Columns.ElementAt(0) }, IsUnique = false }); table.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "UNQ_C3_C1") { - /*Name ="UNQ_C3_C1",*/ Columns = { table.Columns.ElementAt(2), table.Columns.ElementAt(0) }, IsUnique = true }); @@ -491,32 +466,23 @@ public void Indexes_and_alternate_keys() [ConditionalFact] public void Foreign_key() { - var parentTable = new DatabaseTable + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }; - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", Columns = { IdColumn, - new DatabaseColumn - { - Name = "ParentId", - StoreType = "int", - IsNullable = true - } + new DatabaseColumn(Table, "ParentId", "int") { IsNullable = true } }, PrimaryKey = IdPrimaryKey }; childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, OnDelete = ReferentialAction.Cascade, Columns = { childrenTable.Columns.ElementAt(1) }, PrincipalColumns = { parentTable.Columns.ElementAt(0) } @@ -544,35 +510,26 @@ public void Foreign_key() [ConditionalFact] public void Foreign_key_to_unique_constraint() { - var keyColumn = new DatabaseColumn - { - Name = "Key", - StoreType = "int", - IsNullable = false - }; + var keyColumn = new DatabaseColumn(Table, "Key", "int") { IsNullable = false }; - var parentTable = new DatabaseTable + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", Columns = { IdColumn, keyColumn }, PrimaryKey = IdPrimaryKey }; parentTable.UniqueConstraints.Add( - new DatabaseUniqueConstraint { Table = parentTable, Columns = { keyColumn } }); + new DatabaseUniqueConstraint(parentTable, "AK_Foo") { Columns = { keyColumn } }); - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }; childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, OnDelete = ReferentialAction.Cascade, Columns = { childrenTable.Columns.ElementAt(0) }, PrincipalColumns = { parentTable.Columns.ElementAt(1) } @@ -600,23 +557,19 @@ public void Foreign_key_to_unique_constraint() [ConditionalFact] public void Unique_foreign_key() { - var parentTable = new DatabaseTable + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }; - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }; childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, OnDelete = ReferentialAction.NoAction, Columns = { childrenTable.Columns.ElementAt(0) }, PrincipalColumns = { parentTable.Columns.ElementAt(0) } @@ -636,30 +589,26 @@ public void Unique_foreign_key() [ConditionalFact] public void Composite_foreign_key() { - var ida = new DatabaseColumn { Name = "Id_A", StoreType = "int" }; - var idb = new DatabaseColumn { Name = "Id_B", StoreType = "int" }; - var parentTable = new DatabaseTable + var ida = new DatabaseColumn(Table, "Id_A", "int"); + var idb = new DatabaseColumn(Table, "Id_B", "int"); + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", Columns = { ida, idb }, - PrimaryKey = new DatabasePrimaryKey { Columns = { ida, idb } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { ida, idb } } }; - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", Columns = { IdColumn, - new DatabaseColumn { Name = "ParentId_A", StoreType = "int" }, - new DatabaseColumn { Name = "ParentId_B", StoreType = "int" } + new DatabaseColumn(Table, "ParentId_A", "int"), + new DatabaseColumn(Table, "ParentId_B", "int") }, PrimaryKey = IdPrimaryKey }; childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, OnDelete = ReferentialAction.SetNull, Columns = { childrenTable.Columns.ElementAt(1), childrenTable.Columns.ElementAt(2) }, PrincipalColumns = { parentTable.Columns.ElementAt(0), parentTable.Columns.ElementAt(1) } @@ -689,26 +638,18 @@ public void Composite_foreign_key() [ConditionalFact] public void It_loads_self_referencing_foreign_key() { - var table = new DatabaseTable + var table = new DatabaseTable(Database, "ItemsList") { - Name = "ItemsList", Columns = { IdColumn, - new DatabaseColumn - { - Name = "ParentId", - StoreType = "int", - IsNullable = false - } + new DatabaseColumn(Table, "ParentId", "int") { IsNullable = false } }, PrimaryKey = IdPrimaryKey }; table.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(table, "FK_Foo", table) { - Table = table, - PrincipalTable = table, Columns = { table.Columns.ElementAt(1) }, PrincipalColumns = { table.Columns.ElementAt(0) } }); @@ -729,23 +670,19 @@ public void It_loads_self_referencing_foreign_key() [ConditionalFact] public void It_logs_warning_for_bad_foreign_key() { - var parentTable = new DatabaseTable + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", - Columns = { IdColumn, new DatabaseColumn { Name = "NotPkId", StoreType = "int" } }, + Columns = { IdColumn, new DatabaseColumn(Table, "NotPkId", "int") }, PrimaryKey = IdPrimaryKey }; - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", - Columns = { IdColumn, new DatabaseColumn { Name = "ParentId", StoreType = "int" } }, + Columns = { IdColumn, new DatabaseColumn(Table, "ParentId", "int") }, PrimaryKey = IdPrimaryKey }; childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, Columns = { childrenTable.Columns.ElementAt(1) }, PrincipalColumns = { parentTable.Columns.ElementAt(1) } }); @@ -764,28 +701,20 @@ public void It_logs_warning_for_bad_foreign_key() [ConditionalFact] public void Unique_nullable_index_unused_by_foreign_key() { - var table = new DatabaseTable + var table = new DatabaseTable(Database, "Friends") { - Name = "Friends", Columns = { IdColumn, - new DatabaseColumn - { - Name = "BuddyId", - StoreType = "int", - IsNullable = true - } + new DatabaseColumn(Table, "BuddyId", "int") { IsNullable = true } }, PrimaryKey = IdPrimaryKey }; table.Indexes.Add( - new DatabaseIndex { Columns = { table.Columns.ElementAt(1) }, IsUnique = true }); + new DatabaseIndex(Table, "IX_Foo") { Columns = { table.Columns.ElementAt(1) }, IsUnique = true }); table.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(table, "FK_Foo", table) { - Table = table, - PrincipalTable = table, Columns = { table.Columns.ElementAt(1) }, PrincipalColumns = { table.Columns.ElementAt(0) } }); @@ -808,33 +737,24 @@ public void Unique_nullable_index_unused_by_foreign_key() [ConditionalFact] public void Unique_nullable_index_used_by_foreign_key() { - var table = new DatabaseTable + var table = new DatabaseTable(Database, "Friends") { - Name = "Friends", Columns = { IdColumn, - new DatabaseColumn - { - Name = "BuddyId", - StoreType = "int", - IsNullable = true - } + new DatabaseColumn(Table, "BuddyId", "int") { IsNullable = true } }, PrimaryKey = IdPrimaryKey }; table.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "FriendsNameUniqueIndex") { - Name = "FriendsNameUniqueIndex", Columns = { table.Columns.ElementAt(1) }, IsUnique = true }); table.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(table, "FK_Foo", table) { - Table = table, - PrincipalTable = table, Columns = { table.Columns.ElementAt(1) }, PrincipalColumns = { table.Columns.ElementAt(1) } }); @@ -863,35 +783,31 @@ public void Unique_nullable_index_used_by_foreign_key() [ConditionalFact] public void Unique_index_composite_foreign_key() { - var ida = new DatabaseColumn { Name = "Id_A", StoreType = "int" }; - var idb = new DatabaseColumn { Name = "Id_B", StoreType = "int" }; - var parentTable = new DatabaseTable + var ida = new DatabaseColumn(Table, "Id_A", "int"); + var idb = new DatabaseColumn(Table, "Id_B", "int"); + var parentTable = new DatabaseTable(Database, "Parent") { - Name = "Parent", Columns = { ida, idb }, - PrimaryKey = new DatabasePrimaryKey { Columns = { ida, idb } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { ida, idb } } }; - var childrenTable = new DatabaseTable + var childrenTable = new DatabaseTable(Database, "Children") { - Name = "Children", Columns = { IdColumn, - new DatabaseColumn { Name = "ParentId_A", StoreType = "int" }, - new DatabaseColumn { Name = "ParentId_B", StoreType = "int" } + new DatabaseColumn(Table, "ParentId_A", "int"), + new DatabaseColumn(Table, "ParentId_B", "int") }, PrimaryKey = IdPrimaryKey }; childrenTable.Indexes.Add( - new DatabaseIndex + new DatabaseIndex(Table, "IX_Foo") { IsUnique = true, Columns = { childrenTable.Columns.ElementAt(1), childrenTable.Columns.ElementAt(2) } }); childrenTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(childrenTable, "FK_Foo", parentTable) { - Table = childrenTable, - PrincipalTable = parentTable, Columns = { childrenTable.Columns.ElementAt(1), childrenTable.Columns.ElementAt(2) }, PrincipalColumns = { parentTable.Columns.ElementAt(0), parentTable.Columns.ElementAt(1) } }); @@ -915,20 +831,18 @@ public void Unique_names() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "E F") { - Name = "E F", Columns = { IdColumn, - new DatabaseColumn { Name = "San itized", StoreType = "int" }, - new DatabaseColumn { Name = "San+itized", StoreType = "int" } + new DatabaseColumn(Table, "San itized", "int"), + new DatabaseColumn(Table, "San+itized", "int") }, PrimaryKey = IdPrimaryKey }, - new DatabaseTable + new DatabaseTable(Database, "E+F") { - Name = "E+F", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey } @@ -970,7 +884,7 @@ public void Unique_names() [ConditionalFact] public void Sequences() { - var info = new DatabaseModel { Sequences = { new DatabaseSequence { Name = "CountByThree", IncrementBy = 3 } } }; + var info = new DatabaseModel { Sequences = { new DatabaseSequence(Database, "CountByThree") { IncrementBy = 3 } } }; var model = _factory.Create(info, false); @@ -994,9 +908,8 @@ public void DbSet_annotation_is_set() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Blog") { - Name = "Blog", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey } @@ -1014,15 +927,13 @@ public void Pluralization_of_entity_and_DbSet() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Blog") { - Name = "Blog", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }, - new DatabaseTable + new DatabaseTable(Database, "Posts") { - Name = "Posts", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey } @@ -1079,33 +990,24 @@ public void Pluralization_of_entity_and_DbSet() [ConditionalFact] public void Pluralization_of_collection_navigations() { - var blogTable = new DatabaseTable + var blogTable = new DatabaseTable(Database, "Blog") { - Name = "Blog", Columns = { IdColumn }, PrimaryKey = IdPrimaryKey }; - var postTable = new DatabaseTable + var postTable = new DatabaseTable(Database, "Post") { - Name = "Post", Columns = { IdColumn, - new DatabaseColumn - { - Name = "BlogId", - StoreType = "int", - IsNullable = true - } + new DatabaseColumn(Table, "BlogId", "int") { IsNullable = true } }, PrimaryKey = IdPrimaryKey }; postTable.ForeignKeys.Add( - new DatabaseForeignKey + new DatabaseForeignKey(postTable, "FK_Foo", blogTable) { - Table = postTable, - PrincipalTable = blogTable, OnDelete = ReferentialAction.Cascade, Columns = { postTable.Columns.ElementAt(1) }, PrincipalColumns = { blogTable.Columns.ElementAt(0) } @@ -1147,23 +1049,18 @@ public void Not_null_bool_column_with_default_value_is_made_nullable() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Table") { - Name = "Table", Columns = { IdColumn, - new DatabaseColumn + new DatabaseColumn(Table, "NonNullBoolWithDefault", "bit") { - Name = "NonNullBoolWithDefault", - StoreType = "bit", DefaultValueSql = "Default", IsNullable = false }, - new DatabaseColumn + new DatabaseColumn(Table, "NonNullBoolWithoutDefault", "bit") { - Name = "NonNullBoolWithoutDefault", - StoreType = "bit", IsNullable = false } }, @@ -1190,16 +1087,13 @@ public void Nullable_column_with_default_value_sql_does_not_generate_warning() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Table") { - Name = "Table", Columns = { IdColumn, - new DatabaseColumn + new DatabaseColumn(Table, "NullBoolWithDefault", "bit") { - Name = "NullBoolWithDefault", - StoreType = "bit", DefaultValueSql = "Default", IsNullable = true } @@ -1223,20 +1117,17 @@ public void Nullable_column_with_default_value_sql_does_not_generate_warning() [ConditionalFact] public void Correct_arguments_to_scaffolding_typemapper() { - var principalPkColumn = new DatabaseColumn { Name = "PrimaryKey", StoreType = "nvarchar(450)" }; - var principalAkColumn = new DatabaseColumn { Name = "AlternateKey", StoreType = "nvarchar(450)" }; - var principalIndexColumn = new DatabaseColumn { Name = "Index", StoreType = "nvarchar(450)" }; - var rowversionColumn = new DatabaseColumn + var principalPkColumn = new DatabaseColumn(Table, "PrimaryKey", "nvarchar(450)"); + var principalAkColumn = new DatabaseColumn(Table, "AlternateKey", "nvarchar(450)"); + var principalIndexColumn = new DatabaseColumn(Table, "Index", "nvarchar(450)"); + var rowversionColumn = new DatabaseColumn(Table, "Rowversion", "rowversion") { - Name = "Rowversion", - StoreType = "rowversion", ValueGenerated = ValueGenerated.OnAddOrUpdate, [ScaffoldingAnnotationNames.ConcurrencyToken] = true }; - var principalTable = new DatabaseTable + var principalTable = new DatabaseTable(Database, "Principal") { - Name = "Principal", Columns = { principalPkColumn, @@ -1244,26 +1135,24 @@ public void Correct_arguments_to_scaffolding_typemapper() principalIndexColumn, rowversionColumn }, - PrimaryKey = new DatabasePrimaryKey { Columns = { principalPkColumn } }, - UniqueConstraints = { new DatabaseUniqueConstraint { Columns = { principalAkColumn } } }, - Indexes = { new DatabaseIndex { Columns = { principalIndexColumn } } } + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { principalPkColumn } }, + UniqueConstraints = { new DatabaseUniqueConstraint(Table, "AK_Foo") { Columns = { principalAkColumn } } }, + Indexes = { new DatabaseIndex(Table, "IX_Foo") { Columns = { principalIndexColumn } } } }; - var dependentIdColumn = new DatabaseColumn { Name = "Id", StoreType = "int" }; - var dependentFkColumn = new DatabaseColumn { Name = "BlogAlternateKey", StoreType = "nvarchar(450)" }; + var dependentIdColumn = new DatabaseColumn(Table, "Id", "int"); + var dependentFkColumn = new DatabaseColumn(Table, "BlogAlternateKey", "nvarchar(450)"); - var dependentTable = new DatabaseTable + var dependentTable = new DatabaseTable(Database, "Dependent") { - Name = "Dependent", Columns = { dependentIdColumn, dependentFkColumn }, - PrimaryKey = new DatabasePrimaryKey { Columns = { dependentIdColumn } }, - Indexes = { new DatabaseIndex { Columns = { dependentFkColumn } } }, + PrimaryKey = new DatabasePrimaryKey(Table, "PK_Foo") { Columns = { dependentIdColumn } }, + Indexes = { new DatabaseIndex(Table, "IX_Foo") { Columns = { dependentFkColumn } } }, ForeignKeys = { - new DatabaseForeignKey + new DatabaseForeignKey(Table, "FK_Foo", principalTable) { Columns = { dependentFkColumn }, - PrincipalTable = principalTable, PrincipalColumns = { principalAkColumn } } } @@ -1283,15 +1172,14 @@ public void Correct_arguments_to_scaffolding_typemapper() [ConditionalFact] public void Unmapped_column_is_ignored() { - var columnWithUnknownType = new DatabaseColumn { Name = "ColumnWithUnknownStoreType", StoreType = "unknown_type" }; + var columnWithUnknownType = new DatabaseColumn(Table, "ColumnWithUnknownStoreType", "unknown_type"); var dbModel = new DatabaseModel { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Table") { - Name = "Table", Columns = { IdColumn, columnWithUnknownType }, PrimaryKey = IdPrimaryKey } @@ -1312,19 +1200,13 @@ public void Column_and_table_comments() { Tables = { - new DatabaseTable + new DatabaseTable(Database, "Table") { - Name = "Table", Comment = "A table", Columns = { IdColumn, - new DatabaseColumn - { - Name = "Column", - StoreType = "int", - Comment = "An int column" - } + new DatabaseColumn(Table, "Column", "int") { Comment = "An int column" } } } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineerScaffolderTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineerScaffolderTest.cs index 547ab17af6a..307a7d11425 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineerScaffolderTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/ReverseEngineerScaffolderTest.cs @@ -24,10 +24,9 @@ public void Save_works() { using var directory = new TempDirectory(); var scaffolder = CreateScaffolder(); - var scaffoldedModel = new ScaffoldedModel + var scaffoldedModel = new ScaffoldedModel(new ScaffoldedFile(Path.Combine("..", "Data", "TestContext.cs"), "// TestContext")) { - ContextFile = new ScaffoldedFile { Path = Path.Combine("..", "Data", "TestContext.cs"), Code = "// TestContext" }, - AdditionalFiles = { new ScaffoldedFile { Path = "TestEntity.cs", Code = "// TestEntity" } } + AdditionalFiles = { new ScaffoldedFile("TestEntity.cs", "// TestEntity") } }; var result = scaffolder.Save( @@ -56,10 +55,9 @@ public void Save_throws_when_existing_files() File.WriteAllText(entityTypePath, "// Old"); var scaffolder = CreateScaffolder(); - var scaffoldedModel = new ScaffoldedModel + var scaffoldedModel = new ScaffoldedModel(new ScaffoldedFile("TestContext.cs", "// TestContext")) { - ContextFile = new ScaffoldedFile { Path = "TestContext.cs", Code = "// TestContext" }, - AdditionalFiles = { new ScaffoldedFile { Path = "TestEntity.cs", Code = "// TestEntity" } } + AdditionalFiles = { new ScaffoldedFile("TestEntity.cs", "// TestEntity") } }; var ex = Assert.Throws( @@ -80,7 +78,7 @@ public void Save_works_when_overwriteFiles() File.WriteAllText(path, "// Old"); var scaffolder = CreateScaffolder(); - var scaffoldedModel = new ScaffoldedModel { ContextFile = new ScaffoldedFile { Path = "Test.cs", Code = "// Test" } }; + var scaffoldedModel = new ScaffoldedModel(new ScaffoldedFile("Test.cs", "// Test")); var result = scaffolder.Save(scaffoldedModel, directory.Path, overwriteFiles: true); @@ -104,10 +102,9 @@ public void Save_throws_when_readonly_files() try { var scaffolder = CreateScaffolder(); - var scaffoldedModel = new ScaffoldedModel + var scaffoldedModel = new ScaffoldedModel(new ScaffoldedFile("TestContext.cs", "// TestContext")) { - ContextFile = new ScaffoldedFile { Path = "TestContext.cs", Code = "// TestContext" }, - AdditionalFiles = { new ScaffoldedFile { Path = "TestEntity.cs", Code = "// TestEntity" } } + AdditionalFiles = { new ScaffoldedFile("TestEntity.cs", "// TestEntity") } }; var ex = Assert.Throws( @@ -158,7 +155,10 @@ public void ScaffoldModel_works_with_named_connection_string() "Name=DefaultConnection", new DatabaseModelFactoryOptions(), new ModelReverseEngineerOptions(), - new ModelCodeGenerationOptions()); + new ModelCodeGenerationOptions + { + ModelNamespace = "Foo" + }); Assert.Equal("Data Source=Test", databaseModelFactory.ConnectionString);