我有一个 postgres 数据库,我首先使用 ef 来控制我的迁移代码。
我目前有这张桌子/班级。
public class Notification
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
public string ActionType { get; set; } = string.Empty;
public string ActionElement { get; set; } = string.Empty;
public string ActionElementType { get; set; } = string.Empty;
public string Message { get; set; } = string.Empty;
public User ForUser { get; set; } = new User();
public User ByUser { get; set; } = new User();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public bool Seen { get; set; } = false;
public bool Clicked { get; set; } = false;
}
to this
public class Notification
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
public string ActionType { get; set; } = string.Empty;
public string ActionElement { get; set; } = string.Empty;
public string ActionElementType { get; set; } = string.Empty;
//public string Message { get; set; } = string.Empty;
public Message MessageContent { get; set; };
public User ForUser { get; set; } = new User();
public User ByUser { get; set; } = new User();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public bool Seen { get; set; } = false;
public bool Clicked { get; set; } = false;
}
public record Message
{
[Key]
public Guid MessageId { get; set; } = Guid.NewGuid();
public string MessageContent { get; init; }
public ImmutableDictionary<string, string> MessageContentProperties { get; init; }
}
创建了此迁移文件:
/// 公共部分类changeMessageStringToMessageRecord:迁移 { /// protected override void Up(MigrationBuilder migrationBuilder) { 迁移Builder.DropColumn( 名称:“消息”, 表:“通知”);
migrationBuilder.AlterDatabase()
.Annotation("Npgsql:PostgresExtension:hstore", ",,")
.Annotation("Npgsql:PostgresExtension:uuid-ossp", ",,")
.OldAnnotation("Npgsql:PostgresExtension:uuid-ossp", ",,");
migrationBuilder.AddColumn<Guid>(
name: "MessageContentMessageId",
table: "Notifications",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateTable(
name: "Message",
columns: table => new
{
MessageId = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"),
MessageContent = table.Column<string>(type: "text", nullable: false),
MessageContentProperties = table.Column<ImmutableDictionary<string, string>>(type: "hstore", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Message", x => x.MessageId);
});
migrationBuilder.CreateIndex(
name: "IX_Notifications_MessageContentMessageId",
table: "Notifications",
column: "MessageContentMessageId");
migrationBuilder.AddForeignKey(
name: "FK_Notifications_Message_MessageContentMessageId",
table: "Notifications",
column: "MessageContentMessageId",
principalTable: "Message",
principalColumn: "MessageId",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Notifications_Message_MessageContentMessageId",
table: "Notifications");
migrationBuilder.DropTable(
name: "Message");
migrationBuilder.DropIndex(
name: "IX_Notifications_MessageContentMessageId",
table: "Notifications");
migrationBuilder.DropColumn(
name: "MessageContentMessageId",
table: "Notifications");
migrationBuilder.AlterDatabase()
.Annotation("Npgsql:PostgresExtension:uuid-ossp", ",,")
.OldAnnotation("Npgsql:PostgresExtension:hstore", ",,")
.OldAnnotation("Npgsql:PostgresExtension:uuid-ossp", ",,");
migrationBuilder.AddColumn<string>(
name: "Message",
table: "Notifications",
type: "text",
nullable: false,
defaultValue: "");
}
}
当我应用迁移时,我收到错误消息
ALTER TABLE "Notifications" ADD CONSTRAINT "FK_Notifications_Message_MessageContentMessageId" FOREIGN KEY ("MessageContentMessageId") REFERENCES "Message" ("MessageId") ON DELETE CASCADE;
Npgsql.PostgresException (0x80004005): 23503: insert or update on table "Notifications" violates foreign key constraint "FK_Notifications_Message_MessageContentMessageId"
我不确定我是否理解这里的问题?为什么这里有外键问题?
您的通知表可能有一个
MessageContentMessageId
,但它未映射到 MessageId
列中具有相同 Message
的行。
如果您想要外键,则需要清理数据。
例如,在迁移中,您可以包含一条更新语句来删除所有无法找到的内容,方法是添加一条 SQL 语句将无法找到的消息的
MessageContentMessageId
设置为 NULL
您可以将其包装在
migrationBuilder.Sql
函数中
UPDATE Notifications
SET MessageContentMessageId = NULL
FROM Notifications AS n
LEFT JOIN Messages AS m on m.MessageId = n.MessageContentMessageId
WHERE m.MessageId IS NULL