Çözümü çok basit fakat, özellikle büyük ölçekli projelerde ve veritabanından döndürdüğümüz epeyce yüklü bir data kümesi söz konusu olduğunda, gerçekten başa bela olacak bir durum notu düşmek istedim:
Multiple Enumeration ' a dikkat et !
Tabi ki kodun nasıl tasarlandığıyla da ilişkili bir durum bu. Öyleyse, muhtemel bir multiple enumeration senaryosu oluşturalım.
Diyelim ki kitap yazarlarınının bilgilerini döndüren bir metot yazmamız lazım. Parametre olarak Id koleksiyonu alıyor olsun ve bu Id lere sahip Author koleksiyonunu veritabanından çekiyor olalım.
Author entity'lerini çektiğimiz repository metodu şöyle yazılmış olsun ;
Kabaca, GetAuthorCollection metodu IEnumerable<T> tipinden bir parametre alıyor, bu parametreyle yazarları ilgili repository'den çekiyor ve hem parametre aldığı bu id kümesi üzerinde hem de repository'den gelen entity kümesi üzerinde yine IEnumerable 'ın Count() metodu ile işlem yapıyor.
İşte nur topu gibi bir "Multiple enumeration" vakası.
Buradaki asıl dramatik olay, oluşturduğumuz senaryoda IEnumerable'ın arkasında bir EF sorgusunun var olması. Her enumeration'da bu sorguyu veritabanına karşı yürümekteyiz.
Bu durumdan kaçınmanın en kısa yolu "ToList()" veya "ToArray()" 'i çağırmak olacaktır.
Yani ilgili koleksiyonu ToList() veya ToArray()'i çağırarak bellekte toplarsak performanstan kazanmış oluyoruz, bir nevi cacheliyoruz.
Böylece koleksiyon üzerinde yapacağımız diğer işlemler çok fazla maliyetli olmayacaktır.
Bu şekilde yazılmış bir repository metodunu kullanırken dikkat etmezsek eğer birden fazla kez enumeration yaptığımızı her zaman anlayamayabiliriz. Yani Resharper gibi extension 'lar kullanmıyorsak özellikle dikkatten kaçması çok muhtemel.
Bu sebepten aslında en doğru yöntem kodu tasarlarken IEnumerable<T> kullanmak yerine ICollection<T> veya IList<T> tercih etmek olabilir. Yani refactor etmek mümkünse daha güzel olacaktır.
Commentaires