Existe uma maneira de criar um índice em uma propriedade / coluna usando o código primeiro, em vez de usar o novo IndexAttribute
?
Existe uma maneira de criar um índice em uma propriedade / coluna usando o código primeiro, em vez de usar o novo IndexAttribute
?
Respostas:
Bem, 26.10.2017 Entity Framework 6.2 foi lançado oficialmente . Inclui a possibilidade de definir índices com facilidade via API Fluent. Como ele deve ser usado já foi anunciado na versão beta do 6.2.
Agora você pode usar o HasIndex()
método, seguido de IsUnique()
se deveria ser um índice exclusivo.
Apenas um pequeno exemplo de comparação (antes / depois):
// 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();
Também é possível marcar o índice como agrupado com .IsClustered()
.
EDITAR # 1
Adicionado um exemplo de índice de várias colunas e informações adicionais sobre como marcar um índice como agrupado.
EDITAR # 2
Como informação adicional, no EF Core 2.1 é exatamente o mesmo que no EF 6.2 agora.
Aqui está o artigo do MS Doc como referência.
new
. Eu irei consertar isso.
Atualmente não há "suporte de primeira classe" para a criação de um índice por meio da API fluente, mas o que você pode fazer é por meio da API fluente marcar propriedades como tendo atributos da API de anotação. Isso permitirá que você adicione o Index
atributo por meio de uma interface fluente.
Aqui estão alguns exemplos do item de trabalho do site de problemas da EF.
Crie um índice em uma única coluna:
modelBuilder.Entity<MyEntity>()
.Property(e => e.MyProperty)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new IndexAttribute()));
Vários índices em uma única coluna:
modelBuilder.Entity<MyEntity>()
.Property(e => e.MyProperty)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new[]
{
new IndexAttribute("Index1"),
new IndexAttribute("Index2") { IsUnique = true }
}));
Índices multicolunas:
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)));
O uso das técnicas acima fará com que as .CreateIndex()
chamadas sejam criadas automaticamente para você em sua Up()
função quando você organizar sua próxima migração (ou sejam criadas automaticamente no banco de dados se você não estiver usando migrações).
.Primarykey(x=>x.id,clustered:false)
method
HasAnnotation
método e não existe nenhum método como este. mas encontrei um método cujo nome HasColumnAnnotation
aceita os parâmetros que você fornece. Você precisa atualizar sua resposta ou estou errado?
Criei alguns métodos de extensão e os envolvi em um pacote nuget para tornar isso muito mais fácil.
Instale o EntityFramework.IndexingExtensions
pacote nuget.
Então você pode fazer o seguinte:
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));
}
}
O projeto e o código-fonte estão aqui . Aproveitar!
IndexAttribute
classe de EF , então não posso incluí-lo em minha biblioteca.
Sem um nome explícito:
[Index]
public int Rating { get; set; }
Com um nome específico:
[Index("PostRatingIndex")]
public int Rating { get; set; }
EntityFramework
. está incluído nessa montagem. apenas confuso sobre o NS.
instead of using the new IndexAttribute
você notou?
Do EF 6.1 em diante, o atributo [Index]
é suportado.
Use [Index(IsUnique = true)]
para um índice exclusivo.
Aqui está o link da 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; }
Aqui a referência da Microsoft
Entity Framework 6
Property(c => c.MyColumn)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_MyIndex")));
E adicione usando:
using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
Você pode usar a anotação de dados INDEX Code First Data Annotations
Se não quiser usar atributos em seus POCO, você sempre pode fazer da seguinte forma:
context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ...");
Você pode executar esta instrução em sua DbInitializer
classe derivada personalizada . Não conheço nenhuma forma de API fluente de fazer isso.
Escrevo um método de extensão para uso em EF fluente para evitar código extra:
public static PrimitivePropertyConfiguration HasIndexAnnotation(
this PrimitivePropertyConfiguration primitivePropertyConfiguration,
IndexAttribute indexAttribute = null
)
{
indexAttribute = indexAttribute ?? new IndexAttribute();
return primitivePropertyConfiguration
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(indexAttribute)
);
}
então use-o assim:
Property(t => t.CardNo)
.HasIndexAnnotation();
ou assim se o índice precisar de algumas configurações:
Property(t => t.CardNo)
.HasIndexAnnotation(new IndexAttribute("IX_Account") { IsUnique = true });
Você pode usar um destes
// Indexes
this.HasIndex(e => e.IsActive)
.HasName("IX_IsActive");
ou
this.Property(e => e.IsActive).HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_IsActive")));