วิธีสร้างดัชนีใน Entity Framework 6.2 ด้วยโค้ดก่อน


112

มีวิธีสร้างดัชนีบนคุณสมบัติ / คอลัมน์โดยใช้รหัสก่อนแทนที่จะใช้ใหม่IndexAttributeหรือไม่?


5
ดัชนีเป็นแนวคิดฐานข้อมูลไม่ใช่แนวคิดแบบจำลองเอนทิตี แม้ว่าคุณจะระบุดัชนีด้วยแอตทริบิวต์หรือผ่าน API ที่คล่องแคล่ว แต่ก็ไม่ได้ทำอะไรเลยในแอปพลิเคชันของคุณ มันเป็นเพียงคำสั่งสำหรับ EF ที่จะใช้เมื่อสร้างฐานข้อมูล ฉันเชื่อว่าคำแนะนำดังกล่าวอยู่ในการย้ายรหัสก่อนซึ่งเกี่ยวข้องกับการจัดการสคีมาฐานข้อมูลอย่างสิ้นเชิง
JC Ford

คำตอบ:


84

ดี 2017/10/26 Entity Framework 6.2 ถูกปล่อยออกมาอย่างเป็นทางการ รวมถึงความเป็นไปได้ในการกำหนดดัชนีได้อย่างง่ายดายผ่าน Fluent API โฮมันคือการใช้งานได้ประกาศไปแล้วในเบต้า 6.2

ตอนนี้คุณสามารถใช้HasIndex()วิธีการตามด้วยIsUnique()ถ้ามันควรจะเป็นดัชนีที่ไม่ซ้ำ

ตัวอย่างการเปรียบเทียบเล็กน้อย (ก่อน / หลัง):

// before 
modelBuilder.Entity<Person>()
        .Property(e => e.Name)
        .HasColumnAnnotation(
            IndexAnnotation.AnnotationName, 
            new IndexAnnotation(new IndexAttribute { IsUnique = true }));

// after
modelBuilder.Entity<Person>()
    .HasIndex(p => p.Name)
    .IsUnique();

// multi column index
modelBuilder.Entity<Person>()
    .HasIndex(p => new { p.Name, p.Firstname })
    .IsUnique();

.IsClustered()นอกจากนี้ยังเป็นไปได้ที่จะทำเครื่องหมายดัชนีเป็นคลัสเตอร์กับ


แก้ไข # 1

เพิ่มตัวอย่างสำหรับดัชนีหลายคอลัมน์และข้อมูลเพิ่มเติมในการทำเครื่องหมายดัชนีเป็นคลัสเตอร์


แก้ไข # 2

ตามข้อมูลเพิ่มเติมใน EF Core 2.1 ตอนนี้เหมือนกับใน EF 6.2 ทุกประการ
นี่คือไฟล์แนบ MS Doc เป็นข้อมูลอ้างอิง


นี่มันเยี่ยมมาก! ฉันคิดว่าถ้าฉันมีดัชนีหลายคอลัมน์มันจะเป็นดังนี้: .HasIndex (p => new {p.Name, p.Xyz})
Valo

อ๋อขอโทษแน่ ๆ newมันควรจะเป็น ฉันจะซ่อมมัน.
ชว

คุณช่วยแสดงวิธีเขียนโค้ดเดียวกันใน Core 2.x ได้อย่างไร?
user3417479

เท่าที่ฉันรู้ว่าควรเป็นรหัสเดียวกันกับที่แสดงใน "after" และ "multi column index"
ChW

87

ขณะนี้ไม่มี"การสนับสนุนชั้นหนึ่ง"สำหรับการสร้างดัชนีผ่านทาง API ที่คล่องแคล่ว แต่สิ่งที่คุณทำได้คือผ่าน API ที่คล่องแคล่วคุณสามารถทำเครื่องหมายคุณสมบัติว่ามีแอตทริบิวต์จาก Annotation API สิ่งนี้จะช่วยให้คุณสามารถเพิ่มIndexแอตทริบิวต์ผ่านอินเทอร์เฟซที่คล่องแคล่ว

นี่คือตัวอย่างบางส่วนจากรายการงานจากไซต์ปัญหาสำหรับ EF

สร้างดัชนีในคอลัมน์เดียว:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new IndexAttribute()));

ดัชนีหลายรายการในคอลัมน์เดียว:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new[]
            {
                new IndexAttribute("Index1"),
                new IndexAttribute("Index2") { IsUnique = true }
            }));

ดัชนีหลายคอลัมน์:

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty1)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(new IndexAttribute("MyIndex", 1)));

modelBuilder.Entity<MyEntity>()
    .Property(e => e.MyProperty2)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName, 
        new IndexAnnotation(new IndexAttribute("MyIndex", 2)));

การใช้เทคนิคข้างต้นจะทำให้การ.CreateIndex()โทรถูกสร้างขึ้นโดยอัตโนมัติสำหรับคุณในUp()ฟังก์ชันของคุณเมื่อคุณนั่งร้านการย้ายข้อมูลครั้งต่อไป (หรือสร้างขึ้นโดยอัตโนมัติในฐานข้อมูลหากคุณไม่ได้ใช้การย้ายข้อมูล)


4
ที่อาจเพิ่มดัชนีในคอลัมน์ แต่จะไม่ลบดัชนีคลัสเตอร์ที่สร้างบนคีย์หลัก hasKey สร้างดัชนีคลัสเตอร์บนคีย์หลักซึ่งไม่ได้ถูกลบออกโดยค่าเริ่มต้น ที่ต้องถูกลบออกอย่างชัดเจนจากไฟล์การโอนย้ายที่สร้างขึ้นโดยระบุ clusered: false in .Primarykey(x=>x.id,clustered:false)method
Joy

8
ฉันลองใช้HasAnnotationวิธีนี้แล้วและไม่มีวิธีการเช่นนี้ แต่ฉันพบวิธีการที่ชื่อHasColumnAnnotationซึ่งยอมรับพารามิเตอร์ที่คุณระบุ คุณต้องอัปเดตคำตอบของคุณหรือฉันผิด?
Hakan Fıstık

@HakamFostok ฉันเอาตัวอย่างมาจากเว็บไซต์ EF โดยตรง บางทีอาจมีการเปลี่ยนชื่อในเวอร์ชันใดเวอร์ชันหนึ่งหรือมีการพิมพ์ผิดในเวอร์ชันดั้งเดิม
Scott Chamberlain

3
ดูด้านล่างของลิงก์ต่อไปนี้จากการประชุมออกแบบเมื่อต้นปีนี้: "เปลี่ยนชื่อ HasAnnotation เป็น HasColumnAnnotation (รวมถึงตำแหน่งอื่น ๆ ที่เกี่ยวข้องในฐานรหัส)" entityframework.codeplex.com/…
Zac Charles

36

ฉันได้สร้างวิธีการขยายบางอย่างและรวมไว้ในแพ็คเกจนักเก็ตเพื่อให้ง่ายขึ้นมาก

ติดตั้งEntityFramework.IndexingExtensionsแพคเกจ nuget

จากนั้นคุณสามารถทำสิ่งต่อไปนี้:

public class MyDataContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<Customer>()
        .HasIndex("IX_Customers_Name",          // Provide the index name.
            e => e.Property(x => x.LastName),   // Specify at least one column.
            e => e.Property(x => x.FirstName))  // Multiple columns as desired.

        .HasIndex("IX_Customers_EmailAddress",  // Supports fluent chaining for more indexes.
            IndexOptions.Unique,                // Supports flags for unique and clustered.
            e => e.Property(x => x.EmailAddress)); 
  }
}

โครงการและรหัสที่มาอยู่ที่นี่ สนุก!


ฉันชอบแพ็คเกจนี้มาก แต่ดูเหมือนว่าบางครั้งชื่อดัชนีจะหายไปหลังจากนั่งร้านในสคริปต์ขึ้น มันปรากฏให้ฉันเห็นเมื่อใช้คุณสมบัติ 4 อย่างขึ้นไปในดัชนีของฉัน ฉันกำลังทำงานกับ EF 6.1.3
Mixxiphoid

@Mixxiphoid - คุณช่วยบันทึกปัญหาที่นี่พร้อมรายละเอียดสนับสนุนได้ไหม ตรวจสอบให้แน่ใจว่าคุณมีเวอร์ชัน 1.0.1 เนื่องจากมีข้อบกพร่องใน 1.0.0
Matt Johnson-Pint

ฉันมีเวอร์ชัน 1.0.1 ฉันจะบันทึกปัญหา แต่ไม่สามารถทำได้ในขณะนี้
Mixxiphoid

ฉันจะเพิ่มลำดับคอลัมน์ที่เข้าร่วมดัชนีจากมากไปหาน้อยได้อย่างไร โดยค่าเริ่มต้น. HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... จะสร้างลำดับจากน้อยไปหามากสำหรับคอลัมน์ที่เข้าร่วมทั้งหมดในดัชนี
GDroid

@GDroid - น่าเสียดายที่IndexAttributeคลาสของ EF ไม่ได้เปิดเผยดังนั้นฉันจึงไม่สามารถรวมไว้ในห้องสมุดของฉันได้
Matt Johnson-Pint

24

ไม่มีชื่อที่ชัดเจน:

[Index]
public int Rating { get; set; } 

ด้วยชื่อเฉพาะ:

[Index("PostRatingIndex")] 
public int Rating { get; set; }

ดัชนีดูเหมือนจะถูกกีดกัน :(
Hamed Zakery Miab

1
@HamedZakeryMiab คุณกำลังใช้ Entity Framework รุ่นไหน? ดัชนีไม่ได้เลิกใช้งาน
Hugo Hilário

EntityFrameworkขอโทษนะที่ฉันลืมที่จะรวมถึง มันรวมอยู่ในชุดประกอบนั้น สับสนเกี่ยวกับ NS
Hamed Zakery Miab

@ HamedZakeryMiab ใช่มันสับสนสุด ๆ ! ฉันคิดว่ามันเป็นส่วนหนึ่งของ System.DataAnnotations! เป็นแพ็คเกจกรอบงานเอนทิตีแน่นอน
AlbatrossCafe

3
คำถามมีข้อความต่อไปนี้instead of using the new IndexAttributeคุณสังเกตเห็นหรือไม่
Hakan Fıstık

22

ตั้งแต่ EF 6.1 เป็นต้นไป[Index]จะรองรับแอตทริบิวต์
ใช้[Index(IsUnique = true)]สำหรับดัชนีเฉพาะ
นี่คือลิงค์จาก Microsoft

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

    [Index(IsUnique = true)] 
    [StringLength(200)] 
    public string Username { get; set; } 

    public string DisplayName { get; set; } 
}

2
ในขณะนี้อาจตอบคำถามในทางทฤษฎีได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์สำหรับการอ้างอิง
Enamul Hassan

@manetsus ดีมาก. ฉันได้เพิ่มข้อมูลโค้ดเพื่อแสดงถึงการเปลี่ยนแปลง
Darie Dorlus

3
จำเป็นต้องมีความยาวสตริงมิฉะนั้นคุณจะเห็น "เป็นประเภทที่ไม่ถูกต้องสำหรับใช้เป็นคอลัมน์หลักในดัชนี" ข้อยกเว้น เพื่อนร่วมงานของฉันชอบโซลูชัน modelBuilder บน Conntext เพื่อให้คุณไม่เกะกะคลาส User ของคุณซึ่งฉันคิดว่าใช้ได้
andrew pate

สิ่งที่เกี่ยวกับดัชนีที่มีหลายคอลัมน์เพื่อความเป็นเอกลักษณ์? เป็นเรื่องธรรมดาที่จะมีดัชนีคีย์เฉพาะแบบหลายคอลัมน์ ...
enorl76

1
@ enorl76 นั่นยังได้รับการสนับสนุน สำหรับแต่ละคอลัมน์คุณจะต้องใช้แอตทริบิวต์ดังต่อไปนี้ [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } อ้างอิงจากMicrosoft
Darie Dorlus

8

กรอบเอนทิตี 6

Property(c => c.MyColumn)
        .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_MyIndex")));

และเพิ่มโดยใช้:

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

7

3
ความยาวคีย์สูงสุดคือ 900 ไบต์สำหรับ nvarchar และ 450 ไบต์สำหรับ varchar หากคุณใช้โค้ดก่อนคุณสมบัติสตริงจะเป็น nvarchar และคุณควรรวมแอตทริบิวต์ "StringLength" ไว้ใน [[StringLength (450)]
dunwan

สำหรับ EF 6.1 นี่คือคำตอบที่ถูกต้อง docs.microsoft.com/en-us/ef/ef6/modeling/code-first/…
Chris Schaller

2

หากคุณไม่ต้องการใช้แอตทริบิวต์ใน POCO ของคุณคุณสามารถทำได้ดังต่อไปนี้:

context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ..."); 

คุณสามารถเรียกใช้คำสั่งนี้ในDbInitializerคลาสที่ได้รับแบบกำหนดเองของคุณ ฉันไม่รู้วิธีการใช้ Fluent API ในการทำสิ่งนี้


1
แน่นอนครับคุณ Mert ในขณะนี้ฉันใช้การย้ายข้อมูลและในวิธีการ Up () คุณยังสามารถใส่: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") และใน Down () DropIndex (("dbo.Table1 "," Column1_IX ") ฉันแค่หวังว่าพวกเขาจะเพิ่ม API ที่คล่องแคล่วด้วย ...
Valo

1

ฉันเขียนวิธีการขยายเพื่อใช้ใน EF อย่างคล่องแคล่วเพื่อหลีกเลี่ยงโค้ดพิเศษ:

public static PrimitivePropertyConfiguration HasIndexAnnotation(
    this PrimitivePropertyConfiguration primitivePropertyConfiguration, 
    IndexAttribute indexAttribute = null
    )
{
    indexAttribute = indexAttribute ?? new IndexAttribute();

    return primitivePropertyConfiguration
        .HasColumnAnnotation(
            IndexAnnotation.AnnotationName, 
            new IndexAnnotation(indexAttribute)
        );
}

จากนั้นใช้มันดังนี้:

Property(t => t.CardNo)
    .HasIndexAnnotation();

หรือเช่นนี้หากดัชนีต้องการการกำหนดค่าบางอย่าง:

Property(t => t.CardNo)
    .HasIndexAnnotation(new IndexAttribute("IX_Account") { IsUnique = true });

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