Cách tạo chỉ mục trong Entity Framework 6.2 bằng mã trước


112

Có cách nào để tạo chỉ mục trên thuộc tính / cột bằng cách sử dụng mã đầu tiên, thay vì sử dụng mới IndexAttributekhông?


5
Chỉ mục là một khái niệm cơ sở dữ liệu, không phải là một khái niệm mô hình thực thể. Ngay cả khi bạn có thể chỉ định một chỉ mục với một thuộc tính hoặc thông qua API thông thạo, nó sẽ không thực sự LÀM bất cứ điều gì trong ứng dụng của bạn. Nó chỉ là một hướng dẫn để EF sử dụng khi tạo cơ sở dữ liệu. Tôi tin rằng các hướng dẫn như vậy thuộc về di chuyển đầu tiên bằng mã, hoàn toàn liên quan đến việc thao tác lược đồ cơ sở dữ liệu.
JC Ford

Câu trả lời:


84

Ngày 26 tháng 10 năm 2017 Entity Framework 6.2 chính thức được phát hành . Nó bao gồm khả năng xác định các chỉ mục một cách dễ dàng thông qua API Fluent. Ho mà nó sẽ sử dụng đã được công bố trong bản beta của 6.2.

Bây giờ bạn có thể sử dụng HasIndex()phương thức này, tiếp theo là IsUnique()nếu nó phải là một chỉ mục duy nhất.

Chỉ là một ví dụ so sánh nhỏ (trước / sau):

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

Cũng có thể đánh dấu chỉ mục là được nhóm với .IsClustered().


CHỈNH SỬA # 1

Đã thêm một ví dụ về chỉ mục nhiều cột và thông tin bổ sung về cách đánh dấu một chỉ mục là được nhóm.


CHỈNH SỬA # 2

Như thông tin bổ sung, trong EF Core 2.1 nó giống hệt như trong EF 6.2 bây giờ.
Đây là tài liệu tham khảo về MS Doc.


Điều đó thật tuyệt! Tôi cho rằng nếu tôi có chỉ mục đa cột thì nó sẽ giống như: .HasIndex (p => new {p.Name, p.Xyz})
Valo

Ồ, xin lỗi, chắc chắn. Nó nên được new. Tôi sẽ sửa nó.
ChW

Bạn có thể vui lòng chỉ ra cách chúng ta có thể viết cùng một đoạn mã trong Core 2.x không?
user3417479

Theo như tôi biết nó phải là mã giống như được hiển thị dưới "sau" và "chỉ mục nhiều cột".
ChW

87

Hiện tại không có "hỗ trợ hạng nhất" để tạo chỉ mục thông qua API thông thạo, nhưng những gì bạn có thể làm là thông qua API thông thạo, bạn có thể đánh dấu thuộc tính là có thuộc tính từ API chú thích. Điều này sẽ cho phép bạn thêm Indexthuộc tính thông qua một giao diện thông thạo.

Dưới đây là một số ví dụ từ hạng mục công việc từ trang Sự cố cho EF.

Tạo chỉ mục trên một cột duy nhất:

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

Nhiều chỉ mục trên một cột:

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

Chỉ mục nhiều cột:

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

Sử dụng các kỹ thuật trên sẽ làm cho .CreateIndex()các lệnh gọi được tạo tự động cho bạn trong Up()hàm của bạn khi bạn mở đầu lần di chuyển tiếp theo (hoặc được tạo tự động trong cơ sở dữ liệu nếu bạn không sử dụng di chuyển).


4
điều đó có thể thêm chỉ mục trên cột nhưng điều đó sẽ không xóa chỉ mục nhóm được tạo trên khóa chính. HasKey tạo chỉ mục nhóm trên các khóa chính không bị xóa theo mặc định. Mà đã được gỡ bỏ một cách rõ ràng từ các tập tin chuyển đổi tạo ra bởi tình trạng sẽ clusered: false trong .Primarykey(x=>x.id,clustered:false)phương pháp
Joy

8
Tôi đã thử HasAnnotationphương pháp và KHÔNG có phương pháp nào như thế này. nhưng tôi đã tìm thấy một phương thức có tên HasColumnAnnotationchấp nhận các tham số mà bạn cung cấp. Bạn cần cập nhật câu trả lời của mình hay tôi nhầm?
Hakan Fıstık

@HakamFostok Tôi lấy ví dụ trực tiếp từ trang EF. Có lẽ tên đã thay đổi ở một trong các phiên bản hoặc có lỗi đánh máy trong phiên bản gốc.
Scott Chamberlain

3
Xem ngay dưới cùng của liên kết sau từ một cuộc họp thiết kế đầu năm nay: "Đổi tên HasAnnotation thành HasColumnAnnotation (cộng với các vị trí liên quan khác trong cơ sở mã).". entityframework.codeplex.com/…
Zac Charles

36

Tôi đã tạo một số phương thức mở rộng và gói chúng trong một gói nuget để làm cho việc này dễ dàng hơn nhiều.

Cài đặt EntityFramework.IndexingExtensionsgói nuget.

Sau đó, bạn có thể làm như sau:

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

Dự án và mã nguồn ở đây . Thưởng thức!


Tôi thực sự thích gói nhưng có vẻ như tên chỉ mục đôi khi bị thiếu sau đoạn đầu trong kịch bản lên. Nó chỉ xuất hiện đối với tôi khi sử dụng 4 thuộc tính trở lên trong chỉ mục của tôi. Tôi đang làm việc với EF 6.1.3.
Mixxiphoid

@Mixxiphoid - bạn có vui lòng ghi lại sự cố ở đây với các chi tiết hỗ trợ không? Ngoài ra, hãy chắc chắn rằng bạn có phiên bản 1.0.1, vì đã có lỗi trong 1.0.0.
Matt Johnson-Pint

Tôi có phiên bản 1.0.1. Tôi sẽ ghi lại sự cố nhưng không thể làm như vậy vào lúc này.
Mixxiphoid

Làm cách nào để thêm thứ tự cột tham gia chỉ mục để giảm dần? Theo mặc định .HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... tạo thứ tự tăng dần cho tất cả các cột tham gia trong chỉ mục.
GDroid

@GDroid - Rất tiếc, điều này không được IndexAttributelớp học của EF tiết lộ , vì vậy tôi không thể đưa nó vào thư viện của mình.
Matt Johnson-Pint

24

Không có tên rõ ràng:

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

Với một tên cụ thể:

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

Chỉ số có vẻ bị mô tả :(
Hamed Zakery Miab

1
@HamedZakeryMiab Bạn đang sử dụng phiên bản Entity Framework nào? Chỉ mục không bị phản đối.
Hugo Hilário

xin lỗi, tôi quên bao gồm EntityFramework. nó được bao gồm trong lắp ráp đó. chỉ nhầm lẫn về NS.
Hamed Zakery Miab

@HamedZakeryMiab vâng, thật là khó hiểu! Tôi nghĩ nó là một phần của System.DataAnnotations! Nó chắc chắn là gói khuôn khổ thực thể
AlbatrossCafe

3
câu hỏi chứa câu sau instead of using the new IndexAttributebạn có nhận thấy nó không?
Hakan Fıstık

22

Từ EF 6.1 trở đi, thuộc tính [Index]được hỗ trợ.
Sử dụng [Index(IsUnique = true)]cho chỉ mục duy nhất.
Đây là liên kết từ 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
Mặc dù về mặt lý thuyết, điều này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo.
Enamul Hassan

@manetsus Rất tốt. Tôi đã thêm một đoạn mã để phản ánh thay đổi.
Darie Dorlus

3
Độ dài chuỗi là cần thiết, nếu không, bạn sẽ thấy "thuộc loại không hợp lệ để sử dụng làm cột khóa trong ngoại lệ chỉ mục". Đồng nghiệp của tôi thích giải pháp modelBuilder trên Conntext để bạn không làm lộn xộn lớp Người dùng của mình, mà tôi đoán là hợp lệ.
andrew pate

Điều gì về các chỉ mục có nhiều cột cho tính duy nhất? Khá phổ biến để có một nhiều cột chỉ số chủ chốt độc đáo ...
enorl76

1
@ enorl76 Điều đó cũng được hỗ trợ. Đối với mỗi cột, bạn sẽ cần sử dụng một thuộc tính như sau, [Index("IX_BlogIdAndRating", 2)] public int Rating { get; set; } [Index("IX_BlogIdAndRating", 1)] public int BlogId { get; set; } Đây là tài liệu tham khảo từ Microsoft
Darie Dorlus

8

Khung thực thể 6

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

Và thêm bằng cách sử dụng:

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

7

Bạn có thể sử dụng chú thích dữ liệu INDEX Mã chú thích dữ liệu đầu tiên


3
Độ dài khóa tối đa là 900 byte đối với nvarchar và 450 byte đối với varchar. Nếu bạn đang sử dụng mã trước tiên, thuộc tính chuỗi sẽ là nvarchar và bạn nên bao gồm thuộc tính "StringLength" như trong [[StringLength (450)]
dunwan

Đối với EF 6.1, đây là câu trả lời chính xác. docs.microsoft.com/en-us/ef/ef6/modeling/code-first/…
Chris Schaller

2

Nếu bạn không muốn sử dụng các thuộc tính trên POCO của mình, thì bạn luôn có thể làm như sau:

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

Bạn có thể thực thi câu lệnh này trong DbInitializerlớp dẫn xuất tùy chỉnh của mình . Tôi không biết bất kỳ cách nào của Fluent API để thực hiện việc này.


1
Chắc chắn rồi, Mert. Hiện tại tôi đang sử dụng di chuyển và ở đó trong phương thức Up (), bạn cũng có thể đặt: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") và trong Down () DropIndex (("dbo.Table1 "," Column1_IX "). Tôi chỉ hy vọng rằng họ cũng thêm một API thông thạo ...
Valo

1

Tôi viết một phương thức mở rộng để sử dụng trong EF thông thạo để tránh thêm mã:

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

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

sau đó sử dụng nó như thế này:

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

hoặc như thế này nếu chỉ mục cần một số cấu hình:

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

1

Bạn có thể sử dụng một trong số này

// Chỉ mục

 this.HasIndex(e => e.IsActive)
            .HasName("IX_IsActive");

hoặc là

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
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.