Entity Framework Core thêm mã ràng buộc duy nhất trước tiên


152

Tôi không thể tìm cách thêm một ràng buộc duy nhất vào trường của mình bằng cách sử dụng thuộc tính:

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

Tôi đang sử dụng các gói này:

 "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",

Các mẫu Api thông thạo cho các chỉ mục nhìn thấy tại learnentityframeworkcore.com/configuration/fluent-api/ mẹo
Michael Freidgeim

Câu trả lời:


301

Trên lõi EF, bạn không thể tạo Chỉ mục bằng cách sử dụng chú thích dữ liệu. Nhưng bạn có thể làm điều đó bằng API Fluent.

Như thế này bên trong của bạn {Db}Context.cs:

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

... hoặc nếu bạn đang sử dụng quá tải với buildAction:

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

Bạn có thể đọc thêm về nó ở đây: Chỉ mục


1
Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn, đó là giải pháp đúng đắn!
Vadim M

Trong trường hợp ai đó hạ cánh ở đây để tìm giải pháp hoạt động khi sử dụng lược đồ Nhận dạng MS, tôi khuyên bạn nên đặt ràng buộc duy nhất trên trường NormalizedEmail, không phải Email (của thực thể AspNetUsers). Sử dụng các trường hợp khác nhau có thể không vi phạm ràng buộc ngay cả khi đó là cùng một địa chỉ email, tùy thuộc vào cài đặt đối chiếu của db.
Tom

4
Mã này không hoạt động đối với cột kiểu chuỗi :( Có cách nào để thêm ràng buộc duy nhất vào cột chuỗi không?
Johar Zaman

Đi choHasAlternateKey
Chamika Sandamal

1
Tôi đã thử điều này khi tôi đang làm việc này nhưng bây giờ tôi không cần phải thực hiện điều này. Btw Cảm ơn bạn đã bình luận của bạn. @Sampath
Johar Zaman

70

Ngoài ra, nếu bạn muốn tạo các ràng buộc duy nhất trên nhiều cột, bạn chỉ cần thực hiện việc này (theo liên kết của @ 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

Giải pháp cho 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})
    }
}

Bảng DB sẽ trông như thế này:

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

Tham khảo tài liệu của EF Core


11
Theo tài liệu của 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 21/07/18

Tham khảo bình luận của bigworld12: docs.microsoft.com/en-us/ef/core/modeling/ mẹo
granadaCoder

3

OP đang hỏi về việc có thể thêm Thuộc tính vào lớp Thực thể cho Khóa duy nhất hay không. Câu trả lời ngắn gọn là nó có thể, nhưng không phải là một tính năng vượt trội từ Nhóm EF Core. Nếu bạn muốn sử dụng Thuộc tính để thêm Khóa duy nhất vào các lớp thực thể Core Entity Framework, bạn có thể làm những gì tôi đã đăng ở đây

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

Thuộc tính [UniqueKey] là thuộc tính được xác định bởi Microsoft? hoặc người ta nên tự xác định nó?
Mohammed Osman

Thuộc tính [UniqueKey] là Thuộc tính tùy chỉnh mà tôi đã phát triển để cho phép thêm các khóa duy nhất trong các lớp thực thể .cs (chứ không phải thông qua phương thức OnModelCreating () của DbContext)
Justin Tubbs

3
Thật tuyệt. Bạn có thể vui lòng đặt mã của thuộc tính tùy chỉnh mà bạn đã phát triển không?!
Mohammed Osman


2

Đối với một người đang thử tất cả các giải pháp này nhưng không hoạt động, hãy thử giải pháp này, nó hiệu quả với tôi

protected override void OnModelCreating(ModelBuilder builder)
{

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

}

2

Để sử dụng nó trong lõi EF thông qua cấu hình mô hình

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

1

Không có phương pháp nào trong số này làm việc cho tôi trong .NET Core 2.2 nhưng tôi có thể điều chỉnh một số mã tôi có để xác định khóa chính khác để hoạt động cho mục đích này.

Trong ví dụ bên dưới, tôi muốn đảm bảo trường OutletRef là duy nhất:

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

Điều này thêm chỉ mục duy nhất cần thiết trong cơ sở dữ liệu. Những gì nó không làm mặc dù là cung cấp khả năng chỉ định một thông báo lỗi tùy chỉnh.


0

Chúng tôi có thể thêm chỉ mục khóa duy nhất bằng cách sử dụng api trôi chảy. Mã dưới đây làm việc cho tôi

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

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

    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.