EF8 İle Performanslı Toplu İşlemler

Bu makalede, özelikle büyük datalar üzerinde yapılan Bulk Operasyonları, EF Core 8.0 ile gelen yeni özellikler ile nasıl daha performanslı yapabileceğinizden bahsedeceğim.

Öncelikle çalışacağımız Database, Northwind database’i olacaktır. Buradan indirebilirsiniz.

 

 

 

 

 

 

 

 

 

 

 

 

Aşağıda görüldüğü gibi, .Net 8.0 “EntityBulkOperations” adında bir Console Application yaratılır.

Şimdi sıra geldi DAL Projesini yaratmaya:

DAL adında yeni bir Class Library aşağıda görüldüğü gibi yaratılır. İçine Models/DB şeklinde iki tane folder açılır. Bu DAL uygulaması için DB First yöntemini kullanacağız.

DAL Projesine aşağıdaki Kütüphaneler eklenir.

Terminal açılıp DAL projesinin altına gelinir. Ve aşağıdaki komut çalıştırılır. Mevcut Northwind DB’den, DBContext ve Entityleri oluşturmak için scaffold tool’u kullanılmıştır.

Not: Eğer “scaffold” komutunuz, bilgisayarınızda yüklü değil ise, EntityFrameworkCore.Tools’u aşağıdaki komut ile kurmanız gerekmektedir.


Artık yukarıda görüldüğü gibi DAL projemiz ve NorthwindContext’imiz hazır :)

Bulk Insert:

Aşağıda görüldüğü gibi 2 tablo ile ilişkili olan Territories ve Region üzerinde bulk işlemler yapılacaktır.

Territories tablosuna Insert işlemi yapılırken, aynı anda ilişkisel olan Region tablosuna da aynı anda Performanslı bir şekilde kayıt atabilmek için, aşağıdaki ücretsiz kütüphane kullanılmıştır. EF Core 8.0 ile bunun doğrudan yapılabileceği standart bir yol henüz bulunmamaktadır. Ayrı ayrı Entityleri kaydedip, “DbContext.SaveChanges” tabi ki kullanabilirsiniz :)

Aşağıda görüldüğü gibi “Territory” tablosuna üç kayıt atılmıştır Ayrıca herbir Territory kaydına karşılık, yeni bir “Region” kaydı oluşturulmuş ve ID’si de Territory tablosuna aynı anda kaydedilmiştir. Buradaki önemli option config parametresi => “bulkConfig.IncludeGraph = true“‘dur. Bu parametre ile child tablolara da kayıt atılmaktadır.
Program.cs: 

Sql Sorgu Sonucu:

Bulk Update:

Aşağıda görüldüğü gibi Customer ve Orders birbiri ile relational iki tablodur. Biz de belli koşullara göre seçtiğimiz Orders tablosunu, Bulk bir şekilde güncelleyeceğiz.

Öncelikle Order tarihi 1998 olan ve ülkesi ‘Finland’ olan siparişler listelenir.

Yukarıdaki Query ile sadece Order çekilecektir. Toplu güncelleme işleminde Order yanında Customer da çekilmek istenir ise, aşağıdaki gibi bir Query yazılmalıdır.

Yukarıdaki Queryler çağrıldığında Data null hatası alınmaktadır. Sorunu biraz araştırdığımda, aşağıda görülen alanların null geldiğini gördüm. Ama bizim “scaffold” ile oluşturduğumuz Entitylerde, bu string alanlar Nullable olarak tanımlanmamışlardır!

Yapılması gereken, aynen aşağıda olduğu gibi Customer ve Order tablolarının ilgili alanlarının “string?” nullable olarak güncellenmesidir.

İlgili güncelleme yapıldıktan sonra sorgu çalıştırıldığında, aşağıdaki gibi kayıtlara erişilir. Aşağıda görüldüğü gibi “Orderlar” ve ilişkili oldukları “Customerlar” gelmektedir.

Şimdi gelin Order Tablosundaki ilgili koşullara göre null olan ShipRegion alanın, “XXX” olarak Bulk bir şekilde güncelleyelim. Aşağıda görüldüğü gibi, önce ilgili koşullara göre Orderslar çekilmiş, daha sonrada “ExecuteUpdateAsync()” methodu ile => “ShipRegion” filed’ina “XXX” değeri topluca, asenkron bir şekilde set edilmiştir.

Result: Aşağıda görüldüğü gibi ilgili Orderlar’ın “ShipRegion”‘ı “XXX” olmuştur.

Tekrar istenen field’a null değerinin atanması için “x.SetProperty(o => o.ShipRegion, (string?)null))” şeklinde bir atamanın yapılması gerekmektedir.

Aşağıdaki örnekte Order tablosuna ait iki Field “ShipRegion, ShipAddress”, aynı anda Bulk olarak asenkron şekilde güncellenmiştir. Burada kritik keyword “ExecuteUpdateAsync()” methodudur. .Net 8.0 ile performanslı bulk güncelleme, özellikle büyük datalarda “ExecuteUpdateAsync()” ile sağlanmaktadır.

NOT: Orders tablosnun bağlı olduğu Customer tablosu, “SetProperty()” methodu ile Bulk bir şekilde güncellenememektedir. ExecuteUpdateAsync() child methodlarda hata vermektedir.

Bulk Delete:

Aşağıda görüldüğü gibi başta toplu olarak Insert ettiğimiz üç Territories kaydını, şimdi Bulk olarak sileceğiz. Gene burada .Net 8.0 ile hayatımız giren “ExecuteDeleteAsync()” methodu, performanslı bir şekilde  toplu silme işlemi sağlamaktadır.

Performance:

Yapılan Benchmark testleri gösteriyor ki, Entity sayısı arttıkça performans misli ile artmaktadır.

1-) EF Extension’ın paylaştığı bu test de bize, performans konusunda kesinlikle bir fikir vermektedir.

2-) EFCore.BulkExtensions kütüphanesinin Sql server 2019 ile altta yaptığı şu Bulk Insert, Update, Delete Benchmark Testi, kafada hiçbir soru işareti bırakmamaktadır.

Sonuç:

EF Core Bulk işlemler için, AddRange(), Add(), EFCore.BulkExtensions gibi birçok methodun kendine özgü avantajları ve sınırlamaları vardır. Küçük ile orta ölçekli veriler için Add veya AddRange yöntemleri gayet yeterli olabilir. Ancak daha büyük veri kümeleri için, EFCore.BulkExtensions gibi Bulk işlemler yapabileceğiniz methodları kullanmak, hem verimlilik hem de performans açısından mutlaka değerlendirilmesi gereken yeniliklerden bazılarıdır. Seçiminizi, her zaman yapacağınız işlemlerin büyüklüğüne ve uygulamanızın ihtiyaçlarına göre belirleyin.

Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hepinize hoşçakalın.

Source:

  • https://devblogs.microsoft.com/dotnet/announcing-ef8-rc2/
  • https://www.nuget.org/packages/EFCore.BulkExtensions
  • https://entityframework-extensions.net/bulk-insert-optimized
  • https://servicestack.net/posts/bulk-insert-performance
  • https://medium.com/codenx/ef-core8-bulk-operations-bd008a98004e
Herkes Görsün:

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.