我的问题与 this SO post 有关,但我想了解创建索引的惯例是什么,而不是阻止,因为我找不到任何东西。
给定实体:
public class Entity1
{
public Guid Id {get;set;}
public string Name {get;set;}
public ICollection<Entity1Entity2Link> Links {get;set;}
}
public class Entity2
{
public Guid Id {get;set;}
public string Name {get;set;}
public ICollection<Entity1Entity2Link> Links {get;set;}
}
public class Entity1Entity2Link
{
public Guid Entity1Id {get;set;}
public Entity1 Entity1 {get;set;}
public Guid Entity2Id {get;set;}
public Entity2 Entity2 {get;set;}
}
以及多对多关系设置:
modelBuilder
.Entity<Entity1Entity2Link>()
.HasKey(ofl => new
{
ofl.Entity1Id ,
ofl.Entity2Id
});
modelBuilder
.Entity<Entity1Entity2Link>()
.HasOne(ofl => ofl.Entity1)
.WithMany(e => e.Links)
.HasForeignKey(ofl => ofl.Entity1Id);
modelBuilder
.Entity<Entity1Entity2Link>()
.HasOne(ofl => ofl.Entity2)
.WithMany(e => e.Links)
.HasForeignKey(ofl => ofl.Entity2Id);
由此产生的迁移在 Entity2Id 上有索引
// create table etc...
migrationBuilder.CreateIndex(
name: "IX_Entity1Entity2Link_Entity2Id",
table: "Entity1Entity2Link",
column: "Entity2Id");
我正在寻找创建此索引的惯例是什么?我能找到的一个约定是:
<块引用>EF Core 将始终为外键和备用键创建索引。
但是为什么我在 Entity1Id
列上没有看到另一个索引?
我还注意到我可以通过交换组合键定义中的列来交换在列上创建的索引,例如
modelBuilder
.Entity<Entity1Entity2Link>()
.HasKey(ofl => new
{
ofl.Entity2Id,
ofl.Entity1Id
});
这将在 Entity1Id
列上创建索引:
migrationBuilder.CreateIndex(
name: "IX_Entity1Entity2Link_Entity1Id",
table: "Entity1Entity2Link",
column: "Entity1Id");
我使用的是 EF Core 3.1.2。
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.2" />
答案 0 :(得分:3)
基本上就是你提到的
<块引用>按照惯例,在用作外键的每个属性(或一组属性)中创建索引。
有一个例外,部分包含在 Composite Index 部分的以下摘录中:
<块引用>多列上的索引,也称为复合索引,可以加快对索引列进行过滤的查询,也可以加快只对索引覆盖的第一列进行过滤的查询。
因此,按照惯例,所有 FK 都会自动创建索引,除非 FK 属性是某些其他复合索引中的前导列。由于复合索引的前导列提供与包含这些列的单独索引相同的高效搜索能力,因此单独索引是多余的,而 EF Core 足够聪明,不会创建它。
在您的示例中,已经存在与 PK (Entity1Id, Entity2Id)
列关联的复合索引,该列涵盖了 Entity1Id
FK,因此未创建其他索引。如果交换 PK 中的列,则 Entity2Id
将被覆盖,因此只会创建 Entity1Id
FK 的附加索引。