Создание уникального индекса с API-интерфейсом Entity Framework 6.1
У меня есть столбец "Имя", который должен быть 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(); //???
}
}
Ответы
Ответ 1
Вы можете использовать IndexAttribute
, как упоминалось, но с Fluent API
вместо DataAnnotations
, который выполнит трюк:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
К сожалению, нет другого способа создания уникальных индексов с помощью Fluent API
. Существует открытая проблема в отношении этой функции: Уникальные ограничения (уникальные индексы)
Ответ 2
На основе ответа Анатолия, это метод расширения для более простого определения уникальных индексов:
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" });
}
}
Ответ 3
Этот ответ содержит только дополнительную информацию, так как есть уже отличные ответы.
Если вы хотите иметь несколько уникальных полей в своем индексе, вы можете достичь этого, добавив свойство 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)
, так как это ОТМЕНА вашего уникального индекса.
Все ваши индексы (индексы и уникальные) должны быть определены одновременно. Это было бы правильным способом:
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
}
}
)
);
Наконец, если вы также хотите изменить порядок сортировки вашего индекса/уникального, вы можете увидеть:
Как добавить индекс в несколько столбцов с сортировкой по ASC/DESC с использованием Fluent API?.
Ответ 4
Вы можете создать уникальный индекс в файле миграции.
В диспетчере пакетов:
- Enable-Миграция
- Add-Migration InitialMigration
Это создаст новый файл в папке Migrations, отмеченный меткой времени. Класс будет иметь метод 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);