Linq2MySQL ile Rastgele Veri Çekme

Pekçoğumuzun yaşadığı linq ile mysql'den rastgele veri çekme olayının çözümünü bu yazıda bulabilirsiniz.

Çoğumuz projelerimizde veritabanı olarak MySQL kullanırız. Bu yazımızda LINQ ifadeleri kullanarak MySQL içerisinden rastgele veri çekme ile ilgili çözüm önerileri bulacaksınız.

Peki, kabul. "neden böyle bir yazı yazma ihtiyacı hissettin?" ya da "bunun neresi zor ki?" gibi sorular aklınıza gelebilir.

Önce buna bir cevap vereyim. Eğer klasik SQL komutları ile veri çekme işi ile uğraşıyor, LINQ kullanmıyorsanız yazının devamını okumaya ihtiyacınız yok demektir. 

Çünkü;

select * from cmsicerikler
order by rand()
limit 5

gibi bir komutla bu işi çok rahat bir şekilde yapabilirsiniz.

Ya da aklınıza GUID ya da Random ile verileri sıralayabilirim şeklinde bir fikir gelebilir. Hemen deneyelim:

Random rnd = new Random();
var rastgeleIcerik = (from x in db.cmsicerikler
                        orderby rnd.Next()
                        select x).Take(5);

çalıştırın ve hatayı alın:

LINQ to Entities 'Int32 Next()' yöntemini tanımıyor ve bu yöntem bir depo ifadesine çevrilemez.

:)

İşte bu yüzden bu yazıyı yazıyorum.

Şimdi gelelim adım adım çözüme:

Önce MySQL tarafında bir Function oluşturacağız:

CREATE DEFINER=`root`@`localhost` FUNCTION `Rastgele`()
	RETURNS int(11)
	LANGUAGE SQL
	NOT DETERMINISTIC
	CONTAINS SQL
	SQL SECURITY DEFINER
	COMMENT ''
RETURN RAND() * 1000000000

Fonksiyonumuzun adı: Rastgele. Yaptığı iş rastgele sayı oluşturmak. :)

Bir sonraki adım, MySQL tablomuzu projemize eklemek, yani Entity Data Model oluşturmak:

Oluşturduğum model şu şekilde: (Kafama göre -keyfime göre de diyebilirsiniz- bir tablo ekledim.)

Model için verdiğim Namespace ve Entity Container Name ise şu şekilde:

Namespace: "DAModel"

Oluşturduğumuz MySQL fonksiyonumuzu kodumuzun içerisinde kullanabilmek için kendi class ımızı yazıyoruz:

public static class MyDBFunctions
{
    [EdmFunction("DAModel.Store", "Rastgele")]
    public static  int Rastgele()
    {
        throw new ArgumentNullException();
    }
}

Classın metodunu yazarken EdmFunction attribute ünü kullanıyoruz. İlk parametre olarak NameSpaceimiz.Store yazdığımıza dikkat edin. Yoksa çalışmaz!!!

Metodun içerisinde throw dışında herhangi bir ifade göremiyorsunuz değil mi? Bu enteresan gelebilir, ama EdmFunction ın 2. parametresinde de çalıştıracağımız MySQL fonksiyonun adını yazdığımıza dikkat edin. Bu şu anlama geliyor: Bu metodu çalıştırdığınızda, MySQL tarafında oluşturduğumuz Rastgele isimli fonksiyon çalışacaktır.

Şimdi gönül rahatlığı ile LINQ sorgumuzu yazabiliriz.

var rastgeleHaberler = (from x in db.cmsicerikler
                        orderby MyDBFunctions.Rastgele()
                        select new
                        {
                            Id = x.Id,
                            Baslik = x.Baslik,
                            Tarih = x.Tarih
                        }).Take(5);

sonra da istediğiniz gibi verileri kullanabilirsiniz:

foreach (var h in rastgeleHaberler)
{
    Console.WriteLine(h.Id + " - " + h.Baslik);
}

Sonuç 1:

9 - Görsel Tasarım
184 - Artık yıl hesabı
209 - 2. Domain Etkinliği
95 - Microsoft Yazılım Geliştiriciler Teknoloji Günleri (İstanbul)
152 - Time Period Library for .NET

Sonuç 2:

138 - Microsoft Etkinlikleri
130 - Word Çıktısı Alma
121 - Internet Programcılığı ve Veritabanı dersleri 1. dönem 1. sınav soruları
101 - Vuvuzela :(((
56 - Web Sitesi Değerlendirme Kriterleri

vb...

hata yok, veriler rastgele sıralı bir şekilde geliyor. 

Son olarak, oluşan sql cümleciğini merak edebilirsiniz, ona da bir göz atalım:

var sql = ((ObjectQuery)rastgeleHaberler).ToTraceString();
Console.WriteLine(sql);

Sonuç:

SELECT
`Project1`.`Id`,
`Project1`.`Baslik`,
`Project1`.`Tarih`
FROM (SELECT
`Rastgele`() AS `C1`,
`Extent1`.`Id`,
`Extent1`.`Baslik`,
`Extent1`.`Tarih`
FROM `cmsicerikler` AS `Extent1`) AS `Project1`
 ORDER BY
`Project1`.`C1` ASC LIMIT 5

İşte olay budur.

Herkese kolay gelsin.