如何首先使用代码在Entity Framework 6.2中创建索引


112

有没有一种方法可以使用代码优先而不是使用新代码在属性/列上创建索引IndexAttribute


5
索引是数据库概念,而不是实体模型概念。即使您可以使用属性或通过流畅的API指定索引,它实际上也不会在您的应用程序中做任何事情。这只是EF创建数据库时使用的说明。我相信这样的指令属于代码优先迁移,这完全与操纵数据库模式有关。
JC福特

Answers:


84

2017年10月26日,Entity Framework 6.2 正式发布。它包括通过Fluent API轻松定义索引的可能性。何其使用已在6.2 beta中宣布

现在,您可以使用该HasIndex()方法,然后IsUnique()使用它是否应该是唯一索引。

只是一个小的比较(之前/之后)示例:

// before 
modelBuilder.Entity<Person>()
        .Property(e => e.Name)
        .HasColumnAnnotation(
            IndexAnnotation.AnnotationName, 
            new IndexAnnotation(new IndexAttribute { IsUnique = true }));

// after
modelBuilder.Entity<Person>()
    .HasIndex(p => p.Name)
    .IsUnique();

// multi column index
modelBuilder.Entity<Person>()
    .HasIndex(p => new { p.Name, p.Firstname })
    .IsUnique();

也可以将索引标记为.IsClustered()


编辑#1

添加了多列索引的示例,以及有关如何将索引标记为群集的其他信息。


编辑#2

作为附加信息,在EF Core 2.1中,它与现在在EF 6.2中完全相同。
是MS Doc articile作为参考。


这很棒!我想如果我有多列索引,它将类似于:.HasIndex(p => new {p.Name,p.Xyz})
Valo

哦,对不起,确定。应该是new。我会修好它。
ChW

您能否说明我们如何在Core 2.x中编写相同的代码?
user3417479 '18

据我所知,它应该与“之后”和“多列索引”下显示的代码相同。
ChW 18/12/5

87

当前,没有通过Fluent API创建索引的“一流支持”,但是您可以通过Fluent API进行操作,您可以将属性标记为具有Annotation API中的属性。这将允许您Index通过流畅的界面添加属性。

以下是EF发行站点上工作项中的一些示例。

在单列上创建索引:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new IndexAttribute()));

单个列上有多个索引:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new[]
            {
                new IndexAttribute("Index1"),
                new IndexAttribute("Index2") { IsUnique = true }
            }));

多列索引:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty1)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(new IndexAttribute("MyIndex", 1)));

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty2)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new IndexAttribute("MyIndex", 2)));

使用以上技术将导致.CreateIndex()在您为Up()下一个迁移进行脚手架时为您的函数自动创建调用(或者,如果您不使用迁移,则在数据库中自动创建调用)。


4
可能会在列上添加索引,但不会删除在主键上创建的聚集索引。hasKey在默认情况下不会删除的主键上创建聚簇索引。必须从在.Primarykey(x=>x.id,clustered:false)方法中声明clusered:false所创建的迁移文件中明确删除该文件
乔伊

8
我尝试了这种HasAnnotation方法,没有这样的方法。但是我找到了一个名称HasColumnAnnotation可以接受您提供的参数的方法。您需要更新答案还是我错了?
2015年

@HakamFostok我直接从EF网站获取了示例。可能是其中一个版本的名称更改了,或者原始版本中有错字。
Scott Chamberlain

3
请从今年早些时候的设计会议的以下链接的底部开始右键单击:“将HasAnnotation重命名为HasColumnAnnotation(以及代码库中的其他相关位置)。”。 Entityframework.codeplex.com/…–
扎克·查尔斯

36

我创建了一些扩展方法,并将它们包装在nuget包中,以使其变得更加容易。

安装EntityFramework.IndexingExtensionsnuget软件包。

然后,您可以执行以下操作:

public class MyDataContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<Customer>()
        .HasIndex("IX_Customers_Name",          // Provide the index name.
            e => e.Property(x => x.LastName),   // Specify at least one column.
            e => e.Property(x => x.FirstName))  // Multiple columns as desired.

        .HasIndex("IX_Customers_EmailAddress",  // Supports fluent chaining for more indexes.
            IndexOptions.Unique,                // Supports flags for unique and clustered.
            e => e.Property(x => x.EmailAddress)); 
  }
}

项目和源代码在这里。请享用!


我真的很喜欢这个软件包,但是在up脚本中脚手架之后,索引名称有时会丢失。它仅在索引中使用4个或更多属性时才出现。我正在使用EF 6.1.3。
Mixxiphoid 2015年

@Mixxiphoid-您能否在此处记录问题以及支持的详细信息?另外,请确保您具有版本1.0.1,因为1.0.0中存在错误
马特·约翰逊·品脱

我确实有版本1.0.1。我将记录该问题,但目前无法这样做。
Mixxiphoid 2015年

如何将索引参与列顺序添加到降序?默认情况下,HasIndex(“ IX_Customers_EmailAddress”,IndexOptions.Unique,...为索引中的所有参与列创建升序
。– GDroid

@GDroid-不幸的是,这不是EF的IndexAttribute课程所公开的,因此我无法将其包含在我的图书馆中。
马特·约翰逊·品脱

24

没有明确的名称:

[Index]
public int Rating { get; set; } 

使用特定名称:

[Index("PostRatingIndex")] 
public int Rating { get; set; }

指数似乎被
贬低了

1
@HamedZakeryMiab您正在使用哪个版本的Entity Framework?索引未弃用。
HugoHilário16年

对不起,我忘了包括在内EntityFramework。它包含在该程序集中。只是对NS感到困惑。
Hamed Zakery Miab

@HamedZakeryMiab是的,这真让人困惑!我以为它是System.DataAnnotations的一部分!绝对是实体框架软件包
AlbatrossCafe

3
该问题包含以下声明instead of using the new IndexAttribute,您注意到了吗?
哈坎·菲斯特克(HakanFıstık),

22

从EF 6.1开始,[Index]支持该属性。
使用[Index(IsUnique = true)]的唯一索引。
这是微软链接

public class User 
{ 
    public int UserId { get; set; } 

    [Index(IsUnique = true)] 
    [StringLength(200)] 
    public string Username { get; set; } 

    public string DisplayName { get; set; } 
}

2
尽管从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。
Enamul Hassan'5

@manetsus很好。我添加了一个代码段以反映更改。
达里·多卢斯

3
字符串长度是必需的,否则您会看到“类型无效,不能用作索引中的键列”的异常。我的同事喜欢在Conntext上使用modelBuilder解决方案,这样您就不会弄乱您的User类,我认为这是有效的。
安德鲁·帕特

有多个具有唯一性的列的索引呢?具有多列唯一键索引非常常见……
enorl76,19年

1
@ enorl76也受支持。对于每一列,您都需要使用如下所示的属性, [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } 此处来自Microsoft
Darie Dorlus,

8

实体框架6

Property(c => c.MyColumn)
        .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_MyIndex")));

并使用添加:

using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;


2

如果您不想在POCO上使用属性,则可以始终按照以下方式进行操作:

context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ..."); 

您可以在自定义DbInitializer派生类中执行此语句。我不知道这样做的任何Fluent API方法。


1
当然,默特。目前,我正在使用迁移,您还可以在Up()方法中放置:CreateIndex(“ dbo.Table1”,“ Column1”,true,“ Column1_IX”)和Down()DropIndex((“ dbo.Table1 “,” Column1_IX“)。我只是希望他们也能添加流利的API ...
Valo 2014年

1

我编写了一种扩展方法以在流利的EF中使用,以避免额外的代码:

public static PrimitivePropertyConfiguration HasIndexAnnotation(
    this PrimitivePropertyConfiguration primitivePropertyConfiguration, 
    IndexAttribute indexAttribute = null
    )
{
    indexAttribute = indexAttribute ?? new IndexAttribute();

    return primitivePropertyConfiguration
        .HasColumnAnnotation(
            IndexAnnotation.AnnotationName, 
            new IndexAnnotation(indexAttribute)
        );
}

然后像这样使用它:

Property(t => t.CardNo)
    .HasIndexAnnotation();

如果索引需要一些配置,则可以这样:

Property(t => t.CardNo)
    .HasIndexAnnotation(new IndexAttribute("IX_Account") { IsUnique = true });

1

您可以使用其中之一

//索引

 this.HasIndex(e => e.IsActive)
            .HasName("IX_IsActive");

要么

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.