Mã Entity Framework cột duy nhất đầu tiên


114

Tôi đang sử dụng Entity Framework 4.3 và sử dụng Code Fist.

Tôi có một lớp học

public class User
{
   public int UserId{get;set;}
   public string UserName{get;set;}
}

Làm cách nào để nói với Entity Framework rằng UserName phải là duy nhất khi tạo bảng cơ sở dữ liệu? Tôi muốn sử dụng chú thích dữ liệu thay vì tệp cấu hình nếu có thể.

Câu trả lời:


257

Trong Entity Framework 6.1+, bạn có thể sử dụng thuộc tính này trên mô hình của mình:

[Index(IsUnique=true)]

Bạn có thể tìm thấy nó trong không gian tên này:

using System.ComponentModel.DataAnnotations.Schema;

Nếu trường mô hình của bạn là một chuỗi, hãy đảm bảo rằng nó không được đặt thành nvarchar (MAX) trong SQL Server hoặc bạn sẽ thấy lỗi này với Mã khung thực thể trước:

Cột 'x' trong bảng 'dbo.y' thuộc loại không hợp lệ để sử dụng làm cột khóa trong chỉ mục.

Lý do là vì điều này:

SQL Server giữ lại giới hạn 900 byte cho tổng kích thước tối đa của tất cả các cột khóa chỉ mục. "

(từ: http://msdn.microsoft.com/en-us/library/ms191241.aspx )

Bạn có thể giải quyết vấn đề này bằng cách đặt độ dài chuỗi tối đa trên mô hình của mình:

[StringLength(450)]

Mô hình của bạn bây giờ sẽ giống như thế này trong EF CF 6.1+:

public class User
{
   public int UserId{get;set;}
   [StringLength(450)]
   [Index(IsUnique=true)]
   public string UserName{get;set;}
}

Cập nhật:

nếu bạn sử dụng Fluent:

  public class UserMap : EntityTypeConfiguration<User>
  {
    public UserMap()
    {
      // ....
      Property(x => x.Name).IsRequired().HasMaxLength(450).HasColumnAnnotation("Index", new IndexAnnotation(new[] { new IndexAttribute("Index") { IsUnique = true } }));
    }
  }

và sử dụng trong modelBuilder của bạn:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  // ...
  modelBuilder.Configurations.Add(new UserMap());
  // ...
}

Cập nhật 2

cho EntityFrameworkCore xem thêm chủ đề này: https://github.com/aspnet/EntityFrameworkCore/issues/1698

Cập nhật 3

cho EF6.2, hãy xem: https://github.com/aspnet/EntityFramework6/issues/274

Cập nhật 4

ASP.NET Core Mvc 2.2 với EF Core:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }

23
Cảm ơn vì đã trả lời bài viết cũ của anh chàng này với một số thông tin hiện tại có liên quan!
Jim Yarbro

3
tại sao là một chỉ mục, tại sao không chỉ là một ràng buộc?
John Henckel

2
Để trả lời câu hỏi chỉ mục so với contraint ... MSDN: "There are no significant differences between creating a UNIQUE constraint and creating a unique index that is independent of a constraint. Data validation occurs in the same manner, and the query optimizer does not differentiate between a unique index created by a constraint or manually created. However, creating a UNIQUE constraint on the column makes the objective of the index clear." msdn.microsoft.com/en-us/library/ms187019.aspx
user919426

3
Ghi chú; trong Entity Framework Core 1.0.0-preview2-final, phương thức chú thích dữ liệu không khả dụng - docs.efproject.net/en/latest/modeling/…
Edward Comeau

26

EF không hỗ trợ các cột duy nhất ngoại trừ các khóa. Nếu bạn đang sử dụng EF Migrations, bạn có thể buộc EF tạo chỉ mục duy nhất trên UserNamecột (trong mã di chuyển, không phải bằng bất kỳ chú thích nào) nhưng tính duy nhất sẽ chỉ được thực thi trong cơ sở dữ liệu. Nếu bạn cố gắng lưu giá trị trùng lặp, bạn sẽ phải bắt ngoại lệ (vi phạm ràng buộc) do cơ sở dữ liệu kích hoạt.


1
Đó chính xác là những gì tôi đang tìm kiếm! Tôi đã tự hỏi liệu có thể thêm các ràng buộc như vậy bằng cách sử dụng di chuyển hay không.
Alex Jorgenson,

@Ladislav Mrnka: Điều này cũng có thể thực hiện được thông qua phương pháp Seed?
Raheel Khan

2
Bạn muốn cung cấp một ví dụ? Cảm ơn!
Zero3

10

Từ mã của bạn, rõ ràng là bạn sử dụng POCO. Có một khóa khác là không cần thiết: bạn có thể thêm một chỉ mục theo đề xuất của juFo .
Nếu bạn sử dụng Fluent API thay vì phân bổ thuộc tính UserName thì chú thích cột của bạn sẽ giống như sau:

this.Property(p => p.UserName)
    .HasColumnAnnotation("Index", new IndexAnnotation(new[] { 
        new IndexAttribute("Index") { IsUnique = true } 
    }
));

Thao tác này sẽ tạo tập lệnh SQL sau:

CREATE UNIQUE NONCLUSTERED INDEX [Index] ON [dbo].[Users]
(
    [UserName] ASC
)
WITH (
    PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    SORT_IN_TEMPDB = OFF, 
    IGNORE_DUP_KEY = OFF, 
    DROP_EXISTING = OFF, 
    ONLINE = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]

Nếu bạn cố gắng chèn nhiều Người dùng có cùng Tên người dùng, bạn sẽ nhận được DbUpdateException với thông báo sau:

Cannot insert duplicate key row in object 'dbo.Users' with unique index 'Index'. 
The duplicate key value is (...).
The statement has been terminated.

Một lần nữa, chú thích cột không có sẵn trong Entity Framework trước phiên bản 6.1.


Còn việc tạo chỉ mục với nhiều cột khác nhau bằng cách sử dụng cấu hình thì sao?
FindOutIslamNow

Một trên UserName, cái còn lại là gì?
Alexander Christov

5

Lưu ý rằng trong Entity Framework 6.1 (hiện đang ở phiên bản beta) sẽ hỗ trợ IndexAttribute để chú thích các thuộc tính chỉ mục sẽ tự động dẫn đến một chỉ mục (duy nhất) trong Code First Migrations của bạn.


2

Trong EF 6.2 sử dụng FluentAPI , bạn có thể sử dụngHasIndex()

modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();

-13

Giải pháp cho EF4.3

Tên người dùng duy nhất

Thêm chú thích dữ liệu trên cột dưới dạng:

 [Index(IsUnique = true)]
 [MaxLength(255)] // for code-first implementations
 public string UserName{get;set;}

ID duy nhất , tôi đã thêm trang trí [Key] trên cột của mình và xong. Giải pháp tương tự như được mô tả tại đây: https://msdn.microsoft.com/en-gb/data/jj591583.aspx

I E:

[Key]
public int UserId{get;set;}

Câu trả lời thay thế

sử dụng chú thích dữ liệu

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("UserId")]

sử dụng bản đồ

  mb.Entity<User>()
            .HasKey(i => i.UserId);
        mb.User<User>()
          .Property(i => i.UserId)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
          .HasColumnName("UserId");

25
Hãy cẩn thận với giải pháp này. Việc thêm Keythuộc tính vào thuộc tính UserNamesẽ khiến thuộc UserNametính trở thành khóa chính trong cơ sở dữ liệu. Chỉ thuộc UserIdtính nên được đánh dấu bằng Keythuộc tính. Giải pháp này sẽ cung cấp cho bạn hành vi 'đúng' về mặt lập trình trong khi cung cấp cho bạn một thiết kế cơ sở dữ liệu không chính xác.
Alex Jorgenson.
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.