c# - EF Core 迁移从新的复合索引中删除第一个外键索引

标签 c# entity-framework-core foreign-keys relational-database entity-framework-migrations

这是我的模型:

public class Period
{
    [Key]
    public int Id { get; set; }
}

public class Company
{
    [Key]
    public int Id { get; set; }
}

public class Invoice
{
    [Key]
    public int Id { get; set; }

    public int PeriodId { get; set; }
    public Period Period { get; set; }

    public int CompanyId { get; set; }
    public Company Company { get; set; }
}

没什么好看的。一张简单的发票,其中包含一个时间段和一个公司。

这是它们的配置方式:

modelBuilder.Entity<Invoice>()
    .HasOne(p => p.Period)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict)
;

modelBuilder.Entity<Invoice>()
    .HasOne(p => p.Company)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict)
;

这是由此生成的迁移文件:

migrationBuilder.CreateTable(
    name: "Companies",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:Identity", "1, 1")
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Companies", x => x.Id);
    });

migrationBuilder.CreateTable(
    name: "Periods",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:Identity", "1, 1")
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Periods", x => x.Id);
    });

migrationBuilder.CreateTable(
    name: "Invoices",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:Identity", "1, 1"),
        PeriodId = table.Column<int>(nullable: false),
        CompanyId = table.Column<int>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Invoices", x => x.Id);
        table.ForeignKey(
            name: "FK_Invoices_Companies_CompanyId",
            column: x => x.CompanyId,
            principalTable: "Companies",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        table.ForeignKey(
            name: "FK_Invoices_Periods_PeriodId",
            column: x => x.PeriodId,
            principalTable: "Periods",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    });

migrationBuilder.CreateIndex(
    name: "IX_Invoices_CompanyId",
    table: "Invoices",
    column: "CompanyId");

migrationBuilder.CreateIndex(
    name: "IX_Invoices_PeriodId",
    table: "Invoices",
    column: "PeriodId");

一切似乎都是合法的。现在我需要创建一个唯一索引来控制一段时间内公司发票的唯一性:

modelBuilder.Entity<Invoice>()
    .HasIndex(p => new
    {
        p.PeriodId,
        p.CompanyId,
    })
    .IsUnique()
;

这就是迁移现在的样子:

migrationBuilder.DropIndex(
    name: "IX_Invoices_PeriodId",
    table: "Invoices");

migrationBuilder.CreateIndex(
    name: "IX_Invoices_PeriodId_CompanyId",
    table: "Invoices",
    columns: new[] { "PeriodId", "CompanyId" },
    unique: true);

注意“DropIndex”。它从我的复合索引中获取第一列。如果我更改顺序,它仍然会丢弃第一个:

modelBuilder.Entity<Invoice>()
    .HasIndex(p => new
    {
        p.CompanyId,
        p.PeriodId,
    })
    .IsUnique()
;

migrationBuilder.DropIndex(
    name: "IX_Invoices_CompanyId",
    table: "Invoices");

migrationBuilder.CreateIndex(
    name: "IX_Invoices_CompanyId_PeriodId",
    table: "Invoices",
    columns: new[] { "CompanyId", "PeriodId" },
    unique: true);

我不确定我是否理解这背后的逻辑。复合索引中有什么特殊之处使单独的索引无用吗?或者它可能是某种错误?

我发现唯一提到这个问题的是关于 SO 的有点过时的帖子: EF Migrations drops index when adding compsite index

附言使用 SQL Server 作为数据库提供程序在 3.1.8 上测试。

最佳答案

应该更彻底地研究这个问题。 创建复合索引时,它的第一列可以在查询中单独使用。 https://github.com/dotnet/efcore/issues/22513

关于c# - EF Core 迁移从新的复合索引中删除第一个外键索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63843744/

相关文章:

c# - 需要使用 Javascript 打开一个新窗口并传递存储在 C# 中的字符串变量中的查询字符串

c# - 对具有指向其他类的指针的类进行子类化

c# - 从类型中获取 DbSet

mysql - 外部约束键失败

database - 更改 Oracle 中的主键值

c# - 尝试使用通用对象序列化新的 XML 文件

c# - 为什么将空检查后将int设置为0认为没有意义?

c# - EF Core 3 未加载第二层或更深层的相关数据

c# - 使用 AutoMapper 添加、更新和删除列表中的项目

mysql - 我应该索引外键吗?我应该使用该表的主键吗?