C'è un modo per creare un indice su una proprietà / colonna usando il codice prima, invece di usare il nuovo IndexAttribute
?
C'è un modo per creare un indice su una proprietà / colonna usando il codice prima, invece di usare il nuovo IndexAttribute
?
Risposte:
Ebbene 26.10.2017 Entity Framework 6.2 è stato ufficialmente rilasciato . Include la possibilità di definire facilmente gli indici tramite Fluent API. Come usarlo era già stato annunciato nella beta della 6.2.
Ora puoi usare il HasIndex()
metodo, seguito da IsUnique()
se dovrebbe essere un indice univoco.
Solo un piccolo esempio di confronto (prima / dopo):
// 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();
È anche possibile contrassegnare l'indice come raggruppato con .IsClustered()
.
MODIFICA # 1
Aggiunto un esempio per l'indice a più colonne e ulteriori informazioni su come contrassegnare un indice come cluster.
MODIFICA # 2
Come informazioni aggiuntive, in EF Core 2.1 è esattamente lo stesso come in EF 6.2 ora.
Ecco l'artcile MS Doc come riferimento.
new
. Io lo aggiusterò.
Attualmente non esiste un "supporto di prima classe" per la creazione di un indice tramite l'API fluente, ma ciò che puoi fare è tramite l'API fluente puoi contrassegnare le proprietà come aventi attributi dall'API di annotazione. Ciò ti consentirà di aggiungere l' Index
attributo tramite un'interfaccia fluente.
Di seguito sono riportati alcuni esempi dall'elemento di lavoro dal sito Problemi per EF.
Crea un indice su una singola colonna:
modelBuilder.Entity<MyEntity>()
.Property(e => e.MyProperty)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new IndexAttribute()));
Più indici su una singola colonna:
modelBuilder.Entity<MyEntity>()
.Property(e => e.MyProperty)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new[]
{
new IndexAttribute("Index1"),
new IndexAttribute("Index2") { IsUnique = true }
}));
Indici a più colonne:
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)));
L'uso delle tecniche di cui sopra farà sì che le .CreateIndex()
chiamate vengano create automaticamente per te nella tua Up()
funzione quando impalcature la tua prossima migrazione (o verranno create automaticamente nel database se non stai usando le migrazioni).
.Primarykey(x=>x.id,clustered:false)
method
HasAnnotation
metodo e non esiste un metodo come questo. ma ho trovato un metodo il cui nome HasColumnAnnotation
accetta i parametri che fornisci. Devi aggiornare la tua risposta o mi sbaglio?
Ho creato alcuni metodi di estensione e li ho inseriti in un pacchetto nuget per renderlo molto più semplice.
Installa il EntityFramework.IndexingExtensions
pacchetto nuget.
Quindi puoi fare quanto segue:
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));
}
}
IndexAttribute
classe EF , quindi non posso includerlo nella mia libreria.
Senza un nome esplicito:
[Index]
public int Rating { get; set; }
Con un nome specifico:
[Index("PostRatingIndex")]
public int Rating { get; set; }
EntityFramework
. è incluso in quell'assemblaggio. solo confuso sul NS.
instead of using the new IndexAttribute
hai notato?
Da EF 6.1 in poi l'attributo [Index]
è supportato.
Utilizzare [Index(IsUnique = true)]
per indice univoco.
Ecco il collegamento di Microsoft
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true)]
[StringLength(200)]
public string Username { get; set; }
public string DisplayName { get; set; }
}
[Index("IX_BlogIdAndRating", 2)]
public int Rating { get; set; }
[Index("IX_BlogIdAndRating", 1)]
public int BlogId { get; set; }
qui il riferimento da Microsoft
Entity Framework 6
Property(c => c.MyColumn)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_MyIndex")));
E aggiungi usando:
using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
È possibile utilizzare le annotazioni dei dati Code First Data Annotaion
Se non vuoi usare attributi sui tuoi POCO, puoi sempre farlo come segue:
context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ...");
Puoi eseguire questa dichiarazione nella tua abitudine DbInitializer
classe derivata . Tuttavia, non conosco alcun modo API fluente per farlo.
Scrivo un metodo di estensione da utilizzare in EF fluente per evitare codice aggiuntivo:
public static PrimitivePropertyConfiguration HasIndexAnnotation(
this PrimitivePropertyConfiguration primitivePropertyConfiguration,
IndexAttribute indexAttribute = null
)
{
indexAttribute = indexAttribute ?? new IndexAttribute();
return primitivePropertyConfiguration
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(indexAttribute)
);
}
quindi usalo in questo modo:
Property(t => t.CardNo)
.HasIndexAnnotation();
o come questo se index necessita di alcune configurazioni:
Property(t => t.CardNo)
.HasIndexAnnotation(new IndexAttribute("IX_Account") { IsUnique = true });
Puoi usare uno di questi
// Indici
this.HasIndex(e => e.IsActive)
.HasName("IX_IsActive");
o
this.Property(e => e.IsActive).HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_IsActive")));