dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.79k stars 3.19k forks source link

Unable to Scaffold DBContext if tables in SQL Server have certain names #32571

Closed michaelbyrdmba closed 10 months ago

michaelbyrdmba commented 11 months ago

I've been working on switching a ASP.NET Core Web API from using .NET 6 to .NET 8. This project is database first and uses Entity Framework (6 and 8 respectively) to scaffold the DBContext and models into the API.

I have tried several different methods of upgrading the project to see if I can get .NET 8 and EF Core 8 to properly scaffold my DB. I have tried both creating a brand new ASP.Net Core Web API from the Visual Studio template and scaffolding in the brand new project, as well as trying to use the .NET upgrade assistant on the existing .NET 6 API.

If I use the .NET upgrade assistant, the models and DBContext get moved over to the .NET 8 project, however, if you try and run the Scaffold-DBContext command in PMC after the upgrade it will still fail, even if you have the -Force flag in your command to overwrite your existing models.

The error message that you get back is as follows:

PM> Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose
Using project 'NET8Test'.
Using startup project 'NET8Test'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.deps.json --additionalprobingpath C:\Users\.nuget\packages --runtimeconfig C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.runtimeconfig.json C:\Users\.nuget\packages\microsoft.entityframeworkcore.tools\8.0.0\tools\netcoreapp2.0\any\ef.dll dbcontext scaffold Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer --json --output-dir Models --force --verbose --no-color --prefix-output --assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --project C:\Users\source\repos\NET8Test\NET8Test.csproj --startup-assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --startup-project C:\Users\source\repos\NET8Test\NET8Test.csproj --project-dir C:\Users\source\repos\NET8Test\ --language C# --configuration Debug --working-dir C:\Users\source\repos\NET8Test --root-namespace NET8Test --nullable
Using assembly 'NET8Test'.
Using startup assembly 'NET8Test'.
Using application base 'C:\Users\source\repos\NET8Test\bin\Debug\net8.0'.
Using working directory 'C:\Users\source\repos\NET8Test'.
Using root namespace 'NET8Test'.
Using project directory 'C:\Users\source\repos\NET8Test\'.
Remaining arguments: .
Finding design-time services referenced by assembly 'NET8Test'...
Finding design-time services referenced by assembly 'NET8Test'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'NET8Test'...
No design-time services were found.
Finding application service provider in assembly 'NET8Test'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found default schema 'dbo'.
Found type alias with name 'sys.sysname' which maps to underlying data type nvarchar(128).
Found table with name 'dbo.AttributesByCategory'.
Found table with name 'dbo.Properties'.
Found table with name 'dbo.TableAB'.
Found table with name 'dbo.TableB'.
Found table with name 'dbo.TableC'.
Found column with table: dbo.AttributesByCategory, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.AttributesByCategory, column name: IdC, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Properties, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Properties, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Properties, column name: IdC, ordinal: 3, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableB, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableC, column name: IdC, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found primary key on table 'PK_IdB_IdC' with name 'dbo.AttributesByCategory'.
Found primary key on table 'PK_IdA_IdB_IdC' with name 'dbo.Properties'.
Found unique constraint on table 'UC_IdA_IdC' with name 'dbo.Properties'.
Found primary key on table 'PK_IdA' with name 'dbo.TableAB'.
Found unique constraint on table 'UC_IdA_IdB' with name 'dbo.TableAB'.
Found primary key on table 'PK_IdB' with name 'dbo.TableB'.
Found primary key on table 'PK_IdC' with name 'dbo.TableC'.
Found foreign key on table 'FK_AttributesByCategory_Attributes' with name 'dbo.AttributesByCategory', principal table 'dbo.TableC', delete action NO_ACTION.
Found foreign key on table 'FK_AttributesByCategory_Category' with name 'dbo.AttributesByCategory', principal table 'dbo.TableB', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_AttributesByCategory' with name 'dbo.Properties', principal table 'dbo.AttributesByCategory', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_Listings' with name 'dbo.Properties', principal table 'dbo.TableAB', delete action NO_ACTION.
Found foreign key on table 'FK_Listings_Category' with name 'dbo.TableAB', principal table 'dbo.TableB', delete action NO_ACTION.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpDbContextGenerator.TransformText()
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.ProcessTemplate(ITextTransformation transformation)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.GenerateModel(IModel model, ModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions)
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.

However, through lots of trial and error, I've discovered that it seems to be throwing this exception if you have tables with certain names. For instance, I can change the name of either the 'Properties' or 'AttributesByCategory' table and it will scaffold successfully.

However, again there seem to be certain strings that cause it to throw the NRE that I was getting up above.

Here are some examples. One thing to note, I change the name of the table directly from the database diagram in the properties window and then make sure to save the database diagram to ensure that changes take affect and the all existing relationship and references are maintained. Also, I know that some of the FKs still have their old names. I was trying to recreate the issue in the smallest form possible. I renamed many of the tables and the PKs during this process and then scaffolded after each change to see what would happen. This is what I am able to get to either succeed or fail consistently.

1) Change 'Properties' to 'Property' -> Fail

PM> Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose
Using project 'NET8Test'.
Using startup project 'NET8Test'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.deps.json --additionalprobingpath C:\Users\.nuget\packages --runtimeconfig C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.runtimeconfig.json C:\Users\.nuget\packages\microsoft.entityframeworkcore.tools\8.0.0\tools\netcoreapp2.0\any\ef.dll dbcontext scaffold Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer --json --output-dir Models --force --verbose --no-color --prefix-output --assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --project C:\Users\source\repos\NET8Test\NET8Test.csproj --startup-assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --startup-project C:\Users\source\repos\NET8Test\NET8Test.csproj --project-dir C:\Users\source\repos\NET8Test\ --language C# --configuration Debug --working-dir C:\Users\source\repos\NET8Test --root-namespace NET8Test --nullable
Using assembly 'NET8Test'.
Using startup assembly 'NET8Test'.
Using application base 'C:\Users\source\repos\NET8Test\bin\Debug\net8.0'.
Using working directory 'C:\Users\source\repos\NET8Test'.
Using root namespace 'NET8Test'.
Using project directory 'C:\Users\source\repos\NET8Test\'.
Remaining arguments: .
Finding design-time services referenced by assembly 'NET8Test'...
Finding design-time services referenced by assembly 'NET8Test'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'NET8Test'...
No design-time services were found.
Finding application service provider in assembly 'NET8Test'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found default schema 'dbo'.
Found type alias with name 'sys.sysname' which maps to underlying data type nvarchar(128).
Found table with name 'dbo.AttributesByCategory'.
Found table with name 'dbo.Property'.
Found table with name 'dbo.TableAB'.
Found table with name 'dbo.TableB'.
Found table with name 'dbo.TableC'.
Found column with table: dbo.AttributesByCategory, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.AttributesByCategory, column name: IdC, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Property, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Property, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.Property, column name: IdC, ordinal: 3, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableB, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableC, column name: IdC, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found primary key on table 'PK_IdB_IdC' with name 'dbo.AttributesByCategory'.
Found primary key on table 'PK_IdA_IdB_IdC' with name 'dbo.Property'.
Found unique constraint on table 'UC_IdA_IdC' with name 'dbo.Property'.
Found primary key on table 'PK_IdA' with name 'dbo.TableAB'.
Found unique constraint on table 'UC_IdA_IdB' with name 'dbo.TableAB'.
Found primary key on table 'PK_IdB' with name 'dbo.TableB'.
Found primary key on table 'PK_IdC' with name 'dbo.TableC'.
Found foreign key on table 'FK_AttributesByCategory_Attributes' with name 'dbo.AttributesByCategory', principal table 'dbo.TableC', delete action NO_ACTION.
Found foreign key on table 'FK_AttributesByCategory_Category' with name 'dbo.AttributesByCategory', principal table 'dbo.TableB', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_AttributesByCategory' with name 'dbo.Property', principal table 'dbo.AttributesByCategory', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_Listings' with name 'dbo.Property', principal table 'dbo.TableAB', delete action NO_ACTION.
Found foreign key on table 'FK_Listings_Category' with name 'dbo.TableAB', principal table 'dbo.TableB', delete action NO_ACTION.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpDbContextGenerator.TransformText()
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.ProcessTemplate(ITextTransformation transformation)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.GenerateModel(IModel model, ModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions)
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.

2) Change 'Properties' to 'ListingProp' -> Fail

PM> Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose
Using project 'NET8Test'.
Using startup project 'NET8Test'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.deps.json --additionalprobingpath C:\Users\.nuget\packages --runtimeconfig C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.runtimeconfig.json C:\Users\.nuget\packages\microsoft.entityframeworkcore.tools\8.0.0\tools\netcoreapp2.0\any\ef.dll dbcontext scaffold Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer --json --output-dir Models --force --verbose --no-color --prefix-output --assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --project C:\Users\source\repos\NET8Test\NET8Test.csproj --startup-assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --startup-project C:\Users\source\repos\NET8Test\NET8Test.csproj --project-dir C:\Users\source\repos\NET8Test\ --language C# --configuration Debug --working-dir C:\Users\source\repos\NET8Test --root-namespace NET8Test --nullable
Using assembly 'NET8Test'.
Using startup assembly 'NET8Test'.
Using application base 'C:\Users\source\repos\NET8Test\bin\Debug\net8.0'.
Using working directory 'C:\Users\source\repos\NET8Test'.
Using root namespace 'NET8Test'.
Using project directory 'C:\Users\source\repos\NET8Test\'.
Remaining arguments: .
Finding design-time services referenced by assembly 'NET8Test'...
Finding design-time services referenced by assembly 'NET8Test'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'NET8Test'...
No design-time services were found.
Finding application service provider in assembly 'NET8Test'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found default schema 'dbo'.
Found type alias with name 'sys.sysname' which maps to underlying data type nvarchar(128).
Found table with name 'dbo.AttributesByCategory'.
Found table with name 'dbo.ListingProp'.
Found table with name 'dbo.TableAB'.
Found table with name 'dbo.TableB'.
Found table with name 'dbo.TableC'.
Found column with table: dbo.AttributesByCategory, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.AttributesByCategory, column name: IdC, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.ListingProp, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.ListingProp, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.ListingProp, column name: IdC, ordinal: 3, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableB, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableC, column name: IdC, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found primary key on table 'PK_IdB_IdC' with name 'dbo.AttributesByCategory'.
Found primary key on table 'PK_IdA_IdB_IdC' with name 'dbo.ListingProp'.
Found unique constraint on table 'UC_IdA_IdC' with name 'dbo.ListingProp'.
Found primary key on table 'PK_IdA' with name 'dbo.TableAB'.
Found unique constraint on table 'UC_IdA_IdB' with name 'dbo.TableAB'.
Found primary key on table 'PK_IdB' with name 'dbo.TableB'.
Found primary key on table 'PK_IdC' with name 'dbo.TableC'.
Found foreign key on table 'FK_AttributesByCategory_Attributes' with name 'dbo.AttributesByCategory', principal table 'dbo.TableC', delete action NO_ACTION.
Found foreign key on table 'FK_AttributesByCategory_Category' with name 'dbo.AttributesByCategory', principal table 'dbo.TableB', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_AttributesByCategory' with name 'dbo.ListingProp', principal table 'dbo.AttributesByCategory', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_Listings' with name 'dbo.ListingProp', principal table 'dbo.TableAB', delete action NO_ACTION.
Found foreign key on table 'FK_Listings_Category' with name 'dbo.TableAB', principal table 'dbo.TableB', delete action NO_ACTION.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpDbContextGenerator.TransformText()
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.ProcessTemplate(ITextTransformation transformation)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpModelGenerator.GenerateModel(IModel model, ModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions)
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.

3) Change 'Properties' to 'ABCProp' -> Succeeds

PM> Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose
Using project 'NET8Test'.
Using startup project 'NET8Test'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.deps.json --additionalprobingpath C:\Users\.nuget\packages --runtimeconfig C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.runtimeconfig.json C:\Users\.nuget\packages\microsoft.entityframeworkcore.tools\8.0.0\tools\netcoreapp2.0\any\ef.dll dbcontext scaffold Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer --json --output-dir Models --force --verbose --no-color --prefix-output --assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --project C:\Users\source\repos\NET8Test\NET8Test.csproj --startup-assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --startup-project C:\Users\source\repos\NET8Test\NET8Test.csproj --project-dir C:\Users\source\repos\NET8Test\ --language C# --configuration Debug --working-dir C:\Users\source\repos\NET8Test --root-namespace NET8Test --nullable
Using assembly 'NET8Test'.
Using startup assembly 'NET8Test'.
Using application base 'C:\Users\source\repos\NET8Test\bin\Debug\net8.0'.
Using working directory 'C:\Users\source\repos\NET8Test'.
Using root namespace 'NET8Test'.
Using project directory 'C:\Users\source\repos\NET8Test\'.
Remaining arguments: .
Finding design-time services referenced by assembly 'NET8Test'...
Finding design-time services referenced by assembly 'NET8Test'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'NET8Test'...
No design-time services were found.
Finding application service provider in assembly 'NET8Test'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found default schema 'dbo'.
Found type alias with name 'sys.sysname' which maps to underlying data type nvarchar(128).
Found table with name 'dbo.ABCProp'.
Found table with name 'dbo.AttributesByCategory'.
Found table with name 'dbo.TableAB'.
Found table with name 'dbo.TableB'.
Found table with name 'dbo.TableC'.
Found column with table: dbo.ABCProp, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.ABCProp, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.ABCProp, column name: IdC, ordinal: 3, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.AttributesByCategory, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.AttributesByCategory, column name: IdC, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdA, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableAB, column name: IdB, ordinal: 2, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: False, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableB, column name: IdB, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found column with table: dbo.TableC, column name: IdC, ordinal: 1, data type: sys.bigint, maximum length: 8, precision: 19, scale: 0, nullable: False, identity: True, default value: (null), computed value: (null), computed value is stored: False.
Found primary key on table 'PK_IdA_IdB_IdC' with name 'dbo.ABCProp'.
Found unique constraint on table 'UC_IdA_IdC' with name 'dbo.ABCProp'.
Found primary key on table 'PK_IdB_IdC' with name 'dbo.AttributesByCategory'.
Found primary key on table 'PK_IdA' with name 'dbo.TableAB'.
Found unique constraint on table 'UC_IdA_IdB' with name 'dbo.TableAB'.
Found primary key on table 'PK_IdB' with name 'dbo.TableB'.
Found primary key on table 'PK_IdC' with name 'dbo.TableC'.
Found foreign key on table 'FK_Properties_AttributesByCategory' with name 'dbo.ABCProp', principal table 'dbo.AttributesByCategory', delete action NO_ACTION.
Found foreign key on table 'FK_Properties_Listings' with name 'dbo.ABCProp', principal table 'dbo.TableAB', delete action NO_ACTION.
Found foreign key on table 'FK_AttributesByCategory_Attributes' with name 'dbo.AttributesByCategory', principal table 'dbo.TableC', delete action NO_ACTION.
Found foreign key on table 'FK_AttributesByCategory_Category' with name 'dbo.AttributesByCategory', principal table 'dbo.TableB', delete action NO_ACTION.
Found foreign key on table 'FK_Listings_Category' with name 'dbo.TableAB', principal table 'dbo.TableB', delete action NO_ACTION.

In order to recreate this bug, please complete the following steps: 1) Create a new database in SQL Server (I have tried this with SQL Express Version 16.0.1000, SQL Server Enterprise Version 14.0.3421.10, and Azure SQL Server Version 12.0.2000.8 and get the same error on all versions of SQL Server) 2) Create the required tables in this order, to prevent issues with FK constraints. As mentioned above, I know that many of the FKs still have their old names. I am also aware that the Unique Non-Clustered Index on the "Properties" table looks weird since it is on IdA and IdC, but the primary Key is on IdA, IdB, and IdC. This is by design and is part of the larger DB structure that is required. Only leaving it in here as this is the simplest version of the DB that I have been able to reproduce the error with. I stopped short of check if the constraints or FK were causing the issue once I discovered that renaming the "Properties" table fixed the issue.

2.1) TableC

/****** Object:  Table [dbo].[TableC]    Script Date: 12/8/2023 2:02:35 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TableC](
    [IdC] [BIGINT] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_IdC] PRIMARY KEY CLUSTERED 
(
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

2.2) TableB

/****** Object:  Table [dbo].[TableB]    Script Date: 12/8/2023 2:03:09 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TableB](
    [IdB] [BIGINT] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_IdB] PRIMARY KEY CLUSTERED 
(
    [IdB] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

2.3) TableAB

/****** Object:  Table [dbo].[TableAB]    Script Date: 12/8/2023 2:03:33 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TableAB](
    [IdA] [BIGINT] IDENTITY(1,1) NOT NULL,
    [IdB] [BIGINT] NOT NULL,
 CONSTRAINT [PK_IdA] PRIMARY KEY CLUSTERED 
(
    [IdA] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [UC_IdA_IdB] UNIQUE NONCLUSTERED 
(
    [IdA] ASC,
    [IdB] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[TableAB]  WITH CHECK ADD  CONSTRAINT [FK_Listings_Category] FOREIGN KEY([IdB])
REFERENCES [dbo].[TableB] ([IdB])
GO

ALTER TABLE [dbo].[TableAB] CHECK CONSTRAINT [FK_Listings_Category]
GO

2.4) AttributesByCategory

/****** Object:  Table [dbo].[AttributesByCategory]    Script Date: 12/8/2023 2:04:02 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[AttributesByCategory](
    [IdB] [BIGINT] NOT NULL,
    [IdC] [BIGINT] NOT NULL,
 CONSTRAINT [PK_IdB_IdC] PRIMARY KEY CLUSTERED 
(
    [IdB] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[AttributesByCategory]  WITH CHECK ADD  CONSTRAINT [FK_AttributesByCategory_Attributes] FOREIGN KEY([IdC])
REFERENCES [dbo].[TableC] ([IdC])
GO

ALTER TABLE [dbo].[AttributesByCategory] CHECK CONSTRAINT [FK_AttributesByCategory_Attributes]
GO

ALTER TABLE [dbo].[AttributesByCategory]  WITH CHECK ADD  CONSTRAINT [FK_AttributesByCategory_Category] FOREIGN KEY([IdB])
REFERENCES [dbo].[TableB] ([IdB])
GO

ALTER TABLE [dbo].[AttributesByCategory] CHECK CONSTRAINT [FK_AttributesByCategory_Category]
GO

2.5) Properties

/****** Object:  Table [dbo].[Properties]    Script Date: 12/8/2023 2:04:37 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Properties](
    [IdA] [BIGINT] NOT NULL,
    [IdB] [BIGINT] NOT NULL,
    [IdC] [BIGINT] NOT NULL,
 CONSTRAINT [PK_IdA_IdB_IdC] PRIMARY KEY CLUSTERED 
(
    [IdA] ASC,
    [IdB] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [UC_IdA_IdC] UNIQUE NONCLUSTERED 
(
    [IdA] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Properties]  WITH CHECK ADD  CONSTRAINT [FK_Properties_AttributesByCategory] FOREIGN KEY([IdB], [IdC])
REFERENCES [dbo].[AttributesByCategory] ([IdB], [IdC])
GO

ALTER TABLE [dbo].[Properties] CHECK CONSTRAINT [FK_Properties_AttributesByCategory]
GO

ALTER TABLE [dbo].[Properties]  WITH CHECK ADD  CONSTRAINT [FK_Properties_Listings] FOREIGN KEY([IdA], [IdB])
REFERENCES [dbo].[TableAB] ([IdA], [IdB])
GO

ALTER TABLE [dbo].[Properties] CHECK CONSTRAINT [FK_Properties_Listings]
GO

3) Open up Visual Studio. 4) Select "Create a New Project" 5) Select the "ASP.NET Core Web API" template 6) Set the framework to .NET 8.0 -Leave the Authentication type as "None" -Keep "Configure for HTTPS" checked -Leave "Enable Docker" unchecked -Keep "Enable for OpenAPI support" checked -Leave "Do not use top-level statements" unchecked -Keep "Use Controllers" checked 7) Install the following NuGet packages: -Microsoft.EntityFrameworkCore 8.0.0 -Microsoft.EntityFrameworkCore.Design 8.0.0 -Microsoft.EntityFrameworkCore.SqlServer 8.0.0 -Microsoft.EntityFrameworkCore.Tools 8.0.0

This is what my .csproj file looks like after installing all of the packages.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <InvariantGlobalization>false</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>

</Project>

As a side note, you will likely need to override the "Invariant Globalization" setting in the .csproj file to "false", as seen above, otherwise you may get the following error when you try and run the scaffold command:

Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose
Using project 'NET8Test'.
Using startup project 'NET8Test'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.deps.json --additionalprobingpath C:\Users\.nuget\packages --runtimeconfig C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.runtimeconfig.json C:\Users\.nuget\packages\microsoft.entityframeworkcore.tools\8.0.0\tools\netcoreapp2.0\any\ef.dll dbcontext scaffold Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer --json --output-dir Models --force --verbose --no-color --prefix-output --assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --project C:\Users\source\repos\NET8Test\NET8Test.csproj --startup-assembly C:\Users\source\repos\NET8Test\bin\Debug\net8.0\NET8Test.dll --startup-project C:\Users\source\repos\NET8Test\NET8Test.csproj --project-dir C:\Users\source\repos\NET8Test\ --language C# --configuration Debug --working-dir C:\Users\source\repos\NET8Test --root-namespace NET8Test --nullable
Using assembly 'NET8Test'.
Using startup assembly 'NET8Test'.
Using application base 'C:\Users\source\repos\NET8Test\bin\Debug\net8.0'.
Using working directory 'C:\Users\source\repos\NET8Test'.
Using root namespace 'NET8Test'.
Using project directory 'C:\Users\source\repos\NET8Test\'.
Remaining arguments: .
Finding design-time services referenced by assembly 'NET8Test'...
Finding design-time services referenced by assembly 'NET8Test'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'NET8Test'...
No design-time services were found.
Finding application service provider in assembly 'NET8Test'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
en-us is an invalid culture identifier.
   at System.Globalization.CultureInfo.GetCultureInfo(String name)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open()
   at Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal.SqlServerDatabaseModelFactory.Create(DbConnection connection, DatabaseModelFactoryOptions options)
   at Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal.SqlServerDatabaseModelFactory.Create(String connectionString, DatabaseModelFactoryOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions)
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
en-us is an invalid culture identifier.

8) Set up your appsettings.json file with the connection to your database:

{
  "UseInMemoryDatabase": false,
  "ConnectionStrings": {
    "DefaultConnection": "Server=SERVERNAME;Initial Catalog=DATABASENAME;Trusted_Connection=True;Persist Security Info=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

9) Run the PMC Command

Scaffold-DBContext 'Name=ConnectionStrings:DefaultConnection' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -Verbose

This should reproduce the error that throws the NRE error. If you then go into the database diagram and change the name of the "Properties" table to "ABCProp", save the database and then try to run the PMC command again, the scaffold should succeed.

One final thing, if you follow the exact same instructions as above for the ASP.NET Core Web API, but set it up for .NET 6.0 and install all of the same NuGet packages as above in version 6.0.0, the scaffold command will succeed without changing the name of the tables in the DB. This seems to be a breaking change with EF Core 7 and 8.

If this can't be fixed to allow all tables names, it would at least be nice to have a list of table names that will break EF Core and/or instead of throwing an NRE, at least display the affected table names that need to be changed in the stack trace.

Please let me know if you have any further questions or if I can provide any other assistance on this error. I tried to be as thorough as possible when explaining what cause the issue.

EF Core version: 8.0.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 8.0 Operating system: Windows 10 IDE: Tried in both Visual Studio Community 2022 64-Bit Version 17.8.3 and Version 17.7.6

ErikEJ commented 11 months ago

I have reduced the repro to this (removing a table):

CREATE TABLE [dbo].[TableC](
    [IdC] [BIGINT] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_IdC] PRIMARY KEY CLUSTERED 
(
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TableB](
    [IdB] [BIGINT] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_IdB] PRIMARY KEY CLUSTERED 
(
    [IdB] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[AttributesByCategory](
    [IdB] [BIGINT] NOT NULL,
    [IdC] [BIGINT] NOT NULL,
 CONSTRAINT [PK_IdB_IdC] PRIMARY KEY CLUSTERED 
(
    [IdB] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[AttributesByCategory]  WITH CHECK ADD  CONSTRAINT [FK_AttributesByCategory_Attributes] FOREIGN KEY([IdC])
REFERENCES [dbo].[TableC] ([IdC])
GO

ALTER TABLE [dbo].[AttributesByCategory]  WITH CHECK ADD  CONSTRAINT [FK_AttributesByCategory_Category] FOREIGN KEY([IdB])
REFERENCES [dbo].[TableB] ([IdB])
GO

CREATE TABLE [dbo].[Properties](
    [IdA] [BIGINT] NOT NULL,
    [IdB] [BIGINT] NOT NULL,
    [IdC] [BIGINT] NOT NULL,
 CONSTRAINT [PK_IdA_IdB_IdC] PRIMARY KEY CLUSTERED 
(
    [IdA] ASC,
    [IdB] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [UC_IdA_IdC] UNIQUE NONCLUSTERED 
(
    [IdA] ASC,
    [IdC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Properties]  WITH CHECK ADD  CONSTRAINT [FK_Properties_AttributesByCategory] FOREIGN KEY([IdB], [IdC])
REFERENCES [dbo].[AttributesByCategory] ([IdB], [IdC])
GO

Doing this fixes the NRE:

ALTER TABLE [dbo].[Properties] DROP CONSTRAINT [FK_Properties_AttributesByCategory]
GO
ErikEJ commented 11 months ago

@michaelbyrdmba I am not sure it is related to naming!

michaelbyrdmba commented 11 months ago

@ErikEJ Just to confirm, this is indeed an issue with EF Core 7/8 not being able to handle this constraint since it works in EF Core 6. Is that correct?

Otherwise, why does that constraint throw an NRE? From the documentation I've been able to find there should be no reason for the NRE.

As I mentioned in my initial post, that constraint is required in the overall larger schema of the database but does not make a lot of sense in this reduced version.

michaelbyrdmba commented 11 months ago

I talked with another developer today and mentioned the issue with the table name. He mentioned that I should check to see if they were for some reason being scaffolded alphabetically, instead of by dependency.

We validated this theory and this does seem to be the case, which aligns with what I mentioned above:

For instance, I can change the name of either the 'Properties' or 'AttributesByCategory' table and it will scaffold successfully.

This statement is partially true, but it will only scaffold successfully if you name it something in the correct alphabetical order.

For instance:

As a side note, I'm happy to try and help debug if I can. It would be great to further understand how to debug EF Core directly when something throws an NRE. I haven't been able to find much documentation on how to do this other than these two articles, both of which seem to be targeting an earlier version of .NET and no longer work (or the code/instructions are not clear on how to successfully debug a scaffold command):

ajcvickers commented 11 months ago

Note for triage: this is a regression from 6 to 7 related to the T4 template introduction.

michaelbyrdmba commented 11 months ago

@ajcvickers Is this something that I can help triage?

ajcvickers commented 11 months ago

@michaelbyrdmba No, thanks. This is something the team needs to do. It will likely happen in the new year, since a lot of the team will be out the rest of the year.

ErikEJ commented 11 months ago

@michaelbyrdmba Just realised you can work around this by preserving the many to many entity with EF Core Power Tools! https://github.com/ErikEJ/EFCorePowerTools/wiki/Reverse-Engineering#code-generation

ajcvickers commented 11 months ago

Verified same root cause as #28905. Fixed by #32627.

ErikEJ commented 11 months ago

@ajcvickers Just to be clear, this will be fixed in EF9 (only)?

ajcvickers commented 11 months ago

@ErikEJ Despite what I said yesterday, we will discuss.

michaelbyrdmba commented 11 months ago

@ajcvickers @ErikEJ Just to clarify, is this going to be fixed in EF8 (if so, which version number) or in EF9?

ErikEJ commented 11 months ago

It is being considered

michaelbyrdmba commented 10 months ago

@ajcvickers I saw that this issue got closed and is going to be released in EF 8.0.2. Which NuGet package(s) will need to be updated for this to work and when will 8.0.2 be released?

This was the list of NuGet packages that I had previously installed: Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.Tools

ajcvickers commented 10 months ago

@michaelbyrdmba This still needs to approved by management. 8.0.2 is currently scheduled for February. You should always update all EF packages you are using to the same version.