8 Maddede Entity Framework Korkunuzu Yenin
Yenisafak.com ve diğer dikey projelerimizde karşılaştığımız sorunlar için çözümlerimizi 8 maddede sıralayacağım. Entity Framework’ten korkmayın. Yanlış kullanmaktan korkun.
Entity Framework, kullanımı her ne kadar kolay olsa da efsaneleşmiş bir korkuya sahip halen. Çok büyük data’larla çalışırken kullanmaktan korkulan/mümkün oldukça kaçılan bir ORM aslında.
Peki neden korkuluyor? Performans kaybı sanırım bunun en büyük sebebi.
Hadi baştan başlayalım ve bu korkuları oluşturacak sebepleri ortadan kaldıracak adımlar atalım.
Seperation of Concerns konusuna değinmek istiyorum.
Henüz mimari’yi kurarken başlıyor olay. Siz mimari’nizi ne kadar iyi kodladınız ki, Entity Framework çok kötü diyebiliyorsunuz? Burası çooook önemli bir konu.
Projeyi hazırlarken Layer’ları parçalıyorsunuz. Business Logic, Service Layer, Data Access Layer gibi bir çok parçaya bölüyorsunuz.Data onlarca katmandan onlarca yapıdan geçiyor. Yapı içerisine bir de Repository Pattern uyguluyorsunuz ohhhhh missssss :) üstüne bir de Generic hale getiriyorsunuz tadından yenmez :)
Hayır hayır öyle değil işte, Repository Pattern’i unutun artık. Sene 2018 olmuş halen 90'lı yılların yöntemleri kullanılıyor.
1. Repository Pattern’i Unutun Artık!
Repository Pattern, database’i soyutlamak için kullanılıyor. Fakat Entity Framework zaten bunu gerçekleştiriyor. Neden soyutlanmış bir yapıyı tekrar soyutluyoruz? Bence alışkanlıklardan dolayı. Kolaylığından dolayı da diyebiliriz. Fakat bu kötü bir alışkanlık. Performans kaybının baş katili bu olabilir.
2. Gereksiz Kolon Kullanımları
Bir tablonuz var ve içerisinde 20 kolon bulunuyor. Siz bu tablodan kayıt çekiyorsunuz ve ön tarafta bir kart’a buradan çektiğiniz dataları basacaksınız.Genellikle bu işin normali Select atılırken kullanmak istediğiniz alanları belirtirsiniz. 3,5,10 kaç taneyse artık. Gidip de tüm(*) alanları çekmezsiniz. Eğer çekiyorsanız! sorun büyük demektir. Performansınızı alt üst edecek durumlardan birisi de bu.
Generic Repository’ler de Get, GetById gibi metodlar bulunur, bu metodlar bir çok yerde kullanılacağı için “select * from” olarak, yani tüm kolonları sorgusuz sualsiz çekiyor. Repository Pattern kullanmamak gerektiğinin altını bir kez daha çizmiş olayım :)
3. AsNoTracking Kardeşliği :)
Entity Framework database’i sık sık izliyor ve biz çektiğimiz data üzerinde işlem yapıp savechanges yaptığımız zaman gidiyor hemen database’e de işlem uyguluyor, tabii işlem uygulamadan önce her sorgu öncesi database’in sürümünü soruyor, öğreniyor kendisi ile eşit mi diye kontrol ediyor. Bu performansınızı yerle bir edebilir. Orta halli projeleriniz için kullanmasanız da olur aslında fakat büyük data’lar ile sık Read/Write yapıyorsanız bir göz gezdirin derim.
AsNoTracking’i Yenisafak MicroServices’lerimizde kullanıyoruz. Bu data’yı sadece Read için kullanacağım diyerek EF’ye bildiriyorum.
4. SaveChanges Birlik ve Beraberliği
Genellikle database’e bir veri kaydetmek istediğimizde model’i Dbcontext’e ekleyip SaveChanges metodunu çalıştırırız. Peki birden çok tabloya bağlantılı(Relation) olarak kayıt yapmak istediğinizde nasıl yaparsınız?
Genellikle gördüğüm. Her tablo kayıtı için bir SaveChanges() kullanılıyor. Oysa ki çoooook yanlış. Siz Model’lerinizi oluşturup kaç tabloya ekleme yapacaksanız eklemelerinizi yapın. En son kısımda bir tane SaveChanges() koyduğunuzda daha hızlı çalıştığını göreceksiniz.
5. Lazy Loading ve Eager Loading Kapışması
Lazy Loading kadar saçma bir şey görmedim. Neden böyle bir şey yaptıklarını da anlamakta zorlanıyorum. Başlı başına bir yük. Performans kaybını neredeyse en çok yaşatan özelliklerden birisi.
Entity serialize edildiğinde genellikler property çağrılır ve her serialize durumunda extra olarak bir query tekrar çalışır. Tablonuza bağlı onlarca tablo olduğunda Lazy Loading performans konusunda resmen çakılıyor. Bu nedenle Include(Tablo İsmi) kullanmayı deneyin(Eager Loading)
Lazy Loading’i Enable ederek performansı fark edeceğinize inanıyorum.
6. Veri Tipi Katili
Veri Tipi korkutucu gelmese de göze, aslında performansınıza balta vuracak bir sorun olarak karşınıza çıkabilir. Nasıl mı?
Tabloda bir kolon’a veri tipi olarak varchar verdiğinizi düşünün ve bir get işlemi yapacaksınız ve ya set işlemi. Siz Class yapısını C# tarafında kurgularken Column(TypeName=”varchar”) olarak ayarlamadığınız için sql sizin sorgunuzu alacak ve convert işlemine tabi tutacak.
[Column(TypeName=“varchar”)]
public string LessonName { get; set; }
Çünkü; .Net string tipini Nvarchar olarak çalıştıracaktır.
7. AutoDetectChangesEnable Abimiz
Siz bu ayarı true durumuna getirirseniz eğer başınız yanabilir :) ne zaman? bir ve ya daha fazla liste kayıtı ardı ardına db’ye ekleme yaparken.
Peki bu abimizin görevi ne?
AutoDetectChangesEnable, siz bir işlem yapmak istediğinizde tüm entry’ler, savechanges’ler çağrılır ve bir değişiklik var mı kontrol edilir ve gider bir de db’ye bakar. Orada durumlar nasıl diye.
Ne gerek var abi yahu?
Kayıt listesi ekleme esnasından önce false durumuna getirip kayıt ekleme işlemi bitince tekrar true yapabilirsiniz. Bu performans kazanımı sağlayacaktır.
8. Async Kullanın, Kullandırın
Async, gözle görülür çok büyük bir farklılık yaratır. Kayıt eklerken veya Read işlemi yaparken Async kullanmak performansınızı kat ve kat artıracaktır.
Async başlı başına bir konu olduğu için kısa bir şekilde yorumlamak istemiyorum. Bir sonra ki yazımda da belki Async kullanımlarından bahsedebilirim.
8 Madde ile Performans sorunlarını nasıl yok edebileceğinizi ve korkularınızın aslında alışkanlıklarınızdan gelebileceğini belirtmiş oldum.
Bir sonra ki yazımda görüşmek üzere.