Як створити індекс в Entity Framework 6.2 з кодом спочатку


112

Чи є спосіб створити індекс у властивості / стовпці, використовуючи код-перше, замість того, щоб використовувати новий IndexAttribute?


5
Індекс - це концепція бази даних, а не концепція моделі сутності. Навіть якби ви могли вказати індекс з атрибутом або через вільний API, він насправді нічого не зробить у вашій програмі. Це просто інструкція для використання EF при створенні бази даних. Я вважаю, що такі вказівки належать до перших міграцій коду, що повністю стосується маніпулювання схемою бази даних.
JC Ford

Відповіді:


84

Добре 26.10.2017 Entity Framework 6.2 був офіційно випущений . Він включає можливість легко визначати індекси за допомогою API Fluent. Але це використовувати вже було оголошено в бета-версії 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})
Вало

О, вибачте, звичайно. Це повинно бути new. Я це виправлю.
ChW

Чи можете ви покажіть, як ми можемо записати один і той же код у Core 2.x?
користувач3417479

Наскільки я знаю, це повинен бути той самий код, що показаний під "після" та "індекс декількох стовпців".
ChW

87

В даний час не існує «підтримки першого класу» для створення індексу через вільний API, але те, що ви можете зробити, це через API, який вільно говорить, ви можете відзначити властивості як атрибути API анотацій. Це дозволить вам додати Indexатрибут через вільний інтерфейс.

Ось кілька прикладів із робочого пункту на веб-сайті Issues для 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 у .Primarykey(x=>x.id,clustered:false)методі
Joy

8
Я спробував HasAnnotationметод, і немає такого способу, як цей. але я знайшов метод, ім'я HasColumnAnnotationякого приймає параметри, які ви надаєте. Вам потрібно оновити свою відповідь чи я помиляюся?
Hakan Fıstık

@HakamFostok Я взяв приклад прямо з сайту EF. Можливо, назва змінилася в одній з версій або є помилка друку в оригінальній версії.
Скотт Чемберлен

3
Дивіться внизу наступне посилання з наради дизайну на початку цього року: "Перейменуйте HasAnnotation на HasColumnAnnotation (плюс інші відповідні місця в кодовій базі)." entitframework.codeplex.com/…
Зак Чарльз

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.
Метт Джонсон-Пінт

У мене є версія 1.0.1. Я зафіксую проблему, але не можу цього зробити.
Mixxiphoid

Як додати порядок стовпців, що беруть участь в індексах, у порядку зменшення? За замовчуванням .HasIndex ("IX_Customers_EmailAddress", IndexOptions.Unique, ... створює порядку зростання для всіх стовпців, що беруть участь у індексі.
GDroid

@GDroid - На жаль, цей IndexAttributeклас не піддається впливу класу EF , тому я не можу включити його до своєї бібліотеки.
Метт Джонсон-Пінт

24

Без явного імені:

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

З конкретною назвою:

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

Індекс, здається, депримітований :(
Hamed Zakery Miab

1
@HamedZakeryMiab Яку версію Entity Framework ви використовуєте? Індекс не було застарілим.
Хуго Хіларіо

вибачте, я забув включити EntityFramework. він включений у цю збірку. просто розгубився щодо НС.
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
Хоча це теоретично може відповісти на питання, бажано було б сюди включити істотні частини відповіді та надати посилання для довідки.
Енамул Хассан

@manetsus Дуже добре. Я додав фрагмент коду для відображення змін.
Дарі Дорлус

3
Довжина рядка потрібна, інакше ви бачите "вигляд типу", який недійсний для використання в якості ключового стовпця в індексі ". Мій колега віддає перевагу рішенню modelBuilder на Conntext, щоб ви не захаращували свій клас користувача, який, напевно, є дійсним.
андре паште

Що з індексами з кількома стовпцями для унікальності? Досить поширеним є індекс унікального ключа у декількох стовпцях ...
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

Ви можете використовувати кодові анотації даних INDEX Перші анотації даних


3
Максимальна довжина ключа - 900 байт для nvarchar і 450 байт для varchar. Якщо ви використовуєте код спочатку, властивості рядка будуть nvarchar і вам слід включити атрибут "StringLength", як у [[StringLength (450)]
dunwan

Щодо EF 6.1, це правильна відповідь. docs.microsoft.com/en-us/ef/ef6/modeling/code-first/…
Кріс

2

Якщо ви не хочете використовувати атрибути у своїх POCO, то ви завжди можете це робити так:

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

Ви можете виконати цю операцію у власному DbInitializerпохідному класі. Я не знаю жодного способу зробити це Fluent API.


1
Звичайно, Мерт. На даний момент я використовую міграції, і там у методі Up () ви також можете поставити: CreateIndex ("dbo.Table1", "Column1", true, "Column1_IX") та Down () DropIndex (("dbo.Table1" "," Колона1_IX "). Я просто сподівався, що вони також додадуть вільний API ...
Вало,

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

1

Ви можете скористатися одним із цього

// Покажчики

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

або

  this.Property(e => e.IsActive).HasColumnAnnotation(
            "Index",
            new IndexAnnotation(new IndexAttribute("IX_IsActive")));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.