c# - Múltiples índices posibles utilizando HasColumnAnnotation?
entity-framework ef-code-first (1)
Parece que en Entity Framework 6.1 agregaron la capacidad de crear índices de tablas a través del nuevo método HasColumnAnnotation
. Creé algunas extensiones de ayuda para acelerar el proceso:
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 }));
}
}
Esto funciona de maravilla ... hasta que intento crear un segundo índice que contiene una columna que ya se usa en otro índice. Lo que añada último, sobreescribe el original. ¿Alguien sabe si actualmente es posible agregar múltiples índices a la misma columna a través de la nueva HasColumnAnnotation
disponible en StringPropertyConfiguration
y PrimitivePropertyConfiguration
?
Puedo solucionar este problema como siempre lo he hecho agregando índices manualmente en los scripts de migración, pero sería excelente poder configurar esto en las asignaciones de configuración de tipo de EntityTypeConfiguration
para poder tenerlo todo en un solo lugar.
Después de los comentarios de Gerts, esto es lo que terminé haciendo:
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));
}
}
Y aquí está el nuevo uso:
Property(x => x.Name).IsRequired().HasMaxLength(65).HasIndex(new IndexAttribute("IX_Countries_Name") { IsUnique = true }, new IndexAttribute("IX_Countries_Published", 2))
Esto se debe a que cada uno de sus métodos de extensión asigna una nueva anotación a una propiedad y sobrescribe la anterior. Déjame mostrarte eso usando tus métodos en un ejemplo.
Digamos que tenemos esta clase (inútil)
public class Client
{
public int ClientId { get; set; }
public int CompanyId { get; set; }
public int AddressId { get; set; }
}
Y aplique sus definiciones de índice (omitiendo la parte 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);
Alinear los métodos de extensión (gracias a Dios por Resharper) esto conduce a
.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));
Esto es lo mismo que escribir
[Index("ClientCompanyIndex", Order = 1)]
public int ClientId { get; set; }
y luego reemplazándolo por
[Index("ClientAddressIndex", Order = 1)]
public int ClientId { get; set; }
Para reproducir la anotación correcta ...
[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; }
... la configuración de la propiedad ClientId
debería verse como
.Property(c => c.ClientId).HasColumnAnnotation("Index",
new IndexAnnotation(new[]
{
new IndexAttribute("ClientCompanyIndex", 1),
new IndexAttribute("ClientAddressIndex", 1)
}));
Ahora, de repente, crear métodos de extensión es mucho menos atractivo. No vale la pena el esfuerzo de crear una para esta anotación combinada. Pero para las columnas de un solo uso, sus métodos son una mejora.
Por supuesto está claro por qué estás intentando esto. La sintaxis fluida actual es torpe por decir lo menos. El equipo de EF lo sabe perfectamente y esperan que algún colaborador se ocupe de este problema pronto. Tal vez algo para ti?