如何使用 Entity Framework 核心创建聚簇索引
How to create a Clustered Index with Entity Framework Core
从 EF6.1 开始,我们有一种在 属性
上指定聚簇索引的方法
public class Person
{
[Index(IsClustered = true, IsUnique = true)]
public long UserName { get; set; }
}
但是这个 Index 属性现在似乎不在 EF Core 中?在 EF Core 中,您如何实现这一点?
来自当前的 EF Core 文档 - Indexes 部分:
Data Annotations
Indexes can not be created using data annotations.
但是您可以肯定地通过 Fluent API 指定它(请注意具有 ForSqlServer
前缀的扩展方法似乎表示 SqlServer 特定功能):
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.ForSqlServerIsClustered();
更新: 对于 EF Core 3.0+,该方法仅被调用 IsClustered
:
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
更新: 从 EF Core 5.0 开始,Indexes 文档 link 中现在提到了 Index 数据注释,但不能用于指定数据库特定属性,如集群(特定于 SqlServer),因此原始答案仍然适用。
在没有内置支持的情况下,您可以使用自己的自定义属性来注释模型属性并在OnModelCreating()
中应用:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo.GetCustomAttribute<IndexAttribute>();
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = attr.IsUnique;
index.SqlServer().IsClustered = attr.IsClustered;
}
}
}
}
使用简单的标记属性class:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IndexAttribute : Attribute
{
public bool IsUnique { get; set; }
public bool IsClustered { get; set; }
}
然后在你的模型中class,只需添加创建二级索引的属性:
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true, IsClustered = true)]
public string Nickname { get; set; }
}
或者这也行,比如你想按年龄聚类...
modelBuilder
.Entity<Person>()
.Property(t => t.Age)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsClustered = true}));
对于 EF Core 3.0+ 您现在可以使用 IsClustered:
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
.ForSqlServerIsClustered() 现已标记为过时。
另请注意,如果您在 table 上有一个主键,您可能还需要在为您的用户名添加集群之前明确删除其上的集群:
modelBuilder.Entity<Person>()
.HasKey(e => e.PersonId)
.IsClustered(false);
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
从 EF6.1 开始,我们有一种在 属性
上指定聚簇索引的方法public class Person
{
[Index(IsClustered = true, IsUnique = true)]
public long UserName { get; set; }
}
但是这个 Index 属性现在似乎不在 EF Core 中?在 EF Core 中,您如何实现这一点?
来自当前的 EF Core 文档 - Indexes 部分:
Data Annotations
Indexes can not be created using data annotations.
但是您可以肯定地通过 Fluent API 指定它(请注意具有 ForSqlServer
前缀的扩展方法似乎表示 SqlServer 特定功能):
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.ForSqlServerIsClustered();
更新: 对于 EF Core 3.0+,该方法仅被调用 IsClustered
:
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
更新: 从 EF Core 5.0 开始,Indexes 文档 link 中现在提到了 Index 数据注释,但不能用于指定数据库特定属性,如集群(特定于 SqlServer),因此原始答案仍然适用。
在没有内置支持的情况下,您可以使用自己的自定义属性来注释模型属性并在OnModelCreating()
中应用:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo.GetCustomAttribute<IndexAttribute>();
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = attr.IsUnique;
index.SqlServer().IsClustered = attr.IsClustered;
}
}
}
}
使用简单的标记属性class:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IndexAttribute : Attribute
{
public bool IsUnique { get; set; }
public bool IsClustered { get; set; }
}
然后在你的模型中class,只需添加创建二级索引的属性:
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true, IsClustered = true)]
public string Nickname { get; set; }
}
或者这也行,比如你想按年龄聚类...
modelBuilder
.Entity<Person>()
.Property(t => t.Age)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsClustered = true}));
对于 EF Core 3.0+ 您现在可以使用 IsClustered:
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
.ForSqlServerIsClustered() 现已标记为过时。
另请注意,如果您在 table 上有一个主键,您可能还需要在为您的用户名添加集群之前明确删除其上的集群:
modelBuilder.Entity<Person>()
.HasKey(e => e.PersonId)
.IsClustered(false);
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();