Entity Framework 6.2で最初にコードを使用してインデックスを作成する方法


112

新しいを使用する代わりに、コードファーストを使用してプロパティ/列にインデックスを作成する方法はありIndexAttributeますか?


5
インデックスはデータベースの概念であり、エンティティモデルの概念ではありません。属性またはFluent APIを使用してインデックスを指定できたとしても、実際にはアプリケーションで何も実行されません。これは、データベースを作成するときにEFが使用する指示にすぎません。このような指示は、データベーススキーマの操作に完全に関係するコードファーストの移行に属していると思います。
JCフォード

回答:


84

さて、26.10.2017 Entity Framework 6.2が正式にリリースされました。これは、可能性が流暢APIを介して簡単にインデックスを定義するために。使うほうは6.2のベータで既に発表されていました。

これでメソッドを使用できるようになり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の記事です。


これは素晴らしい!複数列のインデックスがある場合、次のようになると思います:.HasIndex(p => new {p.Name、p.Xyz})
Valo

ああ、ごめんなさい。それはあるはずですnew。私はそれを修正します。
ChW 2017年

Core 2.xで同じコードをどのように書くことができるかを示していただけますか?
user3417479 2018

私の知る限り、「後」と「マルチカラムインデックス」で示したのと同じコードにする必要があります。
ChW

87

現在、Fluent APIを介してインデックスを作成するための「ファーストクラスサポート」はありませんが、Fluent APIを介してできることは、プロパティをAnnotation APIからの属性を持つものとしてマークすることです。これIndexにより、流れるようなインターフェイスを介して属性を追加できます。

EFの問題サイトのワークアイテムの例をいくつか示します。

単一の列にインデックスを作成します。

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

1つの列に複数のインデックス:

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を指定して作成された移行ファイルから明示的に削除する必要があります
Joy

8
私はそのHasAnnotation方法を試しましたが、このような方法はありません。しかし、私はHasColumnAnnotationあなたが提供するパラメータを受け入れる名前のメソッドを見つけました。回答を更新する必要がありますか、それとも間違いですか?
HakanFıstık2015年

@HakamFostok EFサイトから直接例を取り上げました。おそらく、バージョンの1つで名前が変更されたか、元のバージョンにタイプミスがあります。
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)); 
  }
}

プロジェクトとソースコードはこちらです。楽しい!


私はパッケージが本当に好きですが、アップスクリプトで足場を組んだ後、インデックス名が欠落することがあります。インデックスで4つ以上のプロパティを使用しているときにのみ表示されました。EF 6.1.3を使用しています。
Mixxiphoid 2015

@Mixxiphoid- サポートの詳細を添えてここに問題を記録していただけますか?1.0.0にバグがあっため、バージョン1.0.1であることも確認してください。
Matt Johnson-Pint 2015

バージョン1.0.1を持っています。問題をログに記録しますが、現時点ではログに記録できません。
Mixxiphoid 2015

インデックス参加列の順序を降順に追加するにはどうすればよいですか?デフォルト.HasIndex(「IX_Customers_EmailAddress」、IndexOptions.Uniqueすることにより、...インデックスに参加するすべての列について昇順を作成します。
GDroid

@GDroid-残念ながら、これはEFのIndexAttributeクラスでは公開されていないため、ライブラリに含めることはできません。
Matt Johnson-Pint 2017年

24

明示的な名前なし:

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

特定の名前で:

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

インデックスは下落しているようです:(
Hamed Zakery Miab

1
@HamedZakeryMiabどのバージョンのEntity Frameworkを使用していますか?インデックスは廃止されませんでした。
HugoHilário2016年

すみません、含めるのを忘れていましたEntityFramework。それはそのアセンブリに含まれています。ちょうどNSについて混乱しています。
Hamed Zakery Miab 16年

@HamedZakeryMiabええ、とても混乱しました!System.DataAnnotationsの一部だと思いました!それは間違いなくエンティティフレームワークパッケージです
AlbatrossCafe

3
質問には次の文instead of using the new IndexAttributeが含まれています。
HakanFıstık2017

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 2016

@manetsusとてもいいです。変更を反映するコードスニペットを追加しました。
Darie Dorlus、2016年

3
文字列の長さが必要です。それ以外の場合、「インデックスのキー列として使用するには無効なタイプです」という例外が表示されます。私の同僚はConntextのmodelBuilderソリューションを好むので、ユーザークラスが乱雑にならないようにします。
アンドリューパテ2017年

一意性のために複数の列を持つインデックスはどうですか?複数列の一意キーインデックスを持つことはかなり一般的です
enorl76

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;

7

INDEXデータアノテーションコードファーストデータアノテーションを使用できます。


3
キーの最大長は、nvarcharの場合は900バイト、varcharの場合は450バイトです。最初にコードを使用している場合、文字列プロパティはnvarcharになるため、[[StringLength(450)]
dunwan


2

POCOで属性を使用したくない場合は、次のようにいつでも実行できます。

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

このステートメントは、カスタムDbInitializer派生クラスで実行できます。私はこれを行うためのFluent APIの方法を知りません。


1
はい、マート。現時点ではマイグレーションを使用しており、Up()メソッドに以下を追加することもできます:CreateIndex( "dbo.Table1"、 "Column1"、true、 "Column1_IX")and in()DropIndex(( "dbo.Table1 "、" Column1_IX ")。私も彼らが流暢なAPIを追加することを望んでいました...
Valo

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

あなたはこれの1つを使うことができます

//インデックス

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

または

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.