wake-up-neo.com

Erstellen eines eindeutigen Index mit der fließenden API von Entity Framework 6.1

Ich habe eine Spalte "Name", die einmalig sein muss. Kein Fremdschlüssel oder ähnliches.

EF 6.1 unterstützt schließlich die Erstellung solcher Indizes über Annotationen. Das wurde bereits auf SO besprochen. Es scheint jedoch, dass dies nur durch Anmerkungen in den Klassen möglich ist. Wie mache ich das nur mit der Fluent API?

Etwas wie das:

public class PersonConfiguration : EntityTypeConfiguration<Person>
{
    public PersonConfiguration()
    {
        HasKey(p => p.Id);
        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        //not possible?
        Index(p => p.Name).IsUnique();  //???
    }
}
38
John

HINWEIS: Relevant für EF 6

Sie können IndexAttribute wie erwähnt verwenden, aber mit Fluent API anstelle von DataAnnotations, was den Trick bewirkt:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name) 
    .HasColumnAnnotation( 
        "Index",  
        new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));

Leider gibt es keine andere Möglichkeit, eindeutige Indizes mit Fluent API zu erstellen. Es gibt ein offenes Problem bezüglich dieser Funktion: Unique Constraints (Unique Indexes)


UPDATE: Entity Framework Core

In der neuesten EF Core-Version können Sie sich auf Fluent API verlassen, um Indizes ohne zusätzliche Tricks anzugeben.
HasIndex erlaubt es, es zu definieren:

modelBuilder 
    .Entity<Person>()
    .HasIndex(x => x.Name);

Daher kehrt das Objekt IndexBuilder zurück und kann für weitere Indexkonfigurationen (d. H. Eindeutigkeit) verwendet werden:

modelBuilder 
    .Entity<Person>()
    .HasIndex(x => x.Name)
    .IsUnique();
58
Anatolii Gabuza

Basierend auf der Antwort von Anatolii, folgt eine Erweiterungsmethode, um eindeutige Indizes flüssiger zu setzen:

public static class MappingExtensions
{
    public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
    {
        return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
    }
}

Verwendungszweck:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name)
    .IsUnique();

Erzeugt Migration wie:

public partial class Add_unique_index : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Person", "Name", unique: true);
    }

    public override void Down()
    {
        DropIndex("dbo.Person", new[] { "Name" });
    }
}
36
Geir Sagberg

Diese Antwort enthält nur zusätzliche Informationen, da es bereits großartige Antworten gibt.

Wenn Sie mehrere eindeutige Felder in Ihrem Index haben möchten, können Sie dies durch Hinzufügen der Order-Eigenschaft erreichen. Sie müssen außerdem sicherstellen, dass Sie in allen Ihren Eigenschaften denselben Indexnamen verwenden (siehe unten uniqueIndex).

string uniqueIndex = "UN_TableName";

this.Property(t => t.PropertyOne)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 1
            }
        )
    );

this.Property(t => t.PropertyTwo)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 2
            }

        )
    );

Nehmen wir an, Sie möchten auch einen Index für PropertyTwo.

Die Methode falsch besteht darin, eine neu -Zeile mit this.Property(t => t.PropertyTwo) zu beginnen, als würde dies Ihren eindeutigen Index ABBRECHEN.

Alle Ihre Indizes (Index und Unique) müssen gleichzeitig definiert werden. Dies wäre der richtige Weg, dies zu tun:

this.Property(t => t.PropertyTwo)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(new[] 
            {
                new IndexAttribute(), // This is the index
                new IndexAttribute(uniqueIndex) // This is the Unique made earlier
                {
                    IsUnique = true,
                    Order = 2
                }
            }
        )
    );

Wenn Sie schließlich auch die Sortierreihenfolge Ihres Index/Unique ändern möchten, sehen Sie Folgendes: 

Wie füge ich einen Index für mehrere Spalten mit ASC/DESC-Sortierung mithilfe der Fluent-API hinzu? .

28
Maxime

In der neuen Version von EF, die 6.2 ist, können Sie die HasIndex-Methode verwenden:

 modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
 modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);

Update für EF Core:

 modelBuilder.Entity<User>()
        .HasIndex(b => b.Email)
        .IsUnique();

 modelBuilder.Entity<User>()
        .HasIndex(b => b.UserName)
        .IsUnique();

Microsoft Docs - EF Core-Indizes

8
Soheil Alizadeh

Sie können einen eindeutigen Index in Ihrer Migrationsdatei erstellen. 

Im Paketmanager:

  1. Aktivieren Sie Migrationen
  2. Add-Migration InitialMigration

Dadurch wird im Migrationsordner eine neue Datei erstellt, die mit einem Zeitstempel versehen ist. Die Klasse verfügt über eine Up- und eine Down-Methode, die Sie zum Erstellen des Index verwenden können:

public override void Up()
{
    // ... 
    CreateIndex("tableName", "columnName", unique: true, name: "myIndex");
}

public override void Down()
{
    // ...
    DropIndex("tableName", "myIndex");
}

Um den Migrationstyp Update-Database im Paketmanager auszuführen.

Sie können den Index auch als Teil der Migration hinzufügen, mit der die Tabelle erstellt wird:

CreateTable(
    "dbo.Products",
    c => new
        {
            ProductId = c.Int(nullable: false, identity: true),
            ProductName = c.String(nullable: false, maxLength: 256),
        })
    .Index(c => c.ProductName, name: "IX_Products_ProductName", unique: true)
    .PrimaryKey(t => t.ProductId);
4
Dismissile

Bei der Verwendung von MVC 5 und EF 6 bestand für mich der Schlüsselpunkt darin, eine Länge in der Zeichenfolge-Eigenschaft anzugeben, an der ich den Index platzieren wollte. 

protected override void OnModelCreating(DbModelBuilder modelBuilder){
    //More stuff
    modelBuilder.Entity<Device>().Property(c => c.Name).HasColumnType("nvarchar").HasMaxLength(50);
    modelBuilder.Entity<Device>().HasIndex(c => c.Name).IsUnique(true); 
}
0
Oscar