So erstellen Sie zuerst einen Index in Entity Framework 6.2 mit Code

112

Gibt es eine Möglichkeit, einen Index für eine Eigenschaft / Spalte mit Code-First zu erstellen, anstatt den neuen zu verwenden IndexAttribute?

Valo
quelle
5
Ein Index ist ein Datenbankkonzept, kein Entitätsmodellkonzept. Selbst wenn Sie einen Index mit einem Attribut oder über die fließende API angeben könnten, würde dies in Ihrer Anwendung nichts bewirken. Es wäre nur eine Anweisung für EF, die beim Erstellen der Datenbank verwendet werden soll. Ich glaube, solche Anweisungen gehören zu Code-First-Migrationen, die sich ausschließlich mit der Manipulation des Datenbankschemas befassen.
JC Ford

Antworten:

84

Nun, 26.10.2017 Entity Framework 6.2 wurde offiziell veröffentlicht . Es bietet die Möglichkeit , Indizes einfach über die Fluent API zu definieren. Wie es zu verwenden ist, wurde bereits in der Beta von 6.2 angekündigt .

Jetzt können Sie die HasIndex()Methode verwenden, gefolgt von der Frage, IsUnique()ob es sich um einen eindeutigen Index handeln soll.

Nur ein kleiner Vergleich (vorher / nachher) Beispiel:

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

Es ist auch möglich, den Index als gruppiert mit zu markieren .IsClustered().


EDIT # 1

Es wurde ein Beispiel für einen mehrspaltigen Index und zusätzliche Informationen zum Markieren eines Index als Cluster hinzugefügt.


EDIT # 2

Als zusätzliche Information ist es in EF Core 2.1 genau das gleiche wie in EF 6.2.
Hier ist der MS Doc Artcile als Referenz.

ChW
quelle
Das ist toll! Ich nehme an, wenn ich einen mehrspaltigen Index habe, wäre das ungefähr so: .HasIndex (p => new {p.Name, p.Xyz})
Valo
Oh, tut mir leid, sicher. Es sollte sein new. Ich werde es reparieren.
ChW
Könnten Sie bitte zeigen, wie wir denselben Code in Core 2.x schreiben können?
user3417479
Soweit ich weiß, sollte es der gleiche Code sein, der unter "nach" und "mehrspaltiger Index" angezeigt wird.
ChW
87

Derzeit gibt es keine "erstklassige Unterstützung" für die Erstellung eines Index über die fließende API. Sie können jedoch über die fließende API Eigenschaften als Attribute aus der Annotation-API markieren. Auf diese Weise können Sie das IndexAttribut über eine fließende Schnittstelle hinzufügen .

Hier sind einige Beispiele aus dem Arbeitselement von der Issues-Site für EF.

Erstellen Sie einen Index für eine einzelne Spalte:

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

Mehrere Indizes für eine einzelne Spalte:

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

Mehrspaltige Indizes:

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

Wenn Sie die oben genannten Techniken verwenden, werden beim Erstellen Ihrer nächsten Migration .CreateIndex()automatisch Aufrufe für Sie in Ihrer Up()Funktion erstellt (oder automatisch in der Datenbank erstellt, wenn Sie keine Migrationen verwenden).

Scott Chamberlain
quelle
4
Dadurch wird möglicherweise der Index für die Spalte hinzugefügt, der auf dem Primärschlüssel erstellte Clustered-Index wird jedoch nicht entfernt. Der hasKey erstellt den Clustered-Index für Primärschlüssel, die nicht standardmäßig entfernt werden. Das muss explizit aus der Migrationsdatei entfernt werden, die durch Angabe von clusered: false in .Primarykey(x=>x.id,clustered:false)method
Joy
8
Ich habe die HasAnnotationMethode ausprobiert und es gibt KEINE solche Methode. Aber ich habe eine Methode gefunden, deren Name HasColumnAnnotationdie von Ihnen angegebenen Parameter akzeptiert. Müssen Sie Ihre Antwort aktualisieren oder irre ich mich?
Hakan Fıstık
@HakamFostok Ich habe das Beispiel direkt von der EF-Site genommen. Vielleicht hat sich der Name in einer der Versionen geändert oder es gibt einen Tippfehler in der Originalversion.
Scott Chamberlain
3
Siehe ganz unten unter dem folgenden Link eines Designmeetings Anfang dieses Jahres: "HasAnnotation in HasColumnAnnotation umbenennen (plus andere relevante Stellen in der Codebasis)." entityframework.codeplex.com/…
Zac Charles
36

Ich habe einige Erweiterungsmethoden erstellt und sie in ein Nuget-Paket eingeschlossen, um dies viel einfacher zu machen.

Installieren Sie das EntityFramework.IndexingExtensionsNuget-Paket.

Dann können Sie Folgendes tun:

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

Das Projekt und der Quellcode sind hier . Genießen!

Matt Johnson-Pint
quelle
Ich mag das Paket wirklich, aber es scheint, dass der Indexname manchmal nach dem Gerüstbau im up-Skript fehlt. Es erschien mir nur, wenn ich 4 oder mehr Eigenschaften in meinem Index verwendete. Ich arbeite mit EF 6.1.3.
Mixxiphoid
@Mixxiphoid - Würden Sie das Problem bitte hier mit unterstützenden Details protokollieren ? Stellen Sie außerdem sicher, dass Sie Version 1.0.1 haben, da in 1.0.0 ein Fehler aufgetreten ist.
Matt Johnson-Pint
Ich habe Version 1.0.1. Ich werde das Problem protokollieren, kann dies jedoch derzeit nicht tun.
Mixxiphoid
Wie füge ich der absteigenden Reihenfolge der teilnehmenden Indexspalten hinzu? Standardmäßig erstellt .HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... eine aufsteigende Reihenfolge für alle teilnehmenden Spalten im Index.
GDroid
@GDroid - Leider wird dies von der EF- IndexAttributeKlasse nicht verfügbar gemacht , sodass ich es nicht in meine Bibliothek aufnehmen kann.
Matt Johnson-Pint
24

Ohne expliziten Namen:

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

Mit einem bestimmten Namen:

[Index("PostRatingIndex")] 
public int Rating { get; set; }
Hugo Hilário
quelle
Index scheint beraubt zu sein :(
Hamed Zakery Miab
1
@HamedZakeryMiab Welche Version von Entity Framework verwenden Sie? Index wurde nicht veraltet.
Hugo Hilário
Entschuldigung, ich habe vergessen einzuschließen EntityFramework. Es ist in dieser Baugruppe enthalten. nur verwirrt über die NS.
Hamed Zakery Miab
@HamedZakeryMiab ja das war super verwirrend! Ich dachte, es wäre Teil von System.DataAnnotations! Es ist definitiv das Entity Framework-Paket
AlbatrossCafe
3
Die Frage enthält die folgende Aussage. instead of using the new IndexAttributeHaben Sie es bemerkt?
Hakan Fıstık
22

Ab EF 6.1 wird das Attribut [Index]unterstützt.
Verwenden Sie [Index(IsUnique = true)]für einen eindeutigen Index.
Hier ist der Link von 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
quelle
2
Während dies theoretisch die Frage beantworten kann, wäre es vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.
Enamul Hassan
@ Manetsus Sehr gut. Ich habe ein Code-Snippet hinzugefügt, um die Änderung widerzuspiegeln.
Darie Dorlus
3
Die Zeichenfolgenlänge wird benötigt, andernfalls wird die Ausnahme "ist von einem Typ, der für die Verwendung als Schlüsselspalte in einem Index ungültig ist" angezeigt. Mein Kollege bevorzugt die modelBuilder-Lösung im Conntext, damit Sie Ihre Benutzerklasse nicht überladen, was meiner Meinung nach gültig ist.
Andrew Pate
Was ist mit Indizes mit mehreren Spalten für die Eindeutigkeit? Sehr häufig, um einen mehrspaltigen eindeutigen Schlüsselindex zu haben ...
enorl76
1
@ enorl76 Das wird auch unterstützt. Für jede Spalte müssten Sie ein Attribut wie das folgende verwenden, [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } hier die Referenz von Microsoft
Darie Dorlus
8

Entity Framework 6

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

Und füge hinzu mit:

using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
Guilherme Ferreira
quelle
2

Wenn Sie keine Attribute für Ihre POCOs verwenden möchten, können Sie dies jederzeit wie folgt tun:

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

Sie können diese Anweisung in Ihrer benutzerdefinierten DbInitializerabgeleiteten Klasse ausführen . Ich kenne jedoch keine Fluent API-Methode, um dies zu tun.

Mert Akcakaya
quelle
1
Sicher, Mert. Im Moment verwende ich Migrationen und dort können Sie in der Up () -Methode auch Folgendes eingeben: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") und in Down () DropIndex (("dbo.Table1") "," Column1_IX "). Ich hatte nur gehofft, dass sie auch eine fließende API hinzugefügt haben ...
Valo
1

Ich schreibe eine Erweiterungsmethode für die Verwendung in fließendem EF, um zusätzlichen Code zu vermeiden:

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

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

dann benutze es so:

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

oder so, wenn der Index einige Konfigurationen benötigt:

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

Sie können eines davon verwenden

// Indizes

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

oder

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