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 คล่องสำหรับดัชนีดูที่learnentityframeworkcore.com/configuration/fluent-api/...
ไมเคิล Freidgeim

คำตอบ:


301

ใน EF core คุณไม่สามารถสร้างดัชนีโดยใช้คำอธิบายประกอบข้อมูล แต่คุณสามารถทำได้โดยใช้ Fluent API

เช่นนี้ภายในของคุณ{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
ขอบคุณมากสำหรับความช่วยเหลือของคุณมันเป็นทางออกที่ถูกต้อง!
Vadim M

ในกรณีที่มีคนมาที่นี่เพื่อหาทางออกที่ใช้งานได้เมื่อใช้ MS Identity schema ฉันขอแนะนำให้ตั้งค่าข้อ จำกัด ที่ไม่ซ้ำกันในฟิลด์ NormalizedEmail ไม่ใช่อีเมล (ของเอนทิตี AspNetUsers) การใช้ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่อาจล้มเหลวในการละเมิดข้อ จำกัด แม้ว่าจะเป็นที่อยู่อีเมลเดียวกันทั้งนี้ขึ้นอยู่กับการตั้งค่าการเรียงชุดของ db
Tom

4
รหัสนี้จะไม่ทำงานสำหรับคอลัมน์ประเภทสตริง :( มีวิธีใดที่จะเพิ่มข้อ จำกัด ที่ไม่ซ้ำกันในคอลัมน์สตริง?
Johar Zaman

ไปกันเลยHasAlternateKey
Chamika Sandamal

1
ฉันลองสิ่งนี้เมื่อฉันกำลังทำสิ่งนี้ แต่ตอนนี้ฉันไม่จำเป็นต้องใช้สิ่งนี้ Btw ขอบคุณสำหรับความคิดเห็นของคุณ @Sampath
Johar Zaman

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


11
อ้างอิงจาก EF Core docs: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: docs.microsoft.com/en-us/ef/core/modeling/ ......
granadaCoder

3

OP กำลังถามว่าเป็นไปได้หรือไม่ที่จะเพิ่มแอททริบิวไปยังคลาสเอนทิตีสำหรับคีย์เฉพาะ คำตอบสั้น ๆ คือเป็นไปได้ แต่ไม่ใช่คุณสมบัตินอกกรอบจากทีม EF Core หากคุณต้องการใช้แอททริบิวเพื่อเพิ่มคีย์ที่ไม่ซ้ำให้กับคลาสเอนทิตี้ของ 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? หรือใครควรนิยามมันด้วยตัวเอง?
โมฮัมเหม็ด Osman

[UniqueKey] แอตทริบิวต์เป็นแอตทริบิวต์ที่กำหนดเองที่ผมได้พัฒนาเพื่อเปิดใช้งานนอกเหนือจากปุ่มที่ไม่ซ้ำกันภายในชั้นเรียน .cs นิติบุคคล (และไม่ผ่าน DbContext ของ OnModelCreating () วิธีการ)
จัสติน Tubbs

3
เยี่ยมมาก คุณกรุณาใส่รหัสของแอตทริบิวต์ที่คุณกำหนดเองได้ไหม!
โมฮัมเหม็ด Osman


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 core ผ่านการกำหนดค่ารุ่น

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

    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.