Entity Framework Core додає спочатку унікальний код обмеження


152

Я не можу знайти унікальне обмеження в моєму полі за допомогою атрибута:

public class User
{
    [Required]
    public int Id { get; set; }

    [Required]
    // [Index("IX_FirstAndSecond", 2, IsUnique = true)] not supported by core
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

Я використовую ці пакети:

 "Microsoft.EntityFrameworkCore": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
 "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",

Зразки вільного Api для індексів дивіться на learnnentityframeworkcore.com/configuration/fluent-api/…
Michael Freidgeim

Відповіді:


301

На ядрі EF ви не можете створити індекси за допомогою анотацій даних. Але це можна зробити за допомогою API Fluent.

Як це всередині вашого {Db}Context.cs:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
        .HasIndex(u => u.Email)
        .IsUnique();
}

... або якщо ви використовуєте перевантаження з buildAction:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>(entity => {
        entity.HasIndex(e => e.Email).IsUnique();
    });
}

Більше про це можна прочитати тут: Індекси


1
Дуже дякую за допомогу, це правильне рішення!
Вадим М

Якщо хтось приземлиться тут, шукаючи рішення, яке працює при використанні схеми MS Identity, я пропоную встановити унікальне обмеження для поля NormalizedEmail, а не електронної пошти (суб'єкта AspNetUsers). Використання різного регістру може не порушити обмеження, навіть якщо це одна і та ж адреса електронної пошти, залежно від налаштування збору db.
Том

4
Цей код не працює для стовпця типу string :( Чи є можливість додати унікальне обмеження для рядка стовпця?
Johar Zaman

Ідіть наHasAlternateKey
Chamika Sandamal

1
Я спробував це, коли я працював над цим, але тепер мені це не потрібно реалізовувати. Btw Дякую за ваш коментар. @Sampath
Джохар Заман

70

Також якщо ви хочете створити унікальні обмеження на кількох стовпцях, ви можете просто зробити це (перейшовши за посиланням @ Sampath )

class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasIndex(p => new { p.FirstName, p.LastName })
            .IsUnique(true);
    }
}

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

9

Рішення для EF Core

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Passport { get; set; }
}

public class ApplicationContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public ApplicationContext()
    {
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=efbasicsappdb;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasAlternateKey(u => u.Passport);
        //or: modelBuilder.Entity<User>().HasAlternateKey(u => new { u.Passport, u.Name})
    }
}

Таблиця БД буде виглядати так:

CREATE TABLE [dbo].[Users] (
    [Id]       INT            IDENTITY (1, 1) NOT NULL,
    [Name]     NVARCHAR (MAX) NULL,
    [Passport] NVARCHAR (450) NOT NULL,
    CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [AK_Users_Passport] UNIQUE NONCLUSTERED ([Passport] ASC)
);

Посилання на документи EF Core


11
Згідно з документами EF Core:If you just want to enforce uniqueness of a column then you want a unique index rather than an alternate key. In EF, alternate keys provide greater functionality than unique indexes because they can be used as the target of a foreign key.
bigworld12

Посилання на коментар bigworld12
granadaCoder

3

ОП запитує про те, чи можна додати атрибут до класу Entity для унікального ключа. Коротка відповідь полягає в тому, що це можливо, але не є функцією, яка не випускається від базової команди EF. Якщо ви хочете використовувати атрибут для додавання унікальних ключів до класів сутності Entity Framework Core, ви можете робити те, що я розмістив тут

public class Company
{
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid CompanyId { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 0)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyName { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 1)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyLocation { get; set; }
}

Атрибут [UniqueKey] - це визначений атрибут Microsoft? чи варто це визначити сам?
Мохаммед Осман

Атрибут [UniqueKey] - це спеціальний атрибут, який я розробив для того, щоб дозволити додавання унікальних ключів у класах сущностей .cs (а не через метод OnModelCreating () DbContext)
Джастін Таббс

3
Це чудово. Чи можете ви, будь ласка, помістити код розробленого вами атрибута ?!
Мохаммед Осман


2

Для когось, хто намагається виконати всі ці рішення, але не працює, спробуйте це, він працював для мене

protected override void OnModelCreating(ModelBuilder builder)
{

    builder.Entity<User>().Property(t => t.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

}

2

Щоб використовувати його в ядрі EF через конфігурацію моделі

public class ApplicationCompanyConfiguration : IEntityTypeConfiguration<Company>
{
    public void Configure(EntityTypeBuilder<Company> builder)
    {
        builder.ToTable("Company"); 
        builder.HasIndex(p => p.Name).IsUnique();
    }
}

1

Жоден із цих методів не працював для мене в .NET Core 2.2, але мені вдалося адаптувати якийсь код, який я мав для визначення іншого основного ключа для роботи для цієї мети.

У наведеному нижче екземплярі я хочу переконатися, що поле OutletRef унікальне:

public class ApplicationDbContext : IdentityDbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Outlet>()
                .HasIndex(o => new { o.OutletRef });
        }
    }

Це додає необхідний унікальний індекс у базі даних. Однак це не дає можливості вказати спеціальне повідомлення про помилку.


0

Ми можемо додати унікальний індекс ключа, використовуючи вільне api. Нижче код працював для мене

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<User>().Property(p => p.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.