‘LINQ to Entities Does Not Recognize The Method ‘Int32 ToInt32(System.Object)’ Method, And This Method Cannot Be Translated Unto A Store Expression.’ Hatası ve Çözümü
Merhaba,
Projelerimizde kullandığımız ve bizlere Entity Data Modeller üzerinde hızlı bir şekilde sorgulama imkanı sağlayan LINQ sorguları üzerinde başlıkta da gördüğünüz gibi aşağıdaki olası hatayı alabilirsiniz.
System.NotSupportedException: ‘LINQ to Entities does not recognize the method ‘Int32 ToInt32(System.Object)’ method, and this method cannot be translated into a store expression.’
Hatamızın görsel hali ise aşağıdaki gibidir;
Evet… Karşılaşılması muhtemel hatamız budur. Peki bu hatayı neden almaktayız?
Öncelikle şunu belirtmeliyim ki, LINQ teknolojisini kullanırken sorgu mantığını göz önüne almazsak bu hatayla karşılaşmamız oldukça yüksek ihtimaldir. Nihayetinde ben bir çalışma esnasında bu mantığı göz ardı ettiğim için bu hataya haddinden fazla mağruz kalıp uygulama tasarımını farklı bir şekilde inşa etmek durumunda kalmış bulunmaktayım.
“Peki ne hoca bu mantık?” diye sabırsızca sorduğunuzu duyar gibiyim. Hadi gelin açıklayalım.
LINQ sorgularında yazmış olduğumuz kalıp veritabanında çalıştırılacak sorguyu hazırlamaktadırlar. Eee haliyle ilgili kalıbı yazmak demek; sorguyu oluşturup, veritabanında çalıştırıp ardından sonucu getirir manasına gelmemektedir.
Şimdi aşağıdaki kod bloğunu ele alalım.
Northwind2Entities db = new Northwind2Entities(); var Personeller = from Personel in db.Personeller select Personel;
Bu kod bloğundaki kalıp, ilgili sorguyu veritabanına gönderip gelen veri kümesini var tipinden Personeller referansına
atamamaktadır ! ! ! Çünkü bu kalıp sadece sorguyu hazırlamaktadır. Yapılan LINQ sorgusunun veritabanında execute edilmesi için herhangi bir yapı tarafından çağırılması gerekmektedir. Örneğin bu yapı foreach döngüsü olabilir;
|Çağrılmadan Önce||Çağrıldıktan Sonra|
Dikkat ederseniz LINQ sorgumuz foreach tarafından çağrıldığı zaman sorgu haline getirilip veritabanında execute edilmiştir.
foreach döngüsünden ziyade LINQ sorgusu neticesinde .ToList() metodu çağrılırsa eğer tekrardan ilgili ifade veritabanında execute edilecektir.
Bizler LINQ sorgularının iterasyonel ya da fonksiyonel çağrım sonucu çalıştırılmalarına Ertelenmiş Çalışma(Deferred Execution) demekteyiz.
İşte… LINQ sorgularını oluştururken göz önüne almamız gereken yapısal mantık bu Deferred Execution olayıdır.
Konumuz olan “LINQ to Entities does not recognize the method ‘Int32 ToInt32(System.Object)’ method, and this method cannot be translated into a store expression.” hatası ise bu bahsettiğim LINQ sorgu mekanizmasına rağmen aşağıdaki gibi bir kullanım sergilemekten kaynaklanmaktadır.
Görüldüğü üzere .ToList() metodu çağrılana kadar ilgili LINQ sorgusu bünyesinde bir Convert işlemi yapılmaya çalışılmıştır. Eee haliyle compiler elde bir sorgu olmadığı için Convert.ToInt32 metodunun T-SQL karşılığını bulamayacağından dolayı bu hatayı vermektedir. Bu hata aşağıdaki gibi bir manevrayla rahatlıkla aşılabilmektedir.
public ActionResult Index(int? id) { Northwind2Entities db = new Northwind2Entities(); if (id != null) { int ID = Convert.ToInt32(id); var GelenPersonel = (from Personel in db.Personeller where Personel.PersonelID == ID select Personel).ToList(); } return View(); }
Yani LINQ sorgusunun içerisinde bir Convert işlemi yapmaktansa bu işlemi sorgu dışında gerçekleştirip, ardından elde edilen değeri direkt olarak sorguya eklememiz bu hatadan kurtulmanızı sağlayacaktır.
Benzer şekilde aşağıdaki Extension metot yapıları ile sorgulama içinde geçerli olacaktır.
Yapmamız gereken bir önceki örnekte verilen çözümü uygulamak, yani sorgu içerisindeki Convert işlemini dışarıda halletmek yeterli olacaktır.
public ActionResult Index(int? id) { Northwind2Entities db = new Northwind2Entities(); int ID = Convert.ToInt32(id); if (id != null) db.Personeller.FirstOrDefault(y => y.PersonelID == ID); return View(); }
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…