Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Índices são um conceito comum em muitos armazenamentos de dados. Embora sua implementação no armazenamento de dados possa variar, elas são usadas para tornar as pesquisas com base em uma coluna (ou conjunto de colunas) mais eficientes. Consulte a seção índices na documentação de desempenho para obter mais informações sobre o bom uso do índice.
Você pode especificar um índice em uma coluna da seguinte maneira:
[Index(nameof(Url))]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
Observação
Por convenção, um índice é criado em cada propriedade (ou conjunto de propriedades) que são usadas como uma chave estrangeira.
Índice composto
Um índice também pode abranger mais de uma coluna:
[Index(nameof(FirstName), nameof(LastName))]
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Índices em várias colunas, também conhecidos como índices compostos, aceleram as consultas que filtram as colunas do índice, mas também consultas que filtram apenas as primeiras colunas cobertas pelo índice. Consulte os documentos de desempenho para obter mais informações.
Exclusividade do índice
Por padrão, os índices não são exclusivos: várias linhas têm permissão para ter os mesmos valores para o conjunto de colunas do índice. Você pode tornar um índice exclusivo da seguinte maneira:
[Index(nameof(Url), IsUnique = true)]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
A tentativa de inserir mais de uma entidade com os mesmos valores para o conjunto de colunas do índice fará com que uma exceção seja gerada.
Ordem de classificação de índice
Na maioria dos bancos de dados, cada coluna coberta por um índice pode ser crescente ou decrescente. Para índices que abrangem apenas uma coluna, isso normalmente não importa: o banco de dados pode percorrer o índice em ordem inversa conforme necessário. No entanto, para índices compostos, a ordenação pode ser crucial para um bom desempenho e pode significar a diferença entre um índice sendo usado por uma consulta ou não. Em geral, as ordens de classificação das colunas de índice devem corresponder às especificadas na ORDER BY cláusula da consulta.
A ordem de classificação de índice é crescente por padrão. Você pode fazer com que todas as colunas tenham ordem decrescente da seguinte maneira:
[Index(nameof(Url), nameof(Rating), AllDescending = true)]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int Rating { get; set; }
}
Você também pode especificar a ordem de classificação em uma base coluna por coluna da seguinte maneira:
[Index(nameof(Url), nameof(Rating), IsDescending = new[] { false, true })]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int Rating { get; set; }
}
Nomenclatura de índice e vários índices
Por convenção, os índices criados em um banco de dados relacional são nomeados IX_<type name>_<property name>. Para índices compostos, <property name> torna-se uma lista de nomes de propriedade separados por sublinhados.
Você pode definir o nome do índice criado no banco de dados:
[Index(nameof(Url), Name = "Index_Url")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
Observe que, se você chamar HasIndex mais de uma vez no mesmo conjunto de propriedades, isso continuará configurando um único índice em vez de criar um novo:
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName })
.HasDatabaseName("IX_Names_Ascending");
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName })
.HasDatabaseName("IX_Names_Descending")
.IsDescending();
Como a segunda HasIndex chamada substitui a primeira, isso cria apenas um índice decrescente. Isso pode ser útil para configurar ainda mais um índice que foi criado por convenção.
Para criar vários índices no mesmo conjunto de propriedades, passe um nome para o HasIndex, que será usado para identificar o índice no modelo EF e distingui-lo de outros índices sobre as mesmas propriedades:
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName }, "IX_Names_Ascending");
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName }, "IX_Names_Descending")
.IsDescending();
Observe que esse nome também é usado como um padrão para o nome do banco de dados, portanto, a chamada HasDatabaseName explícita não é necessária.
Filtro de índice
Alguns bancos de dados relacionais permitem que você especifique um índice filtrado ou parcial. Isso permite indexar apenas um subconjunto dos valores de uma coluna, reduzindo o tamanho do índice e melhorando o desempenho e o uso de espaço em disco. Para obter mais informações sobre índices filtrados do SQL Server, consulte a documentação.
Você pode usar a API fluente para especificar um filtro em um índice, fornecido como uma expressão SQL:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.HasFilter("[Url] IS NOT NULL");
}
Ao usar o provedor do SQL Server, o EF adiciona um 'IS NOT NULL' filtro para todas as colunas anuláveis que fazem parte de um índice exclusivo. Para substituir essa convenção, você pode fornecer um null valor.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.IsUnique()
.HasFilter(null);
}
Colunas incluídas
Alguns bancos de dados relacionais permitem configurar um conjunto de colunas que são incluídas no índice, mas não fazem parte de sua "chave". Isso pode melhorar significativamente o desempenho da consulta quando todas as colunas na consulta são incluídas no índice como colunas chave ou não chave, pois a própria tabela não precisa ser acessada. Para obter mais informações sobre colunas incluídas no SQL Server, consulte a documentação.
No exemplo a seguir, a Url coluna faz parte da chave de índice, portanto, qualquer filtragem de consulta nessa coluna pode usar o índice. Mas, além disso, as consultas que acessam somente as colunas `Title` e `PublishedOn` não precisarão acessar a tabela e serão executadas com mais eficiência.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasIndex(p => p.Url)
.IncludeProperties(
p => new { p.Title, p.PublishedOn });
}
Verificar restrições
As restrições de verificação são um recurso relacional padrão que permite definir uma condição que deve conter para todas as linhas em uma tabela; qualquer tentativa de inserir ou modificar dados que violem a restrição falhará. As restrições de verificação são semelhantes a restrições não nulas (que proíbem nulos em uma coluna) ou a restrições exclusivas (que proíbem duplicatas), mas permitem que a expressão SQL arbitrária seja definida.
Você pode usar a API fluente para especificar uma restrição de verificação em uma tabela, fornecida como uma expressão SQL:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Product>()
.ToTable(b => b.HasCheckConstraint("CK_Prices", "[Price] > [DiscountedPrice]"));
}
Várias restrições de verificação podem ser definidas na mesma tabela, cada uma com seu próprio nome.
Observação: algumas restrições de verificação comuns podem ser configuradas por meio do pacote de comunidade EFCore.CheckConstraints.