使用流利 API 的 EF Core 3 聚簇索引不起作用
EF Core 3 Clustered indexing using fluent API not working
我有一个 .Net 核心 3.1 API,启用了 EF 核心代码优先迁移,我试图在非 PK 列上添加聚集索引。
我有一个车辆实体:
public class Vehicle
{
// PK and has clustered index by default
[Key]
public int Id { get; set; }
// FK and needs to be clustered
public long CompanyId { get; set; }
[ForeignKey(nameof(CompanyId))]
public virtual Company Company { get; set; }
}
我为上述模型创建了代码优先迁移,然后更新了数据库。
此时 table 的 PK 为 Id
和聚簇索引,CompanyId
与 FK 一样。
要从 Id
中删除聚簇索引并在 CompanyId
上添加聚簇索引,我在 OnModelCreating()
方法
中用 Fluent API 编写了以下内容
// Remove ClusteredIndex from PK
modelBuilder.Entity<Vehicle>().HasIndex(m => m.Id).IsUnique(true).IsClustered(false);
// Add clustered index on CompanyId
modelBuilder.Entity<Vehicle>().HasIndex(m => m.CompanyId).IsUnique(false).IsClustered(true);
当我 运行 API 时,我可以看到上面的代码确实执行了,但它对 SQL 数据库没有影响,也没有根据需要更改索引。
我在这里错过了什么?如何在 CompanyId
列上添加聚簇索引?
在迁移中使用旧的 SQL 来解决这个问题。
首先为MigrationBuilder
创建了一个扩展方法:
public static void CreateNonPKClusteredIndex(this MigrationBuilder migrationBuilder,
string tableNameWithSchema,
string pkConstraintName, string pkColumnName,
string nonClusteredIndexName, string clusteredColumnName)
{
// Change PK clustered index to non clustered
migrationBuilder.Sql($"ALTER TABLE {tableNameWithSchema} DROP CONSTRAINT {pkConstraintName}");
migrationBuilder.Sql($"ALTER TABLE {tableNameWithSchema} ADD CONSTRAINT {pkConstraintName} PRIMARY KEY NONCLUSTERED({pkColumnName})");
// Update CompanyId index to clustered index
migrationBuilder.Sql($"Drop Index {nonClusteredIndexName} on {tableNameWithSchema}");
migrationBuilder.Sql($"CREATE CLUSTERED INDEX[{nonClusteredIndexName}] ON {tableNameWithSchema}({clusteredColumnName} ASC)");
}
然后在相应的迁移中的 Up()
中简单地调用它:
migrationBuilder.CreateNonPKClusteredIndex("Core.Vehicles",
"PK_Vehicles", "Id",
"IX_Vehicles_CompanyId", "CompanyId");
结果:
我有一个 .Net 核心 3.1 API,启用了 EF 核心代码优先迁移,我试图在非 PK 列上添加聚集索引。
我有一个车辆实体:
public class Vehicle
{
// PK and has clustered index by default
[Key]
public int Id { get; set; }
// FK and needs to be clustered
public long CompanyId { get; set; }
[ForeignKey(nameof(CompanyId))]
public virtual Company Company { get; set; }
}
我为上述模型创建了代码优先迁移,然后更新了数据库。
此时 table 的 PK 为 Id
和聚簇索引,CompanyId
与 FK 一样。
要从 Id
中删除聚簇索引并在 CompanyId
上添加聚簇索引,我在 OnModelCreating()
方法
// Remove ClusteredIndex from PK
modelBuilder.Entity<Vehicle>().HasIndex(m => m.Id).IsUnique(true).IsClustered(false);
// Add clustered index on CompanyId
modelBuilder.Entity<Vehicle>().HasIndex(m => m.CompanyId).IsUnique(false).IsClustered(true);
当我 运行 API 时,我可以看到上面的代码确实执行了,但它对 SQL 数据库没有影响,也没有根据需要更改索引。
我在这里错过了什么?如何在 CompanyId
列上添加聚簇索引?
在迁移中使用旧的 SQL 来解决这个问题。
首先为MigrationBuilder
创建了一个扩展方法:
public static void CreateNonPKClusteredIndex(this MigrationBuilder migrationBuilder,
string tableNameWithSchema,
string pkConstraintName, string pkColumnName,
string nonClusteredIndexName, string clusteredColumnName)
{
// Change PK clustered index to non clustered
migrationBuilder.Sql($"ALTER TABLE {tableNameWithSchema} DROP CONSTRAINT {pkConstraintName}");
migrationBuilder.Sql($"ALTER TABLE {tableNameWithSchema} ADD CONSTRAINT {pkConstraintName} PRIMARY KEY NONCLUSTERED({pkColumnName})");
// Update CompanyId index to clustered index
migrationBuilder.Sql($"Drop Index {nonClusteredIndexName} on {tableNameWithSchema}");
migrationBuilder.Sql($"CREATE CLUSTERED INDEX[{nonClusteredIndexName}] ON {tableNameWithSchema}({clusteredColumnName} ASC)");
}
然后在相应的迁移中的 Up()
中简单地调用它:
migrationBuilder.CreateNonPKClusteredIndex("Core.Vehicles",
"PK_Vehicles", "Id",
"IX_Vehicles_CompanyId", "CompanyId");
结果: