Cara membuat index di Entity Framework 6.2 dengan kode terlebih dahulu

112

Apakah ada cara untuk membuat indeks pada properti / kolom menggunakan code-first, daripada menggunakan yang baru IndexAttribute?

Valo
sumber
5
Indeks adalah konsep database, bukan konsep model entitas. Bahkan jika Anda dapat menentukan indeks dengan atribut atau melalui API yang lancar, itu tidak akan benar-benar MELAKUKAN apa pun dalam aplikasi Anda. Ini hanya akan menjadi instruksi yang digunakan EF saat membuat database. Saya yakin instruksi seperti itu termasuk dalam migrasi kode pertama, yang sepenuhnya berkaitan dengan manipulasi skema database.
JC Ford

Jawaban:

84

Nah 26.10.2017 Entity Framework 6.2 secara resmi dirilis . Ini mencakup kemungkinan untuk menentukan indeks dengan mudah melalui Fluent API. Ho itu digunakan sudah diumumkan dalam versi beta 6.2.

Sekarang Anda dapat menggunakan HasIndex()metode ini, diikuti oleh IsUnique()jika itu adalah indeks unik.

Contoh perbandingan kecil (sebelum / sesudah):

// 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();

Juga dimungkinkan untuk menandai indeks sebagai clustered with .IsClustered().


EDIT # 1

Menambahkan contoh untuk indeks multi kolom dan informasi tambahan tentang cara menandai indeks sebagai berkerumun.


EDIT # 2

Sebagai informasi tambahan, di EF Core 2.1 persis sama seperti di EF 6.2 sekarang.
Berikut adalah artcile MS Doc sebagai referensi.

ChW
sumber
Ini bagus! Saya kira jika saya memiliki indeks multikolom, itu akan menjadi seperti ini: .HasIndex (p => new {p.Name, p.Xyz})
Valo
Oh, maaf, tentu. Seharusnya begitu new. Saya akan memperbaikinya.
ChW
Bisakah Anda menunjukkan bagaimana kita bisa menulis kode yang sama di Core 2.x?
pengguna3417479
Sejauh yang saya tahu itu harus kode yang sama seperti yang ditunjukkan di bawah "setelah" dan "indeks multi kolom".
ChW
87

Saat ini tidak ada "dukungan kelas satu" untuk membuat indeks melalui API yang lancar, tetapi yang dapat Anda lakukan adalah melalui API yang lancar Anda dapat menandai properti sebagai memiliki atribut dari API Anotasi. Ini akan memungkinkan Anda untuk menambahkan Indexatribut melalui antarmuka yang lancar.

Berikut adalah beberapa contoh dari item pekerjaan dari situs Issues untuk EF.

Buat indeks pada satu kolom:

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

Beberapa indeks dalam satu kolom:

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

Indeks Multi-Kolom:

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)));

Menggunakan teknik di atas akan menyebabkan .CreateIndex()panggilan dibuat secara otomatis untuk Anda dalam Up()fungsi saat Anda menyusun migrasi berikutnya (atau secara otomatis dibuat dalam database jika Anda tidak menggunakan migrasi).

Scott Chamberlain
sumber
4
yang mungkin menambahkan indeks pada kolom tetapi itu tidak akan menghapus indeks berkerumun yang dibuat pada kunci utama. HashKey membuat indeks berkerumun pada kunci utama yang tidak secara default dihapus. Itu harus secara eksplisit dihapus dari file migrasi yang dibuat dengan menyatakan clusered: false in .Primarykey(x=>x.id,clustered:false)method
Joy
8
Saya mencoba HasAnnotationmetode tersebut dan tidak ada metode seperti ini. tetapi saya menemukan metode yang namanya HasColumnAnnotationmenerima parameter yang Anda berikan. Apakah Anda perlu memperbarui jawaban Anda atau saya salah?
Hakan Fıstık
@HakamFostok Saya mengambil contoh langsung dari situs EF. Mungkin namanya berubah di salah satu versi atau ada kesalahan ketik di versi aslinya.
Scott Chamberlain
3
Lihat kanan bawah tautan berikut dari rapat desain awal tahun ini: "Ubah nama HasAnnotation menjadi HasColumnAnnotation (ditambah tempat relevan lainnya di basis kode).". entityframework.codeplex.com/…
Zac Charles
36

Saya telah membuat beberapa metode ekstensi dan membungkusnya dalam paket nuget untuk membuatnya lebih mudah.

Instal EntityFramework.IndexingExtensionspaket nuget.

Kemudian Anda dapat melakukan hal berikut:

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)); 
  }
}

Proyek dan kode sumber ada di sini . Nikmati!

Matt Johnson-Pint
sumber
Saya sangat suka paketnya tetapi tampaknya nama indeks terkadang hilang setelah perancah di skrip up. Ini hanya muncul untuk saya saat menggunakan 4 atau lebih properti di indeks saya. Saya bekerja dengan EF 6.1.3.
Mixxiphoid
@Mixxiphoid - bisakah Anda mencatat masalah di sini dengan detail pendukung? Juga pastikan Anda memiliki versi 1.0.1, karena ada bug di 1.0.0.
Matt Johnson-Pint
Saya memiliki versi 1.0.1. Saya akan mencatat masalah tersebut tetapi tidak dapat melakukannya saat ini.
Mixxiphoid
Bagaimana cara menambahkan urutan kolom indeks yang berpartisipasi ke turun? Secara default .HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... membuat urutan menaik untuk semua kolom yang berpartisipasi dalam indeks.
GDroid
@GDroid - Sayangnya, ini tidak diekspos oleh IndexAttributekelas EF , jadi saya tidak dapat memasukkannya ke dalam perpustakaan saya.
Matt Johnson-Pint
24

Tanpa nama eksplisit:

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

Dengan nama tertentu:

[Index("PostRatingIndex")] 
public int Rating { get; set; }
Hugo Hilário
sumber
Indeks tampaknya melemah :(
Hamed Zakery Miab
1
@HamedZakeryMiab Versi Entity Framework manakah yang Anda gunakan? Indeks tidak digunakan lagi.
Hugo Hilário
permisi, saya lupa memasukkan EntityFramework. itu termasuk dalam majelis itu. hanya bingung dengan NS.
Hamed Zakery Miab
@HamedZakeryMiab ya itu sangat membingungkan! Saya pikir itu adalah bagian dari System.DataAnnotations! Ini jelas merupakan paket kerangka entitas
AlbatrossCafe
3
pertanyaan berisi pernyataan berikut instead of using the new IndexAttributeapakah Anda memperhatikannya?
Hakan Fıstık
22

Dari EF 6.1 dan seterusnya, atribut [Index]ini didukung.
Gunakan [Index(IsUnique = true)]untuk indeks unik.
Ini tautan dari Microsoft

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

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

    public string DisplayName { get; set; } 
}
Darie Dorlus
sumber
2
Meskipun ini secara teoritis dapat menjawab pertanyaan, akan lebih baik jika menyertakan bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
Enamul Hassan
@etsus Baiklah. Saya menambahkan potongan kode untuk mencerminkan perubahan tersebut.
Darie Dorlus
3
Panjang string diperlukan jika tidak, Anda akan melihat 'adalah jenis yang tidak valid untuk digunakan sebagai kolom kunci dalam pengecualian indeks'. Kolega saya lebih memilih solusi modelBuilder pada Conntext sehingga Anda tidak mengacaukan kelas Pengguna Anda, yang menurut saya valid.
andrew pate
Bagaimana dengan indeks dengan banyak kolom untuk keunikan? Cukup umum untuk memiliki indeks Kunci Unik multi-kolom ...
enorl76
1
@ enorl76 Itu juga didukung. Untuk setiap kolom Anda perlu menggunakan atribut seperti berikut, [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } Berikut referensi dari Microsoft
Darie Dorlus
8

Kerangka Entitas 6

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

Dan tambahkan menggunakan:

using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
Guilherme Ferreira
sumber
7

Anda dapat menggunakan anotasi data INDEX Kode Anotasi Data Pertama

Emre
sumber
3
Panjang kunci maksimum adalah 900 byte untuk nvarchar dan 450 byte untuk varchar. Jika Anda menggunakan kode terlebih dahulu, properti string akan menjadi nvarchar dan Anda harus menyertakan atribut "StringLength" seperti pada [[StringLength (450)]
dunwan
Mulai EF 6.1, ini adalah jawaban yang benar. docs.microsoft.com/en-us/ef/ef6/modeling/code-first/…
Chris Schaller
2

Jika Anda tidak ingin menggunakan atribut pada POCO Anda, Anda selalu dapat melakukannya seperti berikut:

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

Anda dapat menjalankan pernyataan ini di DbInitializerkelas turunan khusus Anda . Saya tidak tahu cara API Lancar untuk melakukan ini.

Mert Akcakaya
sumber
1
Tentu, Mert. Saat ini saya menggunakan migrasi dan di sana di metode Up () Anda juga dapat meletakkan: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") dan di Down () DropIndex (("dbo.Table1 "," Column1_IX "). Saya hanya berharap mereka menambahkan API yang lancar juga ...
Valo
1

Saya menulis metode ekstensi untuk digunakan dalam EF yang lancar untuk menghindari kode tambahan:

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

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

lalu gunakan seperti ini:

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

atau seperti ini jika indeks membutuhkan beberapa konfigurasi:

Property(t => t.CardNo)
    .HasIndexAnnotation(new IndexAttribute("IX_Account") { IsUnique = true });
Omid-RH
sumber
1

Anda bisa menggunakan salah satunya

// Indeks

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

atau

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
Nayas Subramanian
sumber