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(); //???
}
}
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)
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();
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" });
}
}
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? .
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();
Sie können einen eindeutigen Index in Ihrer Migrationsdatei erstellen.
Im Paketmanager:
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);
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);
}