รหัส Entity Framework คอลัมน์แรกที่ไม่ซ้ำกัน


114

ฉันใช้ Entity Framework 4.3 และใช้ Code Fist

ฉันมีชั้นเรียน

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

ฉันจะบอก Entity Framework ได้อย่างไรว่า UserName ต้องไม่ซ้ำกันเมื่อสร้างตารางฐานข้อมูล ฉันต้องการใช้คำอธิบายประกอบข้อมูลแทนไฟล์กำหนดค่าถ้าเป็นไปได้

คำตอบ:


258

ใน Entity Framework 6.1+ คุณสามารถใช้แอตทริบิวต์นี้กับโมเดลของคุณ:

[Index(IsUnique=true)]

คุณสามารถค้นหาได้ในเนมสเปซนี้:

using System.ComponentModel.DataAnnotations.Schema;

หากฟิลด์โมเดลของคุณเป็นสตริงตรวจสอบให้แน่ใจว่าไม่ได้ตั้งค่าเป็น nvarchar (MAX) ใน SQL Server มิฉะนั้นคุณจะเห็นข้อผิดพลาดนี้กับ Entity Framework Code First:

คอลัมน์ 'x' ในตาราง 'dbo.y' เป็นประเภทที่ไม่ถูกต้องสำหรับใช้เป็นคอลัมน์หลักในดัชนี

สาเหตุเป็นเพราะสิ่งนี้:

SQL Server ยังคง จำกัด 900 ไบต์สำหรับขนาดรวมสูงสุดของคอลัมน์คีย์ดัชนีทั้งหมด "

(จาก: http://msdn.microsoft.com/en-us/library/ms191241.aspx )

คุณสามารถแก้ปัญหานี้ได้โดยตั้งค่าความยาวสตริงสูงสุดในแบบจำลองของคุณ:

[StringLength(450)]

โมเดลของคุณจะมีลักษณะเช่นนี้ใน EF CF 6.1+:

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

ปรับปรุง:

ถ้าคุณใช้ 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 } }));
    }
  }

และใช้ใน modelBuilder ของคุณ:

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

อัปเดต 2

สำหรับ EntityFrameworkCore โปรดดูหัวข้อนี้ด้วย: https://github.com/aspnet/EntityFrameworkCore/issues/1698

อัปเดต 3

สำหรับ EF6.2 โปรดดู: https://github.com/aspnet/EntityFramework6/issues/274

อัปเดต 4

ASP.NET Core Mvc 2.2 พร้อม EF Core:

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

23
ขอขอบคุณที่ตอบกลับโพสต์เก่าของผู้ชายคนนี้พร้อมข้อมูลปัจจุบันที่เกี่ยวข้อง!
Jim Yarbro

3
ทำไมต้องเป็นดัชนีทำไมไม่เป็นเพียงข้อ จำกัด ?
John Henckel

2
เพื่อตอบคำถาม index vs 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
บันทึก; ใน Entity Framework Core 1.0.0-preview2-final ไม่มีวิธีการใส่คำอธิบายประกอบข้อมูล - docs.efproject.net/th/latest/modeling/…
Edward Comeau

26

EF ไม่รองรับคอลัมน์เฉพาะยกเว้นคีย์ หากคุณใช้ EF Migrations คุณสามารถบังคับให้ EF สร้างดัชนีเฉพาะในUserNameคอลัมน์ (ในรหัสการย้ายข้อมูลไม่ใช่ด้วยคำอธิบายประกอบใด ๆ ) แต่ความเป็นเอกลักษณ์จะถูกบังคับใช้ในฐานข้อมูลเท่านั้น หากคุณพยายามบันทึกค่าที่ซ้ำกันคุณจะต้องตรวจจับข้อยกเว้น (การละเมิดข้อ จำกัด ) ที่ถูกไล่ออกจากฐานข้อมูล


1
นั่นคือสิ่งที่ฉันกำลังมองหา! ฉันสงสัยว่าจะเพิ่มข้อ จำกัด ดังกล่าวโดยใช้การย้ายข้อมูลได้หรือไม่
Alex Jorgenson

@Ladislav Mrnka: นี่เป็นไปได้ด้วยวิธี Seed หรือไม่?
Raheel Khan

2
สนใจที่จะให้ตัวอย่าง? ขอบคุณ!
Zero3

10

จากรหัสของคุณจะเห็นได้ชัดว่าคุณใช้ POCO การมีคีย์อื่นไม่จำเป็น: คุณสามารถเพิ่มดัชนีตามที่juFo แนะนำได้
หากคุณใช้ Fluent API แทนการกำหนดคุณสมบัติ UserName คำอธิบายประกอบคอลัมน์ของคุณควรมีลักษณะดังนี้:

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

สิ่งนี้จะสร้างสคริปต์ SQL ต่อไปนี้:

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]

หากคุณพยายามแทรกผู้ใช้หลายคนที่มี UserName เดียวกันคุณจะได้รับ DbUpdateException พร้อมข้อความต่อไปนี้:

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

อีกครั้งคำอธิบายประกอบคอลัมน์ไม่พร้อมใช้งานใน Entity Framework ก่อนเวอร์ชัน 6.1


สิ่งที่เกี่ยวกับการสร้างดัชนีที่มีหลายคอลัมน์โดยใช้การกำหนดค่า?
FindOutIslamNow

หนึ่งอยู่ใน UserName อีกอันคืออะไร?
Alexander Christov

5

โปรดทราบว่าใน Entity Framework 6.1 (ปัจจุบันอยู่ในรุ่นเบต้า) จะสนับสนุน IndexAttribute เพื่อใส่คำอธิบายประกอบคุณสมบัติดัชนีซึ่งจะส่งผลให้เกิดดัชนี (ไม่ซ้ำกัน) โดยอัตโนมัติในการโยกย้าย Code First ของคุณ



-13

โซลูชันสำหรับ EF4.3

ชื่อผู้ใช้เฉพาะ

เพิ่มคำอธิบายประกอบข้อมูลบนคอลัมน์เป็น:

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

รหัสเฉพาะ ฉันได้เพิ่มการตกแต่ง [คีย์] บนคอลัมน์ของฉันและทำเสร็จแล้ว โซลูชันเดียวกับที่อธิบายไว้ที่นี่: https://msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

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

คำตอบทางเลือก

โดยใช้คำอธิบายประกอบข้อมูล

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

โดยใช้การทำแผนที่

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

25
ระวังด้วยวิธีนี้ การเพิ่มKeyแอตทริบิวต์ให้กับUserNameคุณสมบัติจะทำให้UserNameคุณสมบัติกลายเป็นคีย์หลักในฐานข้อมูล เฉพาะUserIdคุณสมบัติควรถูกทำเครื่องหมายด้วยKeyแอตทริบิวต์ โซลูชันนี้จะทำให้คุณมีพฤติกรรมที่ 'ถูกต้อง' ในด้านการเขียนโปรแกรมในขณะที่ให้คุณออกแบบฐานข้อมูลที่ไม่ถูกต้อง
Alex Jorgenson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.