İçeriğe geç

QueryFirst ve QuerySingle: Veritabanından Tek Kayıt Çekmenin İncelikleri

Selamlar! Bugün sizlerle, veritabanı sorgularında sıkça karşımıza çıkan ama bazen de kafa karıştıran iki komut hakkında konuşacağız: QueryFirst ve QuerySingle. Hani bazen bir veriye ihtiyacımız olur ya, tam olarak bir tane, ne eksik ne fazla. İşte bu noktada bu iki arkadaş devreye giriyor. Açıkçası ilk başlarda ben de karıştırıyordum, hatta bazen yanlış kullanıp programı patlattığım bile oldu 🙂

Şimdi düşününce ne kadar basit ama bir o kadar da önemli bir konu değil mi? Hele ki bizim gibi sürekli veriyle iç içe olanlar için, bu tür küçük detaylar büyük farklar yaratabiliyor. Düşünsenize, bir listeden tek bir ürünü çekmeniz gerekiyor, ama yanlış komutu kullandınız ve birden fazla kayıt geldi. İşte o zaman işler biraz karışıyor, değil mi?

Öncelikle QueryFirst’ten başlayalım. Bu arkadaş, bir sorgu çalıştırdığında, gelen ilk kaydı getirir. Yani siz bir sürü kayıt bekleseniz bile, o sadece ilkini alır ve size verir. Kendi programımda bir keresinde şöyle bir durum olmuştu: Bir kullanıcı listesi çekiyordum ama sadece ilk aktif kullanıcıyı göstermem gerekiyordu. O an aklıma gelmedi QueryFirst, gittim bütün listeyi çektim, sonra içinden ilkini seçtim. Şimdi düşününce komik geliyor ama o zamanlar acil işim vardı, ne yapsam şaşırmıştım.

QueryFirst’ün güzel yanı, eğer sorgunuz hiçbir kayıt döndürmezse, bu komut null döner. Yani programınız patlamaz, boş gelir. Bu da aslında bir avantaj, değil mi? En azından bir hata mesajı alıp ‘Aa, neden böyle oldu?’ diye düşünmek yerine, verinin olmadığını bilirsiniz. Mesela bir ürün ID’si verdiniz ama böyle bir ürün yok. QueryFirst kullanırsanız null alırsınız. Harika!

Gelelim QuerySingle’a. Bu arkadaş ise biraz daha titiz. QuerySingle, sorgunuzun tam olarak bir kayıt döndürmesini bekler. Eğer bir kayıt dönerse, onu verir. Ama eğer sorgunuz hiçbir kayıt döndürmezse ya da birden fazla kayıt döndürürse, işte o zaman patlar! Yani bir hata fırlatır.

Bu durum ilk başta biraz korkutucu gelebilir ama aslında çok mantıklı. Çünkü siz ‘tek bir kayıt istiyorum’ dediğinizde, sistemin de size tam olarak tek bir kayıt getirmesini beklersiniz. Eğer beklediğiniz gibi olmazsa, yani ya hiç kayıt gelmezse (null olmasını umarken bir anda hata almak gibi) ya da birden fazla kayıt gelirse (sizin tek kayıt beklentinizi karşılamaz), orada bir sorun var demektir. Bu yüzden QuerySingle kullanmak, sorgularınızın doğru çalıştığından emin olmanızı sağlar. Hani bazen bir şeyi yapıyorsunuz ama ‘doğru mu yapıyorum?’ diye bir şüpheye düşersiniz ya, işte QuerySingle o şüpheyi ortadan kaldırıyor.

Şimdi gelelim koda. Bu iki komutu nasıl kullanacağımızı bir görelim. Genellikle Entity Framework Core ile kullanıyoruz bu arkadaşları. Diyelim ki bir veritabanımız var ve içinde ‘Urunler’ adında bir tablomuz var. Bu tablodan tek bir ürün çekmek istiyoruz.

Önce bir yanlış yapalım, sonra doğrusunu gösterelim. Hani dedim ya, ilk başlarda karıştırıyordum diye. İşte o karışıklık anından bir örnek:

// YANLIŞ KULLANIM: Birden fazla kayıt gelirse patlar! // Veya hiç kayıt gelirse null hatası verir. // Bu kod, Eğer 'Adi' 'Laptop' olan birden fazla ürün varsa veya hiç yoksa hata verecektir. var yanlisUrun = _context.Urunler.Where(u => u.Adi == "Laptop").Single();  // Neden yanlış? Çünkü 'Laptop' adında birden fazla ürün olabilir.  // Veya hiç olmayabilir. Single() bu durumlarda hata verir. // Program patlar. :)

Gördünüz mü? Eğer ‘Laptop’ adında birden fazla ürün varsa veya hiç yoksa, bu kod çalışmaz. Programımız bir hata mesajıyla karşımıza dikilir. Çok tatlı değil mi? 🙂 Ama neyse ki bunun çözümü var!

Şimdi gelelim doğru kullanıma. Eğer tam olarak bir kayıt bekliyorsak ve bu kaydın mutlaka olması gerektiğini biliyorsak, QuerySingleForEFCore’u kullanabiliriz. Ya da eğer sadece ilk kaydı alıp geçmek istiyorsak, QueryFirst’ü kullanırız. Eğer kayıt yoksa null almayı bekliyorsak, QueryFirst kullanmak daha mantıklı.

Örneğin, belirli bir ID’ye sahip ürünü çekmek istiyoruz. Bu ID’nin benzersiz olduğunu varsayalım.

// DOĞRU KULLANIM 1: ID'ye göre tek kayıt çekme (Kesin var olduğunu bildiğimizde) var dogruUrunSingle = _context.Urunler.Single(u => u.Id == 1);  // Eğer Id=1 olan ürün yoksa, bu kod hata verir. Ama biliyoruz ki ID'ler benzersiz. // Bu yüzden Single() burada güvenle kullanılabilir.

// DOĞRU KULLANIM 2: İlk kaydı alma (Eğer birden fazla olabilir ama ilkini istiyorsak) var ilkUrun = _context.Urunler.FirstOrDefault(); // Veya First() kullanabiliriz ama FirstOrDefault daha güvenli. // FirstOrDefault, kayıt yoksa null döner. First() ise hata verir. // Diyelim ki ürünlerin listelendiği bir sayfada ilk çıkan ürünü göstermek istiyoruz. // Bu durumda FirstOrDefault kullanmak daha akıllıca.

Bu arada, FirstOrDefault ile First arasındaki farkı da bilmek önemli. First, eğer kayıt bulamazsa bir istisna fırlatır. FirstOrDefault ise null döner. Yani ‘ya varsa, yoksa da bana null ver’ dediğimizde FirstOrDefault daha kullanışlı oluyor. Hani bazen bir şey bulamayız ama programın çökmesini istemeyiz ya, işte tam o noktada devreye giriyor.

Peki ya QuerySingle’ın ilk örneğimizdeki gibi birden fazla kayıt gelme ihtimali varsa ne yapacağız? İşte orada da QuerySingle’ın bir kardeşi var: QuerySingleOrDefault. Bu komut, eğer tam olarak bir kayıt gelirse onu verir, eğer hiçbir kayıt gelmezse null döner. Ama yine, eğer birden fazla kayıt gelirse patlar! Yani aslında QueryFirst’ün daha sıkı hali gibi düşünebiliriz bunu. Tek kayıt beklentisi daha güçlü.

Sonuç olarak, QueryFirst ve QuerySingle’ı ne zaman kullanacağımız tamamen senaryoya bağlı. Tek bir kayıt bekliyorsak ve bu kaydın mutlaka olması gerekiyorsa QuerySingle kullanırız. Eğer birden fazla kayıt gelme ihtimali varsa ve programın patlamasını istemiyorsak, ama sadece ilkini alacaksak QueryFirst kullanırız. Eğer kayıt gelmezse null almak istiyorsak FirstOrDefault daha uygun. Bu küçük nüanslar, kodumuzun daha sağlam ve hatasız çalışmasını sağlıyor.

Bu arada, bu konuyu daha detaylı incelemek isterseniz, Entity Framework Core’un kendi dokümantasyonuna göz atabilirsiniz. Genelde bu tür konuları ararken Google’da arama yapmak en hızlı yol oluyor. Orada bulduğum bir yazıdan bu bilgileri pekiştirmiştim sanırım.

Umarım bu yazı, QueryFirst ve QuerySingle arasındaki farkı ve ne zaman hangisini kullanacağınızı netleştirmiştir. Unutmayın, küçük detaylar büyük farklar yaratır! Hadi bakalım, kodlarımıza geri dönme vakti!