Entity Framework Core menambahkan kode kendala unik-pertama

152

Saya tidak dapat menemukan cara untuk menambahkan batasan unik ke bidang saya dengan menggunakan atribut:

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; }
}

Saya menggunakan paket-paket ini:

 "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",
Vadim M
sumber
Sampel Fluent
Michael Freidgeim

Jawaban:

301

Pada inti EF Anda tidak dapat membuat Indeks menggunakan anotasi data. Namun Anda dapat melakukannya menggunakan Fluent API.

Seperti ini di dalam diri Anda {Db}Context.cs:

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

... atau jika Anda menggunakan kelebihan dengan buildAction:

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

Anda dapat membaca lebih lanjut tentang ini di sini: Indeks

Sampath
sumber
1
Terima kasih banyak atas bantuan Anda, ini solusi yang tepat!
Vadim M
Jika seseorang datang ke sini mencari solusi yang berfungsi saat menggunakan skema MS Identity, saya sarankan untuk menetapkan batasan unik pada bidang NormalizedEmail, bukan Email (dari entitas AspNetUsers). Menggunakan case yang berbeda mungkin gagal melanggar batasan bahkan jika alamat emailnya sama, tergantung pada pengaturan collation dari db.
Tom
4
Kode ini tidak berfungsi untuk kolom tipe string :( Apakah ada cara untuk menambahkan batasan unik pada kolom string?
Johar Zaman
Go forHasAlternateKey
Chamika Sandamal
1
Saya mencoba ini ketika saya sedang mengerjakan ini tetapi sekarang saya tidak perlu mengimplementasikan ini. Terima kasih atas komentar Anda. @Sampath
Johar Zaman
70

Juga jika Anda ingin membuat batasan unik pada beberapa kolom, Anda cukup melakukan ini (mengikuti tautan @Sathath )

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; }
}
Hossein Narimani Rad
sumber
9

Solusi untuk 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})
    }
}

Tabel DB akan terlihat seperti ini:

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)
);

Rujuk ke dokumen EF Core

Evgeniy Miroshnichenko
sumber
11
Menurut dokumen 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
Referensi komentar bigworld12
granadaCoder
3

OP bertanya tentang apakah mungkin untuk menambahkan atribut ke kelas Entitas untuk Kunci Unik. Jawaban singkatnya adalah bahwa hal itu mungkin, tetapi bukan fitur yang tidak biasa dari Tim Inti EF. Jika Anda ingin menggunakan Atribut untuk menambahkan Kunci Unik ke kelas entitas Inti Entitas Kerangka Anda, Anda bisa melakukan apa yang saya posting di sini

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; }
}
Justin Tubbs
sumber
Atribut [UniqueKey] adalah atribut yang ditentukan oleh Microsoft? atau orang harus mendefinisikannya sendiri?
Mohammed Osman
Atribut [UniqueKey] adalah Atribut khusus yang telah saya kembangkan untuk mengaktifkan penambahan kunci unik dalam kelas entitas .cs (dan tidak melalui metode OnModelCreating () DbContext)
Justin Tubbs
3
Itu hebat. Bisakah Anda meletakkan kode atribut khusus yang Anda kembangkan ?!
Mohammed Osman
2

Untuk seseorang yang mencoba semua solusi ini tetapi tidak berhasil coba yang ini, itu berhasil untuk saya

protected override void OnModelCreating(ModelBuilder builder)
{

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

}
Shonie
sumber
2

Untuk menggunakannya di inti EF melalui konfigurasi model

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

Tak satu pun dari metode ini bekerja untuk saya di .NET Core 2.2 tetapi saya dapat mengadaptasi beberapa kode yang saya miliki untuk mendefinisikan kunci primer yang berbeda untuk bekerja untuk tujuan ini.

Dalam contoh di bawah ini saya ingin memastikan bidang OutletRef unik:

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

Ini menambahkan indeks unik yang diperlukan dalam database. Yang tidak dilakukannya adalah menyediakan kemampuan untuk menentukan pesan kesalahan khusus.

Robin Wilson
sumber
0

Kami dapat menambahkan indeks kunci unik dengan menggunakan api fasih. Kode di bawah ini berfungsi untuk saya

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

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

    }
Kuldeep Singh
sumber