【问题标题】:How to create a Clustered Index with Entity Framework Core如何使用 Entity Framework Core 创建聚集索引
【发布时间】:2016-12-21 00:17:41
【问题描述】:

从 EF6.1 开始,我们有一种方法可以在属性上指定聚集索引

public class Person 
{
  [Index(IsClustered = true, IsUnique = true)]
  public long UserName { get; set; }
}

但是这个 Index 属性现在似乎不在 EF Core 中?在 EF Core 中如何实现这一点?

【问题讨论】:

标签: entity-framework entity-framework-core clustered-index


【解决方案1】:

来自当前的 EF Core 文档 - Indexes 部分:

数据注释

不能使用数据注释创建索引。

但您可以肯定地通过 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 开始,索引文档链接中现在提到了 Index 数据注释,但它不能用于指定数据库特定属性,如集群(SqlServer 特定),所以原来的答案仍然适用。

【讨论】:

  • .ForSqlServerIsClustered(); 有 MySql 特定版本吗?
  • @Zze 由于每个提供者都添加了自己的扩展方法并且当前有several MySql providers for EF Core,因此您应该检查您正在使用的那个。我会检查以ForMySql 开头的扩展方法。
  • 我明白了......无法在表 'FooDto' 上创建多个聚集索引。在创建另一个聚集索引之前删除现有的聚集索引“PK_FooDto”,因为我的 FooDto 中有一个 Id 字段。有没有办法解决这个问题?
  • 修复了我的实体在其 Id 字段上自动聚类,直到我添加 modelBuilder.Entity().HasKey(e => e.Id).ForSqlServerIsClustered(clustered: false);跨度>
  • 我收到类似这样的错误“IndexBuilder”不包含“ForSqlServerIsClustered”的定义,并且没有可访问的扩展方法“ForSqlServerIsClustered”接受“IndexBuilder”类型的第一个参数可能是找到了吗?
【解决方案2】:

对于 EF Core 3.0+,您现在可以使用 IsClustered:

modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();

.ForSqlServerIsClustered() 现在被标记为过时。

另外请注意,如果您的表上有主键,您可能还需要在添加用户名上的集群之前显式删除其上的集群:

modelBuilder.Entity<Person>()
.HasKey(e => e.PersonId)
.IsClustered(false);

modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();

【讨论】:

  • 感谢为我节省了时间并分享了 .ForSqlServerIsClustered() 的替代方案,因为在 Microsoft 的网站上它已过时,但是,它们没有包含应该使用的信息。
  • 我收到类似这样的错误“IndexBuilder”不包含“IsClustered”的定义,并且没有可访问的扩展方法“IsClustered”接受“IndexBuilder”类型的第一个参数成立?使用 EF Core 5.0.3
  • @KarthicG IsClustered 在 EF Core 5 中仍然可用。检查您的 using 语句没有冲突,并且您引入了正确的语句:docs.microsoft.com/en-us/dotnet/api/…
  • 澄清一下,需要的nuget是Microsoft.EntityFrameworkCore.SqlServer
【解决方案3】:

在没有内置支持的情况下,您可以使用自己的自定义属性来注释模型属性并在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;
            }
        }
    }
}

带有简单的标记属性类:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IndexAttribute : Attribute
{
    public bool IsUnique { get; set; } 
    public bool IsClustered { get; set; } 
}

然后在你的模型类中,添加创建二级索引的属性即可:

public class User
{
    public int UserId { get; set; }
    [Index(IsUnique = true, IsClustered = true)]
    public string Nickname { get; set; }
}

【讨论】:

    【解决方案4】:

    或者这也可以,比如如果你想按年龄分组......

                modelBuilder
                .Entity<Person>()
                .Property(t => t.Age)
                .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsClustered = true}));
    

    【讨论】:

    猜你喜欢
    • 2017-04-21
    • 2021-06-16
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    相关资源
    最近更新 更多