Можно использовать несколько индексов с использованием HasColumnAnnotation?

Похоже, что в Entity Framework 6.1 они добавили возможность создания табличных индексов с помощью нового метода HasColumnAnnotation. Я создал несколько вспомогательных расширений, чтобы ускорить процесс:

public static class MappingExtensions
{
    public static StringPropertyConfiguration HasIndex(this StringPropertyConfiguration config, bool isUnique = false)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsUnique = isUnique }));
    }
    public static StringPropertyConfiguration HasIndex(this StringPropertyConfiguration config, string name, int order = 1, bool isUnique = false)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute(name, order) { IsUnique = isUnique }));
    }
    public static PrimitivePropertyConfiguration HasIndex(this PrimitivePropertyConfiguration config, bool isUnique = false)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsUnique = isUnique }));
    }
    public static PrimitivePropertyConfiguration HasIndex(this PrimitivePropertyConfiguration config, string name, int order = 1, bool isUnique = false)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute(name, order) { IsUnique = isUnique }));
    }
}

Это работает фантастически... пока я не попытаюсь создать второй индекс, содержащий столбец, уже использованный в другом индексе. Независимо от того, что я добавляю, последняя перезаписывает оригинал. Кто-нибудь знает, возможно ли в настоящее время добавить несколько индексов в один и тот же столбец через новый HasColumnAnnotation, доступный в StringPropertyConfiguration и PrimitivePropertyConfiguration?

Я могу обойти это, как всегда, вручную добавляя индексы в сценарии миграции, но было бы очень удобно настраивать это в сопоставлениях EntityTypeConfiguration, чтобы я мог иметь все это в одном месте.


После обратной связи Gerts это то, что я закончил:

public static class MappingExtensions
{
    public static StringPropertyConfiguration HasIndex(this StringPropertyConfiguration config, params IndexAttribute[] indexes)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(indexes));
    }

    public static PrimitivePropertyConfiguration HasIndex(this PrimitivePropertyConfiguration config, params IndexAttribute[] indexes)
    {
        return config.HasColumnAnnotation("Index", new IndexAnnotation(indexes));
    }
}

И вот новое использование:

Property(x => x.Name).IsRequired().HasMaxLength(65).HasIndex(new IndexAttribute("IX_Countries_Name") { IsUnique = true }, new IndexAttribute("IX_Countries_Published", 2))

Ответы

Ответ 1

Это связано с тем, что каждый из ваших методов расширения назначает новую аннотацию свойству и перезаписывает предыдущую. Позвольте мне показать, что, используя ваши методы в примере.

Скажем, у нас есть этот (бесполезный) класс

public class Client
{
    public int ClientId { get; set; }
    public int CompanyId { get; set; }
    public int AddressId { get; set; }
}

И примените свои определения индекса (пропуская часть modelBuilder.Entity<Client>()):

.Property(c => c.ClientId).HasIndex("ClientCompanyIndex");
.Property(c => c.CompanyId).HasIndex("ClientCompanyIndex", 2);
.Property(c => c.ClientId).HasIndex("ClientAddressIndex");
.Property(c => c.AddressId).HasIndex("ClientAddressIndex", 2);

Встраивая методы расширения (слава богу за Resharper), это приводит к

.Property(c => c.ClientId).HasColumnAnnotation("Index",
    new IndexAnnotation(new IndexAttribute("ClientCompanyIndex", 1));
.Property(c => c.CompanyId).HasColumnAnnotation("Index",
     new IndexAnnotation(new IndexAttribute("ClientCompanyIndex", 2));
.Property(c => c.ClientId).HasColumnAnnotation("Index",
    new IndexAnnotation(new IndexAttribute("ClientAddressIndex", 1));
.Property(c => c.AddressId).HasColumnAnnotation("Index",
     new IndexAnnotation(new IndexAttribute("ClientAddressIndex", 2));

Это то же самое, что писать

[Index("ClientCompanyIndex", Order = 1)]
public int ClientId { get; set; }

а затем заменив его на

[Index("ClientAddressIndex", Order = 1)]
public int ClientId { get; set; }

Воспроизведение правильной аннотации...

[Index("ClientAddressIndex", IsUnique = true, Order = 1)]
[Index("ClientCompanyIndex", IsUnique = true, Order = 1)]
public int ClientId { get; set; }
[Index("ClientCompanyIndex", IsUnique = true, Order = 2)]
public int CompanyId { get; set; }
[Index("ClientAddressIndex", IsUnique = true, Order = 2)]
public int AddressId { get; set; }

... конфигурация свойства ClientId должна выглядеть как

.Property(c => c.ClientId).HasColumnAnnotation("Index",
    new IndexAnnotation(new[]
        {
            new IndexAttribute("ClientCompanyIndex", 1),
            new IndexAttribute("ClientAddressIndex", 1)
        }));

Теперь внезапно создание методов расширения гораздо менее привлекательно. Это вряд ли стоит усилий для создания одного для этой объединенной аннотации. Но для одноразовых столбцов ваши методы улучшаются.

Конечно, понятно, почему вы пытаетесь это сделать. Текущий свободный синтаксис, по меньшей мере, неуклюж. Команда EF прекрасно это знает, и они надеются, что кто-то из авторов этого вопроса вскоре получит эту проблему. Может быть, что-то для вас?