在表上插入或更新违反了实体框架中的外键约束

问题描述 投票:0回答:1

Configurations
表具有主键
Id
和引用
CurrentVersionId
表中的
Id
列的外键
ConfigurationVersions
ConfigurationVersions
表具有主键
Id
和引用
ConfigurationId
表中的
Id
列的外键
Configurations

基本上,主要任务是如果表相互引用,如何播种数据。

我有两种例外情况。第一个涉及到

FK_Configurations_ConfigurationVersions_CurrentVersionId
如果我在
_context.SaveChanges
之后调用
DeviceConfiguration
,另一个是在创建版本之后添加之后的
FK_Configurations_ConfigurationVersions_configurationId

异常数据:
严重性:错误
sql状态:23503
MessageText:表“ConfigurationVersions”的插入或更新违反了外键约束“FK_ConfigurationVersions_Configurations_ConfigurationId”
详细信息:详细信息已被编辑,因为它可能包含敏感数据。在连接字符串中指定“包含错误详细信息”以包含此信息。
模式名称:public
表名称:配置版本
约束名称:FK_ConfigurationVersions_Configurations_ConfigurationId*

代码:

[Table("Configurations")]
public class DeviceConfiguration
{
    public int Id { get; set; }
    public int CurrentVersionId { get; set; }
}

[Table("ConfigurationVersions")]
public class DeviceConfigurationVersion
{
    public int Id { get; set; }
    public int ConfigurationId { get; set; }
}

这是我创建这些表的迁移

public partial class Initial : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterDatabase()
                        .Annotation("Npgsql:Enum:device_configuration_source", "Versioned,Duplicated,RollBacked,Imported")
                        .Annotation("Npgsql:Enum:device_configuration_state", "Published,Draft,Unsaved")
                        .Annotation("Npgsql:Enum:device_configuration_type", "Factory,Custom");

        migrationBuilder.CreateTable(
                name: "Configurations",
                columns: table => new
                {
                    Id = table.Column<int>(type: "integer", nullable: false)
                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
                    CurrentVersionId = table.Column<int>(type: "integer", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Configurations", x => x.Id);
                });

        migrationBuilder.CreateTable(
                name: "ConfigurationVersions",
                columns: table => new
                {
                    Id = table.Column<int>(type: "integer", nullable: false)
                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
                    ConfigurationId = table.Column<int>(type: "integer", nullable: false),
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_ConfigurationVersions", x => x.Id);
                    table.ForeignKey(
                        name: "FK_ConfigurationVersions_Configurations_ConfigurationId",
                        column: x => x.ConfigurationId,
                        principalTable: "Configurations",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });
            
     migrationBuilder.AddForeignKey(
                name: "FK_Configurations_ConfigurationVersions_CurrentVersionId",
                table: "Configurations",
                column: "CurrentVersionId",
                principalTable: "ConfigurationVersions",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropTable(name: "ConfigurationVersions");
    migrationBuilder.DropTable(name: "Configurations");
}

数据播种器

public class DataSeeder
{
    private readonly ApplicationDbContext _context;

    public DataSeeder(ApplicationDbContext context)
    {
        _context = context;
    }

    public void SeedData()
    {
        if (_context.Configurations != null && _context.Configurations.Any())
        {
            return;
        }

        for (int i = 1; i <= 100; i++)
        {
            DeviceConfiguration configuration = new()
                  {
                      CurrentVersionId = i
                  };
            _context.Configurations?.Add(configuration);

            DeviceConfigurationVersion version = new()
                  {
                      ConfigurationId = configuration.Id
                  };
            _context.ConfigurationVersions?.Add(version);

            _context.SaveChanges();

            configuration.CurrentVersionId = version.Id;
            _context.SaveChanges();
        }
    }
}
c# .net entity-framework entity-framework-core migration
1个回答
0
投票

您没有设置

Id
的显式值,因此
configuration.Id
等于
0

DeviceConfiguration configuration = new()
{
    CurrentVersionId = i
};

在这里,您只需将

0
分配给
version.configuration.Id

DeviceConfigurationVersion version = new()
{
    ConfigurationId = configuration.Id
};

仅在此行之后,查询才会发送到 SQL,该 SQL 创建一行并生成

Id
的实际值。

_context.SaveChanges();

所以你有两个选择

  1. 将其分为两个调用:
DeviceConfiguration configuration = new()
{
    CurrentVersionId = i
};

_context.SaveChanges();

DeviceConfigurationVersion version = new()
{
    ConfigurationId = configuration.Id
};

_context.SaveChanges();
  1. 只需让 EF 关心
    Id
    ,并操作对象即可。
[Table("Configurations")]
public class DeviceConfiguration
{
    public int Id { get; set; }
    public DeviceConfigurationVersion CurrentVersion { get; set; }
}

[Table("ConfigurationVersions")]
public class DeviceConfigurationVersion
{
    public int Id { get; set; }
    public DeviceConfiguration Configuration { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.