Я пытаюсь создать EF Entity с кодом First и EntityTypeConfiguration
, используя свободный API. создание первичных ключей легко, но не так с уникальным ограничением. Я видел старые сообщения, которые предлагали выполнять собственные команды SQL для этого, но они, похоже, преследуют цель. возможно ли это с помощью EF6?
Настройка уникального ограничения с использованием свободного API?
Ответ 1
На EF6.2 вы можете использовать HasIndex()
для добавления индексов для миграции через свободный API.
https://github.com/aspnet/EntityFramework6/issues/274
Пример
modelBuilder
.Entity<User>()
.HasIndex(u => u.Email)
.IsUnique();
На EF6.1 и далее вы можете использовать IndexAnnotation()
для добавления индексов для миграции в ваш свободный API.
http://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex
Вы должны добавить ссылку на:
using System.Data.Entity.Infrastructure.Annotations;
Базовый пример
Вот простое использование, добавление индекса для свойства User.FirstName
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
Практический пример:
Вот более реалистичный пример. Он добавляет уникальный индекс для нескольких свойств: User.FirstName
и User.LastName
с именем индекса "IX_FirstNameLastName"
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true }));
modelBuilder
.Entity<User>()
.Property(t => t.LastName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));
Ответ 2
В дополнение к ответу Йорро это можно сделать с помощью атрибутов.
Пример комбинации уникальных клавиш типа int
:
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
Если тип данных string
, то необходимо добавить атрибут MaxLength
:
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
Если существует проблема разделения модели домен/хранилище, можно использовать атрибут/класс Metadatatype
: https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx?f=255&MSPPError=-2147217396
Пример быстрого консольного приложения:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace EFIndexTest
{
class Program
{
static void Main(string[] args)
{
using (var context = new AppDbContext())
{
var newUser = new User { UniqueKeyIntPart1 = 1, UniqueKeyIntPart2 = 1, UniqueKeyStringPart1 = "A", UniqueKeyStringPart2 = "A" };
context.UserSet.Add(newUser);
context.SaveChanges();
}
}
}
[MetadataType(typeof(UserMetadata))]
public class User
{
public int Id { get; set; }
public int UniqueKeyIntPart1 { get; set; }
public int UniqueKeyIntPart2 { get; set; }
public string UniqueKeyStringPart1 { get; set; }
public string UniqueKeyStringPart2 { get; set; }
}
public class UserMetadata
{
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
}
public class AppDbContext : DbContext
{
public virtual DbSet<User> UserSet { get; set; }
}
}
Ответ 3
Ниже приведен метод расширения для установки уникальных индексов более плавно:
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" });
}
}
Src: Создание уникального индекса с функциональным API-интерфейсом Entity Framework 6.1
Ответ 4
@coni2k ответ правильный, однако вы должны добавить атрибут [StringLength]
для работы, иначе вы получите недопустимое ключевое исключение (Пример ниже).
[StringLength(65)]
[Index("IX_FirstNameLastName", 1, IsUnique = true)]
public string FirstName { get; set; }
[StringLength(65)]
[Index("IX_FirstNameLastName", 2, IsUnique = true)]
public string LastName { get; set; }
Ответ 5
К сожалению, это не поддерживается в Entity Framework. Это было на дорожной карте для EF 6, но ее отбросили: Workemem 299: Уникальные ограничения (уникальные индексы)
Ответ 6
Между тем есть следующее:
Извините за не копирование кода, это немного длиннее.