EF Core 迁移从新的复合索引中删除第一个外键索引
EF Core migrations drops first foreign key index from a new composite index
这是我的模型:
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 上唯一提到这个问题有点过时 post:
EF Migrations drops index when adding compsite index
P.S。使用 SQL 服务器作为数据库提供程序在 3.1.8 上测试。
应该更深入地研究这个问题。
创建复合索引时,它的第一列可以在查询中单独使用。
https://github.com/dotnet/efcore/issues/22513
这是我的模型:
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 上唯一提到这个问题有点过时 post: EF Migrations drops index when adding compsite index
P.S。使用 SQL 服务器作为数据库提供程序在 3.1.8 上测试。
应该更深入地研究这个问题。 创建复合索引时,它的第一列可以在查询中单独使用。 https://github.com/dotnet/efcore/issues/22513