Entity Framework 6.2'de önce kodla dizin oluşturma


112

Bir mülk / sütun üzerinde yeniyi kullanmak yerine önce kodu kullanarak dizin oluşturmanın bir yolu var mı IndexAttribute?


5
Bir indeks bir veritabanı kavramıdır, bir varlık modeli kavramı değildir. Bir öznitelikle veya akıcı API aracılığıyla bir dizin belirtebilseniz bile, aslında uygulamanızda hiçbir şey YAPMAZ. Veritabanını oluştururken EF'in kullanması için bir talimat olurdu. Bu tür talimatların, tamamen veritabanı şemasının işlenmesiyle ilgili olan ilk kod geçişlerine ait olduğuna inanıyorum.
JC Ford

Yanıtlar:


84

Peki 26.10.2017 Entity Framework 6.2 resmi olarak yayınlandı . Fluent API aracılığıyla dizinleri kolaylıkla tanımlama olanağını içerir . Kullanılacaksa zaten 6.2 beta sürümünde duyurulmuştu .

Artık HasIndex()yöntemi, ardından IsUnique()benzersiz bir dizin olması gerekiyorsa kullanabilirsiniz.

Küçük bir karşılaştırma (önce / sonra) örneği:

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

Dizini kümelenmiş olarak işaretlemek de mümkündür .IsClustered().


DÜZENLE # 1

Çok sütunlu dizin için bir örnek ve bir dizinin kümelenmiş olarak nasıl işaretleneceği hakkında ek bilgi eklendi.


DÜZENLE # 2

Ek bilgi olarak, EF Core 2.1'de, şimdi EF 6.2'deki ile tamamen aynıdır.
İşte referans olarak MS Doc makalesi.


Bu harika! Sanırım çok sütunlu dizine sahipsem, şöyle bir şey olurdu: .HasIndex (p => new {p.Name, p.Xyz})
Valo

Oh, pardon, tabi. Olmalı new. Düzelteceğim.
ChW

Aynı kodu Core 2.x'te nasıl yazabileceğimizi gösterir misiniz?
user3417479

Bildiğim kadarıyla "sonra" ve "çok sütunlu indeks" altında gösterilen kodun aynısı olmalı.
ChW

87

Şu anda akıcı API aracılığıyla bir dizin oluşturmak için "birinci sınıf destek" yoktur , ancak akıcı API aracılığıyla yapabileceğiniz şey, özellikleri Ek Açıklama API'sinden özelliklere sahip olarak işaretleyebilirsiniz. Bu, Indexözelliği akıcı bir arayüz aracılığıyla eklemenize izin verecektir .

İşte EF için Sorunlar sitesindeki çalışma öğesinden bazı örnekler.

Tek bir sütunda bir dizin oluşturun:

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

Tek bir sütunda birden çok dizin:

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

Çok Sütunlu dizinler:

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

Yukarıdaki tekniklerin kullanılması, bir sonraki geçişinizi yapılandırdığınızda işlevinizde .CreateIndex()sizin için otomatik olarak çağrıların oluşturulmasına Up()(veya geçişleri kullanmıyorsanız veritabanında otomatik olarak oluşturulmasına) neden olacaktır.


4
Bu, dizini sütuna ekleyebilir, ancak bu, birincil anahtarda oluşturulan kümelenmiş dizini kaldırmaz. HasKey, varsayılan olarak kaldırılmayan birincil anahtarlarda kümelenmiş dizini oluşturur. Bunun, clusered: false in .Primarykey(x=>x.id,clustered:false)yöntemi belirtilerek oluşturulan geçiş dosyasından açıkça kaldırılması gerekir
Joy,

8
HasAnnotationYöntemi denedim ve bunun gibi bir yöntem yok. ama HasColumnAnnotationsağladığınız parametreleri kabul eden isimli bir yöntem buldum . Cevabınızı güncellemeniz mi gerekiyor yoksa yanılıyor muyum?
Hakan Fıstık

@HakamFostok Örneği doğrudan EF sitesinden aldım. Belki de sürümlerden birinde isim değişmiştir veya orijinal sürümde bir yazım hatası vardır.
Scott Chamberlain

3
Bu yılın başlarında düzenlenen bir tasarım toplantısında aşağıdaki bağlantının hemen altına bakın: "HasAnnotation'ı HasColumnAnnotation (artı kod tabanındaki diğer ilgili yerler) olarak yeniden adlandırın.". entityframework.codeplex.com/…
Zac Charles

36

Bunu daha kolay hale getirmek için bazı uzantı yöntemleri oluşturdum ve bunları bir nuget paketine sardım.

EntityFramework.IndexingExtensionsNuGet paketini kurun .

Daha sonra şunları yapabilirsiniz:

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

Proje ve kaynak kodu burada . Zevk almak!


Paketi gerçekten beğendim ama görünüşe göre yukarı komut dosyasında yapı iskelesi oluşturduktan sonra dizin adı bazen eksik görünüyor. Benim için yalnızca dizinimde 4 veya daha fazla özellik kullanırken göründü. EF 6.1.3 ile çalışıyorum.
Mixxiphoid

@Mixxiphoid - sorunu destekleyici ayrıntılarla buraya kaydeder misiniz ? Ayrıca 1.0.0'da bir hata olduğundan 1.0.1 sürümüne sahip olduğunuzdan emin olun .
Matt Johnson-Pint

1.0.1 sürümüne sahibim. Sorunu günlüğe kaydedeceğim ancak şu anda yapamam.
Mixxiphoid

Azalan sıraya dizine katılan sütun sırasını nasıl eklerim? Varsayılan olarak .HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... dizindeki tüm katılan sütunlar için artan düzen oluşturur.
GDroid

@GDroid - Ne yazık ki, bu EF'in IndexAttributesınıfı tarafından gösterilmiyor , bu yüzden onu kitaplığıma ekleyemiyorum .
Matt Johnson-Pint

24

Açık bir isim olmadan:

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

Belirli bir adla:

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


1
@HamedZakeryMiab Entity Framework'ün hangi sürümünü kullanıyorsunuz? Dizin kullanımdan kaldırılmadı.
Hugo Hilário

afedersiniz, eklemeyi unuttum EntityFramework. bu derlemeye dahildir. NS hakkında kafam karıştı.
Hamed Zakery Miab

@HamedZakeryMiab evet, bu süper kafa karıştırıcıydı! System.DataAnnotations'ın bir parçası olduğunu düşündüm! Kesinlikle varlık çerçeve paketidir
AlbatrossCafe

3
soru aşağıdaki ifadeyi içeriyor instead of using the new IndexAttributefark ettiniz mi?
Hakan Fıstık

22

EF 6.1'den itibaren öznitelik [Index]desteklenmektedir. Benzersiz dizin için
kullanın [Index(IsUnique = true)].
İşte Microsoft'un bağlantısı

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

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

    public string DisplayName { get; set; } 
}

2
Bu teorik olarak soruya cevap görülebilir fakat tercih edildiğini burada cevabın temel parçalarını kapsadığı ve başvuru için bağlantı sağlar.
Enamul Hassan

@manetsus Çok iyi. Değişikliği yansıtmak için bir kod parçası ekledim.
Darie Dorlus

3
Dize uzunluğu gereklidir, aksi takdirde bir 'bir dizinde anahtar sütun olarak kullanım için geçersiz bir türden' istisnası görürsünüz. Meslektaşım Conntext'te modelBuilder çözümünü tercih ediyor, bu yüzden User sınıfınızı karıştırmıyorsunuz, ki bu geçerli.
andrew pate

Benzersizlik için birden çok sütuna sahip dizinler ne olacak? Çok sütunlu Benzersiz Anahtar dizinine sahip olmak oldukça yaygındır ...
enorl76

1
@ enorl76 Bu da desteklenmektedir. Her sütun için aşağıdaki gibi bir öznitelik kullanmanız gerekir, [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } İşte Microsoft
Darie Dorlus'tan

8

Entity Framework 6

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

Ve şunu kullanarak ekleyin:

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


2

POCO'larınızda öznitelikler kullanmak istemiyorsanız, bunu her zaman aşağıdaki gibi yapabilirsiniz:

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

Bu ifadeyi özel DbInitializertüretilmiş sınıfınızda çalıştırabilirsiniz. Yine de bunu yapmanın herhangi bir Fluent API yolunu bilmiyorum.


1
Tabii Mert. Şu anda geçişleri kullanıyorum ve orada Up () yönteminde şunları da koyabilirsiniz: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") ve Down () DropIndex (("dbo.Table1) "," Column1_IX "). Sadece akıcı bir API eklediklerini umuyordum ...
Valo

1

Ekstra koddan kaçınmak için akıcı EF'de kullanmak için bir uzantı yöntemi yazıyorum:

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

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

sonra şu şekilde kullanın:

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

veya indeks bazı yapılandırmalara ihtiyaç duyarsa bunun gibi:

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

1

Bunlardan birini kullanabilirsin

// Dizinler

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

veya

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.