Entity Framework Core – Global Query Filters
Merhaba,
Entity Framework Core ile şartlı sorgu deyince akla direkt Where
komutu gelmektedir. Where, yapısal olarak bool mantıkta aldığı şart ifadesini sorgu diline çevirmekte ve hedef verileri bizlere getirmekte olan bir LINQ sorgusudur. Lakin Where fonksiyonu dışında generate edilecek sql sorgusunu şartlı oluşturabilecek birçok LINQ sorgusu mevcuttur : FirstOrDefault
, Single
vs. Bu içeriğimizde tüm şartlı sorguları generate edebilen LINQ sorgularının belirli bir entity’e özel, uygulama seviyesinde genel/global sorgu filtrelerinin oluşturulmasını sağlayan Global Query Filters özelliği inceliyor olacağız.
Global Query Filters, bir entity’e özel uygulama seviyesinde genel/ön kabullü şart oluşturmamızı ve böylece verileri global bir şekilde filtrelememizi sağlayan özelliktir. Belirtilen entity üzerinde yapılan tüm sorgulamalarda ekstradan bir şart ifadesine gerek kalmaksızın filtreleri otomatik uygulayarak, hızlıca sorgulama yapmamızı sağlamaktadır.
Misal olarak, sadece aktif olan personelleri elde etmek istediğimizde aşağıdaki gibi bir sorgu oluşturmamız gerekmektedir :
var employees = context.Employees.Where(e => e.IsActive).ToList();
İhtiyaca binaen bu tarz bir sorgu oldukça doğaldır. Amma velakin, her personel sorgulamasında sadece aktif olanların elde edilmesi gerekiyorsa bu durum kod maliyeti açısından zarara yol açacaktır. Nihayetinde Employee entity’sine her sorgu oluşturulan yerde Where(e => e.IsActive)
komutunun kullanılması, bağlayıcı ve sönük bir kalıptan ibaret olacaktır. Böyle bir durumda Employee entity’sine global seviyede ilgili şartı ön koşullu olarak tanımlamak en doğrusu olacaktır.
Bunun için global query filters özelliğini kullanmamız gerekmektedir. İlgili özellik sayesinde, uygulama seviyesinde Employee türüne özgü bir ön tanımlı şart ekleyeceğiz. Bu eklenen şart LINQ sorgusu çalıştırılmadan önce ilgili sorguya filtre olarak otomatik eklenecektir. Global query filters’ı ekleyebilmek için genellikle ‘OnModelCreating’ metodu kullanılabilmektedir;
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Employee>().HasQueryFilter(e => e.IsActive); base.OnModelCreating(modelBuilder); }
Görüldüğü üzere Employee entity’sine global query filter ‘HasQueryFilter’ metodu sayesinde eklenmiştir. Bu konfigürasyondan sonra ilgili uygulamada Employee üzerine yapılan tüm sorgular default olarak bu şarta tabi tutulacaktır.
İlgili sorguyu şartı eklemeksizin aşağıdaki gibi çalıştırdığımızda da yukarıdaki ile aynı sonucu verecektir.
var employees = context.Employees.ToList();
Bu özellik kullanılırken dikkat edilmesi gereken bir husus vardır ki, o da, global query filters üzerine tekrar sorgu çekmektir.
var employees = context.Employees.Where(e => e.IsActive).ToList();
Zaten var olan filters üzerine çekilen sorgu “ve” mantığında değerlendirilecek ve generate edilen sql sorgusuna dahil edilecektir.
Bu durumda sorgu lüzumsuz yere şartlara boğulmakta ve maliyeti artmaktadır. O yüzden ilgili özelliğin kullanıldığı entity’ler de istemsizce bu duruma düşmemek için dikkatli olmakta fayda vardır.
IgnoreQueryFilters Metodu
Bazı durumlarda global olarak tanımlanmış bu filtrenin uygulanmasına ihtiyacımız olmayacaktır. Böyle bir durumda oluşturulacak LINQ sorgusuna özel ‘IgnoreQueryFilters’ metoduyla ilgili filtreyi devre dışı bırakabiliriz.
var employees = context.Employees.IgnoreQueryFilters().ToList();
Böylece filtre uygulamaksızın tüm veriler elde edilecektir. Ya da farklı şartlarla sorguyu sıfırdan inşa edebilirsiniz…
Nihai olarak;
Global Query Filters özelliğinin, bir sorgunun birden fazla aynı özelliği gösterdiği ve aynı şartları uyguladığı durumlarda bir başka deyişle multitenancy senaryolarda tercih edildiğini gözlemlemekteyiz. İhtiyaca binaen kullanıldığında kod açısından temiz ve sade bir sorgulama yetisi kazandırdığı kanaatindeyiz.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
Meraba,
bir süredir üzerine çalıştığım “c# asp.net entity framework” araç takip isteminde yeni araç ekleme özelliği var.Daha önceden kaydedilmiş bir araç,silinmeden tekrar kaydedilmek istenirse uyarı vermesini istiyorum.Nasıl yapabilirim.Yardımcı olursanız çok sevinirim.İyi Günler dilerim
Kullanışlı bir özellikmiş hocam elinize sağlık