Gibt es eine Möglichkeit, wenn C# Entity Framework Core -Gerüst diese alternative Schlüsselbeziehung ordnungsgemäß ohne
Posted: 20 Feb 2025, 12:13
Ich habe kürzlich versucht, eine Datenbank mit einer alternativen Schlüsselbeziehung unter Verwendung von C# Entity Framework Core und SQL Server zu senken, und war überrascht, dass ich das Datenbankschema nicht ohne manuelle Änderungen bereitstellen konnte. Siehe die minimale Datenbank -Setup unten: < /p>
Minimales Datenbank -Setup < /p>
Hier hat PrincipalTabelle zwei Tasten: einen Primärschlüssel und einen alternativen Schlüssel. Der abhängige Tisch hängt vom alternativen Schlüssel des PrincipalTabels ab. Wenn ich versuche, dies mit Entity Framework Core 9.0.2 auf .NET 8 und SQL Server 2022 zu scstellen Konvention. < /p>
Was ich ausprobiert habe, ist: < /p>
Fehlt mir etwas, um diese Arbeit ohne manuelle Intervention zu machen?
Minimales Datenbank -Setup < /p>
Hier hat PrincipalTabelle zwei Tasten: einen Primärschlüssel und einen alternativen Schlüssel. Der abhängige Tisch hängt vom alternativen Schlüssel des PrincipalTabels ab. Wenn ich versuche, dies mit Entity Framework Core 9.0.2 auf .NET 8 und SQL Server 2022 zu scstellen Konvention. < /p>
Was ich ausprobiert habe, ist: < /p>
- Erstellen Sie das minimale Datenbank -Setup im SQL -Server. zusammen mit einem leeren C# -Projekt mit den richtigen Nuget -Paketen
- DOTNE EF DBCONTEXT SCAFFOLD "
. Wenn ich dann weiterhin: < /p>
Code: Select all
using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; namespace MinimalReproduce.Scaffold; public partial class MinimalReproduceContext : DbContext { public MinimalReproduceContext() { } public MinimalReproduceContext(DbContextOptions options) : base(options) { } public virtual DbSet DependentTables { get; set; } public virtual DbSet PrincipalTables { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. => optionsBuilder.UseSqlServer(""); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.HasKey(e => e.DependentId); entity.ToTable("DependentTable"); entity.Property(e => e.DependentId).ValueGeneratedNever(); entity.HasOne(d => d.Alternate).WithMany(p => p.DependentTables) .HasPrincipalKey(p => p.AlternateId) .HasForeignKey(d => d.AlternateId) .OnDelete(DeleteBehavior.ClientSetNull) .HasConstraintName("FK_DependentTable_PrincipalTable"); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.PrimaryId); entity.ToTable("PrincipalTable"); entity.HasIndex(e => e.AlternateId, "AK_PrincipalTable_AlternateId").IsUnique(); entity.Property(e => e.PrimaryId).ValueGeneratedNever(); }); OnModelCreatingPartial(modelBuilder); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); } < /code> Ich hätte erwartet, dass EFCORE den alternativen Schlüssel erkennen würde, insbesondere weil der Schlüssel gemäß der hier gefundenen alternativen Schlüsselkonvention benannt ist. Ich würde erwarten, dass der generierte Kontext so etwas wie eine Entität () enthält. ) .IsUnique ()
Löschen Sie das vorhandene minimale Datenbank -Setup aus SQL Server < /li>Erstellen einer anfänglichen MigrationCode: Select all
dotnet ef migrations add Initial
- So bereitstellt die Datenbank
Code: Select all
dotnet ef database update
Code: Select all
Failed executing DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='0']
CREATE UNIQUE INDEX [AK_PrincipalTable_AlternateId] ON [PrincipalTable] ([AlternateId]);
Microsoft.Data.SqlClient.SqlException (0x80131904): The operation failed because an index or statistics with name 'AK_PrincipalTable_AlternateId' already exists on table 'PrincipalTable'.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) in /_/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 /_/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 /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs:line 1421
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) in /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs:line 2637
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite) in /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs:line 3502
at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName) in /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs:line 1667
at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery() in /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs:line 1213
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.Execute(IReadOnlyList`1 migrationCommands, IRelationalConnection connection, MigrationExecutionState executionState, Boolean beginTransaction, Boolean commitTransaction, Nullable`1 isolationLevel)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.c.b__3_1(DbContext _, ValueTuple`6 s)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IReadOnlyList`1 migrationCommands, IRelationalConnection connection, MigrationExecutionState executionState, Boolean commitTransaction, Nullable`1 isolationLevel)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateImplementation(DbContext context, String targetMigration, MigrationExecutionState state, Boolean useTransaction)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.c.b__20_1(DbContext c, ValueTuple`4 s)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
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.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:bdd08de7-8eb9-4603-bb01-6637b3998c78
Error Number:1913,State:1,Class:16
The operation failed because an index or statistics with name 'AK_PrincipalTable_AlternateId' already exists on table 'PrincipalTable'.