Dizinler

Dizinler, birçok veri deposunda ortak bir kavramdır. Veri deposundaki uygulamaları farklılık gösterse de, bir sütuna (veya sütun kümesine) göre yapılan aramaları daha verimli hale getirmek için kullanılır. İyi dizin kullanımı hakkında daha fazla bilgi için performans belgelerindeki dizinler bölümüne bakın.

Bir sütun üzerinde aşağıdaki gibi bir dizin belirtebilirsiniz:

[Index(nameof(Url))]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Dekont

Kural gereği, yabancı anahtar olarak kullanılan her özellikte (veya özellik kümesinde) bir dizin oluşturulur.

Bileşik dizin

Dizin birden fazla sütuna da yayılabilir:

[Index(nameof(FirstName), nameof(LastName))]
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Bileşik dizinler olarak da bilinen birden çok sütundaki dizinler, dizinin sütunlarına göre filtreleyen sorguları hızlandırdığı gibi, yalnızca dizinin kapsadığı ilk sütunları filtreleyen sorguları da hızlandırmaktadır. Daha fazla bilgi için performans belgelerine bakın.

Dizin benzersizliği

Varsayılan olarak, dizinler benzersiz değildir: dizinin sütun kümesi için birden çok satırın aynı değerlere sahip olması sağlanır. Dizini aşağıdaki gibi benzersiz hale getirebilirsiniz:

[Index(nameof(Url), IsUnique = true)]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Dizinin sütun kümesi için aynı değerlere sahip birden fazla varlık eklemeye çalışmak bir özel durum oluşturmaya neden olur.

Dizin sıralama düzeni

Dekont

Bu özellik EF Core 7.0'da kullanıma sunulmuştur.

Çoğu veritabanında, bir dizinin kapsadığı her sütun artan veya azalan olabilir. Yalnızca bir sütunu kapsayan dizinler için bu genellikle önemli değildir: veritabanı gerektiğinde ters sırada dizinden geçiş yapabilir. Ancak bileşik dizinler için sıralama iyi performans açısından çok önemli olabilir ve sorgu tarafından kullanılan veya kullanılmayan dizin arasındaki fark anlamına gelebilir. Genel olarak, dizin sütunlarının sıralama düzenleri sorgunuzun yan tümcesinde ORDER BY belirtilenlere karşılık gelir.

Dizin sıralama düzeni varsayılan olarak artandır. Aşağıdaki gibi tüm sütunların azalan düzende olmasını sağlayabilirsiniz:

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

Sıralama düzenini sütun temelinde aşağıdaki gibi de belirtebilirsiniz:

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

Dizin adlandırma ve birden çok dizin

Kural gereği, ilişkisel veritabanında oluşturulan dizinler olarak adlandırılır IX_<type name>_<property name>. Bileşik dizinler için, <property name> özellik adlarının alt çizgiyle ayrılmış bir listesi haline gelir.

Veritabanında oluşturulan dizinin adını ayarlayabilirsiniz:

[Index(nameof(Url), Name = "Index_Url")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Aynı özellik kümesinde birden çok kez çağrı HasIndex yaparsanız, bunun yeni bir dizin oluşturmak yerine tek bir dizin yapılandırmaya devam ettiğini unutmayın:

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName })
    .HasDatabaseName("IX_Names_Ascending");

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName })
    .HasDatabaseName("IX_Names_Descending")
    .IsDescending();

İkinci HasIndex çağrı ilkini geçersiz kıldığından, bu yalnızca tek bir azalan dizin oluşturur. Bu, kural tarafından oluşturulan bir dizini daha fazla yapılandırmak için yararlı olabilir.

Aynı özellik kümesi üzerinde birden çok dizin oluşturmak için, EF modelindeki dizini tanımlamak ve aynı özellikler üzerinden diğer dizinlerden ayırmak için kullanılacak olan öğesine bir ad HasIndexgeçirin:

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName }, "IX_Names_Ascending");

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName }, "IX_Names_Descending")
    .IsDescending();

Bu adın veritabanı adı için varsayılan olarak da kullanıldığını, bu nedenle açıkça çağırmanın HasDatabaseName gerekli olmadığını unutmayın.

Dizin filtresi

Bazı ilişkisel veritabanları filtrelenmiş veya kısmi dizin belirtmenize olanak sağlar. Bu, bir sütunun değerlerinin yalnızca bir alt kümesini dizine eklemenizi ve dizinin boyutunu azaltmanızı ve hem performansı hem de disk alanı kullanımını geliştirmenizi sağlar. SQL Server filtrelenmiş dizinleri hakkında daha fazla bilgi için belgelere bakın.

Fluent API'sini kullanarak bir dizinde SQL ifadesi olarak sağlanan bir filtre belirtebilirsiniz:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .HasFilter("[Url] IS NOT NULL");
}

SQL Server sağlayıcısını kullanırken EF, benzersiz bir 'IS NOT NULL' dizinin parçası olan tüm null atanabilir sütunlar için bir filtre ekler. Bu kuralı geçersiz kılmak için bir null değer sağlayabilirsiniz.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .IsUnique()
        .HasFilter(null);
}

Eklenen sütunlar

Bazı ilişkisel veritabanları, dizine dahil edilen ancak "anahtarının" parçası olmayan bir sütun kümesi yapılandırmanıza olanak sağlar. Bu, sorgudaki tüm sütunlar anahtar veya anahtar olmayan sütunlar olarak dizine eklendiğinde sorgu performansını önemli ölçüde geliştirebilir çünkü tablonun kendisine erişilmesi gerekmez. SQL Server dahil edilen sütunlar hakkında daha fazla bilgi için belgelere bakın.

Aşağıdaki örnekte sütun dizin Url anahtarının bir parçasıdır, bu nedenle bu sütundaki tüm sorgu filtrelemeleri dizini kullanabilir. Ancak buna ek olarak, yalnızca ve PublishedOn sütunlarına erişen sorguların Title tabloya erişmesi gerekmez ve daha verimli çalışır:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasIndex(p => p.Url)
        .IncludeProperties(
            p => new { p.Title, p.PublishedOn });
}

Kısıtlamaları denetleme

Denetim kısıtlamaları, tablodaki tüm satırlar için tutması gereken bir koşul tanımlamanızı sağlayan standart bir ilişkisel özelliktir; kısıtlamayı ihlal eden verileri ekleme veya değiştirme girişimleri başarısız olur. Denetim kısıtlamaları null olmayan kısıtlamalara (bir sütundaki null değerleri yasaklayan) veya benzersiz kısıtlamalara (yinelenenleri yasaklar) benzer, ancak rastgele SQL ifadesinin tanımlanmasına izin verir.

Tablo üzerinde SQL ifadesi olarak sağlanan bir denetim kısıtlaması belirtmek için Fluent API'sini kullanabilirsiniz:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Product>()
        .ToTable(b => b.HasCheckConstraint("CK_Prices", "[Price] > [DiscountedPrice]"));
}

Aynı tabloda her biri kendi adına sahip birden çok denetim kısıtlaması tanımlanabilir.

Not: Bazı yaygın denetim kısıtlamaları EFCore.CheckConstraints topluluk paketi aracılığıyla yapılandırılabilir.