EntityFramework.Docs
EntityFramework.Docs copied to clipboard
scaffolding change in the name of navigation property since dotnet 8.0 ?
I'm working on a asp.net core backend that was on .net 6 and we're trying to migrate it to .net 8.
We have noticed a change for which we haven't yet found documentation. Given a simple Test
database with the following 3 tables:
CREATE TABLE [dbo].[ItemCategory] (
[Name] VARCHAR (25) NOT NULL,
[Description] NVARCHAR (512) NULL,
CONSTRAINT [PK_ItemCategory] PRIMARY KEY CLUSTERED ([Name] ASC),
);
CREATE TABLE [dbo].[Item] (
[Name] VARCHAR (40) NOT NULL,
[Description] NVARCHAR (512) NULL,
[CategoryName] VARCHAR (25) NOT NULL,
CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED ([Name] ASC, [CategoryName] ASC),
CONSTRAINT [FK_Item_ItemCategory] FOREIGN KEY ([CategoryName]) REFERENCES [dbo].[ItemCategory] ([Name]),
);
CREATE TABLE [dbo].[SomeTable] (
[Id] INT IDENTITY (1, 1) NOT FOR REPLICATION NOT NULL,
[DetailItemName] VARCHAR (40) NOT NULL,
[DetailItemCategoryName] VARCHAR (25) NOT NULL,
CONSTRAINT [PK_SomeTable] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_SomeTable_DetailItem] FOREIGN KEY ([DetailItemName], [DetailItemCategoryName]) REFERENCES [dbo].[Item] ([Name], [CategoryName])
);
I can use the following command to generate the c# classes:
dotnet ef dbcontext scaffold "Data Source=localhost\sqlexpress;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True;TrustServerCertificate=True" Microsoft.EntityFrameworkCore.SqlServer -f
if I use net6.0, namely with exactly this csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.25">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.25" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>
I get the following output for the SomeTable
C# class:
using System;
using System.Collections.Generic;
namespace ClassLibrary1
{
public partial class SomeTable
{
public int Id { get; set; }
public string DetailItemName { get; set; } = null!;
public string DetailItemCategoryName { get; set; } = null!;
public virtual Item DetailItem { get; set; } = null!;
}
}
However, if I switch to net8.0, using exactly this csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<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" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>
I get the following output:
using System;
using System.Collections.Generic;
namespace ClassLibrary1;
public partial class SomeTable
{
public int Id { get; set; }
public string DetailItemName { get; set; } = null!;
public string DetailItemCategoryName { get; set; } = null!;
public virtual Item Item { get; set; } = null!;
}
Notice that with net6.0 and net7.0 we get this:
public virtual Item DetailItem { get; set; } = null!;
but with net8.0 we get this:
public virtual Item Item { get; set; } = null!;
When I run the scaffold command in both cases I get the same output in both cases:
We have a lot of existing code and tables and we'd like to be able to use the "old naming scheme" if possible. Is there a way to do that ?
Thanks!
Note for triage: this is a consequence of https://github.com/dotnet/efcore/pull/29771, which stopped using common prefixes to generate navigation names.
@shikamu Custom T4 templates can be used to customize the navigation names to whatever you choose.
Note from triage: the new behavior is preferable to the old behavior, but for cases where the old behavior was reasonable we should document this as a breaking change.
@ajcvickers thanks for the replies. Is there a ready to use T4 template that emulates the old behaviour ? this would be quite useful to have as this is essentially a breaking change, and we would then be able to get around it in an effortless fashion.
@shikamu There is no specific template for this. Start from the default templates and edit the code that writes the navigation names.