Создание уникального индекса с помощью Entity Framework 6.1 fluent API
У меня есть столбец "Name", который должен быть unqiue. Никакого внешнего ключа или чего-то подобного.
EF 6.1, наконец, поддерживает создание таких индексов с помощью аннотаций. Это уже обсуждалось на SO. Но, похоже, это можно сделать только с помощью аннотаций в классах. Как это сделать, используя только Fluent API?
что-то вроде этого:
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(); //???
}
}
6 ответов
Примечание: относится к EF 6
можно использовать IndexAttribute
как уже упоминалось, но С Fluent API
вместо DataAnnotations
что будет делать трюк:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
к сожалению, нет другого способа создать уникальные индексы с помощью Fluent API
. Существует открытая проблема, касающаяся этой функции:Уникальные Ограничения (Уникальные Индексы)
обновление: Entity Framework Ядро
В последнем выпуске EF Core вы можете положиться на
Fluent API
для указания индексов без дополнительных уловок.
HasIndex
позволяет определить его:
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name);
отсюда ретурс IndexBuilder
object вы можете использовать его для дальнейших конфигураций индекса (i.e уникальность):
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name)
.IsUnique();
основываясь на ответе Анатолия, вот метод расширения для более плавной установки уникальных индексов:
public static class MappingExtensions
{
public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
{
return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
}
}
использование:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.IsUnique();
будет генерировать миграции, такие как:
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" });
}
}
этот ответ содержит только дополнительную информацию, поскольку уже есть отличные ответы.
если вы хотите несколько уникальных полей в вашем индексе вы можете достичь этого, добавив Order
собственность. Необходимо также убедиться, что во всех свойствах используется одно и то же имя индекса (см. 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
}
)
);
теперь, предположим, вы также хотите индекс на PropertyTwo
.
на неправильно способ сделать это было бы начать новая строку с this.Property(t => t.PropertyTwo)
как это отменит Ваш уникальный индекс.
все ваши индексы (index и unique) должны быть определены одновременно. Это был бы правильный способ сделать это:
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
}
}
)
);
наконец, если вы также хотите изменить порядок сортировки вашего индекса / unique, вы можете увидеть:
как добавить индекс на несколько столбцов с сортировкой ASC/DESC с помощью Fluent API ?.
в новой версии EF это 6.2 можно использовать HasIndex
способ:
modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);
обновление для EF Core:
modelBuilder.Entity<User>()
.HasIndex(b => b.Email)
.IsUnique();
modelBuilder.Entity<User>()
.HasIndex(b => b.UserName)
.IsUnique();
в файле миграции можно создать уникальный индекс.
В Менеджере Пакетов:
- Включить-Миграций
- Добавить - Миграция InitialMigration
это создаст новый файл в папке миграций, который помечен временем. Класс будет иметь метод Up и Down, который можно использовать для создания индекса:
public override void Up()
{
// ...
CreateIndex("tableName", "columnName", unique: true, name: "myIndex");
}
public override void Down()
{
// ...
DropIndex("tableName", "myIndex");
}
для запуска типа миграции Update-Database в диспетчере пакетов.
вы также можете добавьте индекс как часть миграции, которая также создает таблицу:
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);
для меня, используя MVC 5 и EF 6, ключевой точкой было указание длины в свойстве string, где я хотел разместить индекс.
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);
}