การตั้งค่าข้อ จำกัด เฉพาะด้วย API อย่างคล่องแคล่ว?


185

ฉันพยายามสร้าง EF Entity ด้วย Code First และEntityTypeConfigurationใช้ API อย่างคล่องแคล่ว การสร้างคีย์หลักนั้นง่าย แต่ไม่ได้ จำกัด เฉพาะด้วยข้อ จำกัด ที่ไม่เหมือนใคร ฉันเห็นโพสต์เก่าที่แนะนำให้เรียกใช้งานคำสั่ง SQL ดั้งเดิมสำหรับสิ่งนี้ แต่ดูเหมือนจะเอาชนะวัตถุประสงค์ได้ เป็นไปได้กับ EF6

คำตอบ:


275

บนEF6.2คุณสามารถใช้HasIndex()เพื่อเพิ่มดัชนีสำหรับการย้ายข้อมูลผ่าน API ได้อย่างคล่องแคล่ว

https://github.com/aspnet/EntityFramework6/issues/274

ตัวอย่าง

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

ในEF6.1เป็นต้นไปคุณสามารถใช้IndexAnnotation()เพื่อเพิ่มดัชนีสำหรับการย้ายข้อมูลใน API ได้อย่างคล่องแคล่ว

http://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex

คุณต้องเพิ่มการอ้างอิงถึง:

using System.Data.Entity.Infrastructure.Annotations;

ตัวอย่างพื้นฐาน

นี่คือการใช้งานง่ายเพิ่มดัชนีในUser.FirstNameคุณสมบัติ

modelBuilder 
    .Entity<User>() 
    .Property(t => t.FirstName) 
    .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));

ตัวอย่างการปฏิบัติ:

นี่เป็นตัวอย่างที่สมจริงมากขึ้น มันจะเพิ่มดัชนีที่ไม่ซ้ำกับคุณสมบัติหลายประการ: User.FirstNameและUser.LastNameด้วยชื่อดัชนี "IX_FirstNameLastName"

modelBuilder 
    .Entity<User>() 
    .Property(t => t.FirstName) 
    .IsRequired()
    .HasMaxLength(60)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(
            new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true }));

modelBuilder 
    .Entity<User>() 
    .Property(t => t.LastName) 
    .IsRequired()
    .HasMaxLength(60)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(
            new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));

4
สิ่งนี้จำเป็นสำหรับการตั้งชื่อกำกับคำอธิบายประกอบคอลัมน์เป็น "ดัชนี"! ฉันเขียนชื่ออื่นและใช้งานไม่ได้! ฉันใช้เวลาหลายชั่วโมงก่อนจะลองเปลี่ยนชื่อเป็น "ดัชนี" ดั้งเดิมในโพสต์ของคุณและเข้าใจว่าสิ่งนี้สำคัญ :( จะต้องมีค่าคงที่ในกรอบเพื่อไม่ให้รหัสสตริงยาก
Alexander Vasilyev

10
@AlexanderVasilyev ค่าคงที่หมายถึงIndexAnnotation.AnnotationName
Nathan

3
@ นาธานขอบคุณ! แค่นั้นแหละ! ตัวอย่างในโพสต์นี้ต้องได้รับการแก้ไขโดยใช้ค่าคงที่นี้
Alexander Vasilyev

2
ไม่สามารถหาได้ใน EF7 - DNX
Shimmy Weitzhandler

2
ฉันเชื่อว่าจำเป็นต้องตั้งค่า IsUnique เป็นจริงเมื่อสร้าง IndexAttribute ในตัวอย่างแรก new IndexAttribute() { IsUnique = true }เช่นนี้ มิฉะนั้นจะสร้างดัชนีปกติ (ไม่ซ้ำกัน)
jakubka

134

นอกเหนือจากคำตอบของ Yorro แล้วยังสามารถทำได้โดยใช้แอตทริบิวต์

ตัวอย่างสำหรับการintรวมคีย์ที่เป็นเอกลักษณ์:

[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }

[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }

หากชนิดข้อมูลstringนั้นMaxLengthจะต้องเพิ่มแอตทริบิวต์:

[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }

[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }

หากมีข้อกังวลเรื่องการแยกโดเมน / หน่วยเก็บข้อมูลการใช้Metadatatypeคุณสมบัติ / คลาสสามารถเป็นตัวเลือก: https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx?f= 255 & MSPPError = -2147217396


ตัวอย่างแอปคอนโซลด่วน:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;

namespace EFIndexTest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new AppDbContext())
            {
                var newUser = new User { UniqueKeyIntPart1 = 1, UniqueKeyIntPart2 = 1, UniqueKeyStringPart1 = "A", UniqueKeyStringPart2 = "A" };
                context.UserSet.Add(newUser);
                context.SaveChanges();
            }
        }
    }

    [MetadataType(typeof(UserMetadata))]
    public class User
    {
        public int Id { get; set; }
        public int UniqueKeyIntPart1 { get; set; }
        public int UniqueKeyIntPart2 { get; set; }
        public string UniqueKeyStringPart1 { get; set; }
        public string UniqueKeyStringPart2 { get; set; }
    }

    public class UserMetadata
    {
        [Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
        public int UniqueKeyIntPart1 { get; set; }

        [Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
        public int UniqueKeyIntPart2 { get; set; }

        [Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
        [MaxLength(50)]
        public string UniqueKeyStringPart1 { get; set; }

        [Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
        [MaxLength(50)]
        public string UniqueKeyStringPart2 { get; set; }
    }

    public class AppDbContext : DbContext
    {
        public virtual DbSet<User> UserSet { get; set; }
    }
}

45
ไม่ใช่ถ้าคุณต้องการแยกรุ่นโดเมนของคุณออกจากความกังวลเรื่องพื้นที่จัดเก็บ
Rickard Liljeberg

4
คุณต้องแน่ใจว่าคุณมีการอ้างอิงถึง EntityFramework
Michael Tranchida

2
จะดีถ้าแอตทริบิวต์ดัชนีถูกแยกออกจาก Entity Framework เพื่อให้ฉันสามารถรวมไว้ในโครงการรุ่นของฉัน ฉันเข้าใจว่ามันเป็นเรื่องที่เกี่ยวกับการจัดเก็บ แต่เหตุผลหลักที่ฉันใช้มันคือการวางข้อ จำกัด ที่ไม่ซ้ำกันในสิ่งต่าง ๆ เช่นชื่อผู้ใช้และชื่อบทบาท
Sam

2
ไม่สามารถหาได้ใน EF7 - DNX
Shimmy Weitzhandler

4
ใช้งานได้เฉพาะในกรณีที่คุณจำกัดความยาวของสตริงด้วยเนื่องจาก SQL ไม่อนุญาตให้ใช้nvarchar (สูงสุด)เป็นคีย์
JMK

17

นี่คือวิธีการขยายสำหรับการตั้งค่าดัชนีที่ไม่ซ้ำกันอย่างคล่องแคล่วมากขึ้น

public static class MappingExtensions
{
    public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
    {
        return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
    }
}

การใช้งาน:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name)
    .IsUnique();

จะสร้างการโยกย้ายเช่น:

public partial class Add_unique_index : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Person", "Name", unique: true);
    }

    public override void Down()
    {
        DropIndex("dbo.Person", new[] { "Name" });
    }
}

src: การสร้างดัชนีที่ไม่ซ้ำกับ API คล่องแคล่ว Framework 6.1 Entity


16

คำตอบของ @ coni2k นั้นถูกต้อง แต่คุณต้องเพิ่มแอ[StringLength]ททริบิวให้ทำงานมิฉะนั้นคุณจะได้รับข้อยกเว้นคีย์ที่ไม่ถูกต้อง (ตัวอย่างซอลเบลโลว์)

[StringLength(65)]
[Index("IX_FirstNameLastName", 1, IsUnique = true)]
public string FirstName { get; set; }

[StringLength(65)]
[Index("IX_FirstNameLastName", 2, IsUnique = true)]
public string LastName { get; set; }


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