Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to change PK and FK names in TPT tables? (fluent API, EF Core 7) #30376

Closed
Saibamen opened this issue Mar 1, 2023 · 4 comments
Closed

How to change PK and FK names in TPT tables? (fluent API, EF Core 7) #30376

Saibamen opened this issue Mar 1, 2023 · 4 comments

Comments

@Saibamen
Copy link

Saibamen commented Mar 1, 2023

How to change PK and FK names in TPT tables? (fluent API, EF Core 7)

I need to be compatible with database generated by legacy EF6.
I have few TPT tables (base class is also included in DB), but I don't know how to change:

  1. PK names in base table and child tables
  2. FK names for (base table) ID in child tables

Include your code

Models

public class KatalogArtikel
{
    public long KatalogArtikelId { get; set; }
    public decimal VEMenge { get; set; }
    public decimal VEPreis { get; set; }
    public bool Freigabe_ARTOS { get; set; }
    public DateTime ChangedDate { get; set; }
    (...)
}
public class ProfilArtikel : KatalogArtikel
{
    public int ProfilLaengeMM { get; set; }
}
public class DienstleistungsArtikel : KatalogArtikel
{
    
}

Configurations

KatalogArtikel:

public void Configure(EntityTypeBuilder<KatalogArtikel> entity)
{
    entity.HasIndex(e => e.KatalogArtikelId).HasDatabaseName("IX_KatalogArtikelId");
    entity.Property(e => e.KatalogArtikelId).ValueGeneratedOnAdd().UseIdentityColumn().Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
    // TODO: How to change PK name, but only for KatalogArtikel table, not for all tables?
    entity.HasKey(e => e.KatalogArtikelId);//.HasName("PK_dbo.KatalogArtikel");
    entity.Property(e => e.Freigabe_ARTOS).HasDefaultValueSql("((0))").ValueGeneratedNever();
    entity.Property(e => e.ChangedDate).HasColumnType("datetime");
    entity.Property(e => e.VEMenge).HasPrecision(18, 2);
    entity.Property(e => e.VEPreis).HasPrecision(18, 4).HasDefaultValueSql("((0))");
    (...)

    entity.UseTptMappingStrategy();

    /*
     * Column order - to improve comparison of changes between EF6 vs EF Core DB schema
     */
    entity.Property(e => e.Bezeichnung).HasColumnOrder(1);
    entity.Property(e => e.ImageFileName).HasColumnOrder(2);
    (...)

    // FKeys
    (...)
}

KatalogArtikel_Profile:

public class ProfilArtikelConfiguration : IEntityTypeConfiguration<ProfilArtikel>
{
    public void Configure(EntityTypeBuilder<ProfilArtikel> entity)
    {
        entity.ToTable("KatalogArtikel_Profile");
        entity.HasBaseType<KatalogArtikel>();
        // TODO: How to change PK name in TPT table?
        // TODO: In DB we have: CONSTRAINT [PK_dbo.KatalogArtikel_Profile] PRIMARY KEY CLUSTERED ([KatalogArtikelId] ASC),
        //entity.HasKey(e => e.KatalogArtikelId).HasName("PK_dbo.KatalogArtikel_Profile");
        entity.HasIndex(e => e.KatalogArtikelId).IsUnique(false).HasDatabaseName("IX_KatalogArtikelId");
        entity.Property(e => e.ProfilLaengeMM).HasColumnName("ProfilLaengeMM");

        // TODO: How to change FK name in TPT table?
        // TODO: In DB we have: CONSTRAINT [FK_KatalogArtikel_Profile_dbo.KatalogArtikel_KatalogArtikelId] FOREIGN KEY ([KatalogArtikelId]) REFERENCES [dbo].[KatalogArtikel] ([KatalogArtikelId])
    }
}

KatalogArtikel_Dienstleistungen:

public void Configure(EntityTypeBuilder<DienstleistungsArtikel> entity)
{
    entity.ToTable("KatalogArtikel_Dienstleistungen");
    entity.HasBaseType<KatalogArtikel>();
    // TODO: How to change PK name in TPT table?
    // TODO: In DB we have: CONSTRAINT [PK_dbo.KatalogArtikel_Dienstleistungen] PRIMARY KEY CLUSTERED ([KatalogArtikelId] ASC),
    //entity.HasKey(e => e.KatalogArtikelId).HasName("PK_dbo.KatalogArtikel_Dienstleistungen");
    entity.HasIndex(e => e.KatalogArtikelId).IsUnique(false).HasDatabaseName("IX_KatalogArtikelId");

    // TODO: How to change FK name in TPT table?
    // TODO: In DB we have: CONSTRAINT [FK_KatalogArtikel_Dienstleistungen_dbo.KatalogArtikel_KatalogArtikelId] FOREIGN KEY ([KatalogArtikelId]) REFERENCES [dbo].[KatalogArtikel] ([KatalogArtikelId])
}

Include stack traces

When I want to change PK name for KatalogArtikel table (entity.HasKey(e => e.KatalogArtikelId).HasName("PK_dbo.KatalogArtikel");), migration will change all PK names in all TPT tables instead of just KatalogArtikel...

Applying migration '20230301150353_init'.
Failed executing DbCommand (110ms) [Parameters=[], CommandType='Text', CommandTimeout='120']
CREATE TABLE [KatalogArtikel_Dienstleistungen] (
    [KatalogArtikelId] bigint NOT NULL,
    CONSTRAINT [PK_dbo.KatalogArtikel] PRIMARY KEY ([KatalogArtikelId]),
    CONSTRAINT [FK_KatalogArtikel_Dienstleistungen_KatalogArtikel_KatalogArtikelId] FOREIGN KEY ([KatalogArtikelId]) REFERENCES [KatalogArtikel] ([KatalogArtikelId]) ON DELETE CASCADE
);
Microsoft.Data.SqlClient.SqlException (0x80131904): There is already an object named 'PK_dbo.KatalogArtikel' in the database.
Could not create constraint or index. See previous errors.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\SqlConnection.cs:line 2010
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\src\Microsoft\Data\SqlClient\SqlInternalConnection.cs:line 770
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\TdsParser.cs:line 1404
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\TdsParser.cs:line 2622
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\SqlCommand.cs:line 3479
   at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\SqlCommand.cs:line 1662
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery() in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\netcore\src\Microsoft\Data\SqlClient\SqlCommand.cs:line 1208
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:xxxxx
Error Number:2714,State:5,Class:16

Include provider and version information

EF Core version: 7.0.3
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows
IDE: Visual Studio 2022 17.5

@ajcvickers
Copy link
Member

@Saibamen I haven't tried it for constraint names, but I suspect using the table builder API is the way to do, as shown here for column names: https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#properties-mapped-to-different-column-names

@Saibamen
Copy link
Author

Saibamen commented Mar 2, 2023

@ajcvickers: builder API doesn't have HasKey and HasOne (for FK) methods:

image

Documentation for OwnedNavigationTableBuilder: https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.builders.ownednavigationtablebuilder?view=efcore-7.0#methods

@ajcvickers
Copy link
Member

@AndriySvyryd may know.

@AndriySvyryd
Copy link
Member

Not implemented yet. See #27971 and #27972

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Mar 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants