【发布时间】:2021-09-10 21:04:36
【问题描述】:
我正在使用 Npgsql 和 PostgreSQL 一起使用 EF Core,并且我已将依赖实体的外键(章节,见下文)设置为可为空的 int。当我删除主体实体(在本例中为 Book)时,我期待 CASCADE NULL 会发生。相反,在迁移中,行为是 ON DELETE RESTRICT。所以当我尝试删除它抛出的 Book 实体时
对表“Books”的更新或删除违反了对表“Chapters”的外键约束“FK_Chapters_Books_BookId”
默认情况下不应该是ON DELETE SET NULL吗?如何设置为 SET NULL?
包含您的代码
图书实体:
[Index(nameof(ISBN))]
public class Book
{
public int BookId { get; set; }
public string ISBN { get; set; }
public List<Chapter> Chapters { get; set; }
}
章节实体:
public class Chapter
{
public int ChapterId { get; set; }
public string Title { get; set; }
public int? BookId { get; set; } // <--- nullable
public Book Book { get; set; }
}
为章节实体生成的迁移:
migrationBuilder.CreateTable(
name: "Chapters",
columns: table => new
{
ChapterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Title = table.Column<string>(type: "text", nullable: true),
BookId = table.Column<int>(type: "integer", nullable: true),
},
constraints: table =>
{
table.PrimaryKey("PK_Chapters", x => x.ChapterId);
table.ForeignKey(
name: "FK_Chapters_Books_BookId",
column: x => x.BookId,
principalTable: "Books",
principalColumn: "BookId",
onDelete: ReferentialAction.Restrict); // <--- Why??????
});
正如您在上面看到的,onDelete: ReferentialAction.Restrict) 中有限制。为什么不默认SetNull?
包括堆栈跟踪
Message:
Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while updating the entries. See the inner exception for details.
---- Npgsql.PostgresException : 23503: update or delete on table "Books" violates foreign key constraint "FK_Chapters_Books_BookId" on table "Chapters"
Stack Trace:
ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
RelationalDatabase.SaveChanges(IList`1 entries)
StateManager.SaveChanges(IList`1 entriesToSave)
StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
NpgsqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
DbContext.SaveChanges()
BookServicesTests.RegisterNewBook_CanSuccessfullySaveToDatabase() line 63
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
NpgsqlConnector.<ReadMessage>g__ReadMessageLong|194_0(NpgsqlConnector connector, Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
NpgsqlDataReader.NextResult()
NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
NpgsqlCommand.ExecuteReader(CommandBehavior behavior)
NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
DbCommand.ExecuteReader()
RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
包括提供者和版本信息
- EF Core 版本:5.0.4
- 数据库提供者:Npgsql.EntityFrameworkCore.PostgreSQL
- 目标框架:.NET 5.0
- 操作系统:Windows 10
- IDE:Visual Studio 2019 16.10)
【问题讨论】:
标签: c# postgresql entity-framework-core npgsql