2014-06-21 11 views
15

Sembra in Entity Framework 6.1 che hanno aggiunto la possibilità di creare indici tabella tramite il nuovo metodo HasColumnAnnotation. Ho creato un paio di estensioni di supporto per accelerare il processo:È possibile utilizzare più indici utilizzando 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 })); 
    } 
} 

Questo funziona fantastico ... fino a quando cerco di creare un secondo indice che contiene una colonna già utilizzato in un altro indice. Qualunque cosa aggiunga per ultima sovrascrive l'originale. Qualcuno sa se è attualmente possibile aggiungere più indici alla stessa colonna tramite il nuovo HasColumnAnnotation disponibile su StringPropertyConfiguration e PrimitivePropertyConfiguration?

Posso aggirare il problema come sempre aggiungendo manualmente gli indici negli script di Migrazione, ma sarebbe eccellente poterlo configurare nei mapping EntityTypeConfiguration in modo da poter avere tutto in un unico punto.


Dopo il feedback Gerts, questo è quello che ho finito per fare:

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

Ed ecco il nuovo utilizzo:

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

risposta

25

Questo perché ciascuno dei tuoi metodi di estensione assegnare un nuova annotazione su una proprietà e sovrascrivere quella precedente. Lascia che ti mostri questo usando i tuoi metodi in un esempio.

Dire che abbiamo questo (inutile) di classe

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

e applicare le definizioni di indice (saltare 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); 

Inlining i metodi di estensione (grazie a Dio per ReSharper) questo porta 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)); 

Questo è lo stesso di scrittura

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

e poi sostituzione facendo

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

Per riprodurre l'annotazione corretta ...

[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 configurazione della proprietà ClientId dovrebbe essere simile

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

Ora improvvisamente la creazione di metodi di estensione è molto meno attraente. Non vale la pena di crearne uno per questa annotazione combinata. Ma per le colonne monouso i tuoi metodi sono un miglioramento.

Ovviamente è chiaro perché lo stai provando. L'attuale sintassi fluente è a dir poco clamorosa. Il team EF knows this perfectly well e sperano in qualche collaboratore per risolvere presto questo problema. Forse qualcosa per te?

+0

Grazie Gert. Ho capito che potrebbe essere ciò che stava accadendo. L'ultimo esempio mi mostra cosa devo fare dopo.Probabilmente aggiusterò la mia classe helper in modo che accetti gli indici 'Params IndexAttribute [] 'così posso passare più indici per proprietà. Nuovo codice aggiunto alla domanda. – Sam

+0

+1. Nel tuo ultimo pezzo di codice di esempio hai perso l'attributo 'IsUnique', avrebbe dovuto essere' new IndexAttribute ("ClientCompanyIndex", 1) {IsUnique = true} 'e' new IndexAttribute ("ClientAddressIndex", 1) {IsUnique = vero} '. –

Problemi correlati