İlkay İlknur

just a developer...

Entity Framework Code First Index Attribute Kullanımı

Entity Framework Code First içerisindeki en büyük sıkıntılardan birisidir kod içerisinden Index yaratmak. Code First ile istediğimiz tüm işlemleri yazdığımız model classları üzerinden yapabilirken iş index yaratma kısmına gelince ya SQL Scriptlerini kod içerisine ekleriz ya da Code First Migrations içerisindeki index yaratma ve drop etme metotların kullanırız. Ancak çok şükür artık Entity Framework 6.1 versiyonuyla beraber artık index yaratma işlerini de doğrudan model classlarımız üzerinden yapabiliyoruz. O zaman hemen Entity Framework Nuget paketini projemize ekleyerek giriş yapalım.

PM> Install-Package EntityFramework

Entity Framework paketini yükledikten sonra da aşağıdaki gibi model ve DbContext sınıfımızın olduğunu düşünelim.

public class Person
{
    public int Id { getset; }
    [MaxLength(64)]
    public string Name { getset; }
    [MaxLength(64)]
    public string Surname { getset; }
    public int NumberOfChildren { getset; }
}

public class PersonDbContext : DbContext
{
    public DbSet<Person> People { getset; }
}

Diyelim ki modelimiz içerisindeki Name ve NumberOfChildren alanlarına index koymak istiyoruz. Bunun için ilgili propertylerin üzerine Index attribute'ünü koyarak istediğimiz indexi yaratabiliriz.

public class Person
{
    public int Id { getset; }
    [MaxLength(64)]
    [Index]
    public string Name { getset; }
    [MaxLength(64)]
    public string Surname { getset; }
    [Index]
    public int NumberOfChildren { getset; }
}

Bakalım database tarafında indexlerimiz nasıl oluşmuş.

Index attribute'ünü kullanırken herhangi bir parametre vermediğimizde index adı IX_{Property_Adı} şeklinde yaratılıyor. Bunun yanında yaratılan indexler aynı zamanda Non-Unique ve Non-Clustured. Eğer indexin adını veya tipini değiştirmek isterseniz Index attribute'ü içerisindeki parametreleri kullanabilirsiniz.

Parametre Adı

Açıklaması

Name(string) Indexin Adı
Order(int) Bu property index içerisinde kaçıncı sırada olacak.
IsUnique(bool) Yaratılacak olan index unique index mi ?
IsClustered(bool)            Yaratılacak olan index clustered index mi ?

Birden Fazla Property'i Kapsayan Index Yaratma

Bazı durumlarda birden fazla kolonu kapsayan indexler yaratmamız gerekebiliyor. Peki bakalım bunun için Entity Framework tarafında nasıl bir çözüm bulunmuş ? Yukarıdaki tablodan hatırlarsanız indexlere isim verebiliyorduk. Eğer siz 2 farklı property üzerindeki index attributelerine aynı index ismini parametre olarak geçerseniz Entity Framework arka planda otomatik olarak bu alanları kapsayan bir index yaratıyor. Index içerisindeki kolonların sırasını belirlemek için Order parametresini kullanabilirsiniz.

Şimdi yukarıdaki örnekdeki Name ve Surname alanlarını içerisinde barındıran bir index yaratalım.

public class Person
{
    public int Id { getset; }
    [MaxLength(64)]
    [Index("IX_Name", 1)]
    public string Name { getset; }
    [MaxLength(64)]
    [Index("IX_Name", 2)]
    public string Surname { getset; }
    [Index]
    public int NumberOfChildren { getset; }
}
Yarattığımız indexin database tarafındaki karşılığı şu şekilde.

Code First Migrations Desteği

Model classlarındaki propertylerin üzerine koyduğumuz index attributelerinde herhangi bir değişiklik yaparsak bu değişiklikler migrations tarafından da algılanıyor. Örneğe geçmeden önce Package Manager Console üzerinden Entity Framework için migrationları enable edelim.

PM> Enable-Migrations

Yukarıda son hali bulunan model classımız üzerinde şu değişiklikleri yapalım. İlk olarak NumberOfChildren propertysinde bulunan indexin adını değiştirelim. Sonrasında da Name ve Surname alanlarını kapsayan indexi sadece Name alanını kapsayacak şekilde değiştirelim.

Model classımızın son hali şu şekilde olacak.

public class Person
{
    public int Id { getset; }
    [MaxLength(64)]
    [Index("IX_Name", 1)]
    public string Name { getset; }
    [MaxLength(64)]
    public string Surname { getset; }
    [Index("IX_ChildrenNumber")]
    public int NumberOfChildren { getset; }
}

Model üzerinde değişikliği yaptıktan sonra Package Manager Console üzerinde bir Migration yaratalım ve bakalım migration kodu nasıl yaratılmış.

PM> Add-Migration IndexChanges

Yukarıdaki komutu çalıştırdıktan sonra migration kodu solution içerisinde Migrations klasöründe yaratılmış oldu.

Bu yaratılan migration içerisindeki koda bakarsak ilgili değişikliğin migration kodu içerisine eklendiğini görürüz.

public partial class IndexChanges : DbMigration
{
    public override void Up()
    {
        DropIndex("dbo.People""IX_Name");
        RenameIndex(table: "dbo.People", name: "IX_NumberOfChildren", newName: "IX_ChildrenNumber");
        CreateIndex("dbo.People""Name");
    }

    public override void Down()
    {
        DropIndex("dbo.People"new[] { "Name" });
        RenameIndex(table: "dbo.People", name: "IX_ChildrenNumber", newName: "IX_NumberOfChildren");
        CreateIndex("dbo.People"new[] { "Name""Surname" }, name: "IX_Name");
    }
}

Son olarak bu migrationı database'e uygulamak için Package Manager Console üzerinden database'i update edelim.

PM> Update-Database

Bu işlemi de yaptıktan sonra bakalım değişiklikler database tarafına nasıl yansımış.

Eksikler

Index attribute'ü çoğu genel kullanım durumumda ihtiyacımızı karşılarken bazı durumlarda da eksik kalabiliyor. Bu eksik kaldığı noktalarda da maalesef yine SQL üzerinden ilerlemek dışında pek bir alternatifimiz yok.

Benim şu ana kadar index attribute'ü içerisinde gördüğüm en büyük eksiklik index içerisine extra kolonları include edemememiz.

Bunun dışında benim gördüğüm pek bir eksiklik yok gibi. Ancak sizin karşılaştığınız problemler olursa bu yazının altına comment olarak ekleyin ve yazıyı genişletelim ;)



Yorum Gönder