Yazılım Mimarileri ve Tasarım Desenleri Üzerine

Entity Framework’te Unable To Create A Constant Value Of Type ‘xxx’. Only Primitive Types Or Enumeration Types Are Supported In This Context Hatası ve Çözümü

Merhaba,

Geçenlerde üzerine çalıştığım bir projede almış olduğum bir hata üzerine konuşuyor olacağız. Bu hatanın diğerlerinden farkı belli başlı, tespit edilebilir durumlarda karşılaşabilmemizden ziyade; birden fazla sergilenen yaklaşımda karşılaşılabilen ve geniş yelpazeli bir olası hata olmasıdır.

İnceleyeceğimiz hata makalemizin başlığında olduğu gibi

Entity Framework’te Unable To Create A Constant Value Of Type ‘xxx’. Only Primitive Types Or Enumeration Types Are Supported In This Context

hatasıdır.

Bu hata; Entity Framework, LINQ vs. gibi Framework yapılarında genellikle tanımlanmayan veri türleri üzerinde alınan bir hatadır. Zaten hatada da bahsedilen yapılan çalışma(artık ne ise)da üzerinde çalışılan veri türünün bilinen türlerden yahut numaralandırıcılardan olması gerekiyor.

Şimdi bizler bir kaç örnek durumu ele alarak ilgili hata durumunu gözlemleyecek ve ardından çözümler üzerine istişare ederek bir sonuca varacağız.

Öncelikle vereceğimiz örneklendirmelerde Entity Framework üzerinden çalışmalarımızı icra edeceğimizi şimdiden bildiririm.

İlk başta aşağıdaki örneği inceleyelim.

            NorthwindEntities vt = new NorthwindEntities();
            Personeller p = new Personeller { Adi = "Nancy", SoyAdi = "Davaleo" };
            vt.Set<Personeller>().Contains(p);

Dikkat ederseniz “Set<Personeller>()” metodundan dönen sonuç üzerinden “Contains” metodu ile veri eşleştirme sonucu sorgulanmaktadır. Bu komutları derleyip çalıştırdığımız zaman aşağıdaki sonuçla karşılaşmaktayız.

Görüldüğü üzere “Set<Personeller>()” metodunun tipi “System.Data.Entity.DbSet<Personeller>”dir. Buradaki çalışmada “Set<Personeller>()” metodu neticesinde dönen sonucu “.ToList()” metodu ile List koleksiyonuna çevirdiğimiz zaman sorunumuz çözülecektir.

            NorthwindEntities vt = new NorthwindEntities();
            Personeller p = new Personeller { Adi = "Nancy", SoyAdi = "Davaleo" };
            vt.Set<Personeller>().ToList().Contains(p);

Dikkatinizi “System.Data.Entity.DbSet<T>” tipine çekmek istiyorum. 😉

Bir başka örneği incelersek eğer,

            NorthwindEntities vt = new NorthwindEntities();
            var Personeller = (from personel in vt.Personeller
                               select personel
                               ).ToList();

            var Satislar = (from satislar in vt.Satislar
                            where 
                            (Personeller.Any
                            (p => p.PersonelID == satislar.PersonelID))
                            select satislar).ToList();

Buradaki duruma göz atarsak eğer;

“List<Personeller>” ile “DbSet<Satislar>” koleksiyonları içerisinden alınan veriler üzerinde bir karşılaştırılma yapılmaktadır. Bu kodu derleyip çalıştırdığımızda da aşağıdaki aslen konumuzla alakalı durumla karşılaşılacaktır.

Haliyle tekrardan şaibe yaratan “DbSet<T>” metodu kullanılmaktadır. Yapmamız gereken karşılaştırmada rol alan iki tipten birini diğerine benzetmektir.

1. Yol 2. Yol
Görüldüğü üzere Satislar tablosunu .ToList metodu ile List tipine çevirebiliriz. Ya da Personeller sorgusundaki .ToList metodunu silerek sorgu sonucunu koleksiyon olarak elde etmekten vaz geçeriz. Haliyle görüldüğü üzere IQueryable<T> tipinden sonucu elde ederiz.

Aşağıda da görüldüğü üzere IQueryable<T> tipi aslen DbSet<T> referansının Base Class’ıdır. O yüzden amacımız olan benzerleştirme işlemimiz başarılı olmuştur diyebiliriz.

Bu örneğimizde, DbSet<T> tipiyle yapılan çalışmalarda dikkatli olmanız gerektiğini tekrardan göstermiş olmaktadır. 😉

Ve son olarak aşağıdaki durumu inceleyelim.

            NorthwindEntities vt = new NorthwindEntities();
            var Personel = vt.Personeller.Where(p => p.PersonelID == 3).DefaultIfEmpty(new Personeller { Adi = "Gençay", SoyAdi = "Yıldız" }).First();

Bu koduda derleyip çalıştırdığımız zaman beklenilen durumla karşılaşmaktayız.

Dikkat edilirse eğer Personeller DbSet<T> iken DefaultIfEmpty metodu generic yapısından dolayı DbSet<T>’nin base classı IQueryable<T> olarak gelmektedir. Haliyle bu iki metod sonuç olarak aynıdır. Ama sonuncu metodumuz First ise geriye sadece Personeller tipi döneceğinden dolayı bu hata kaçınılmaz olmaktadır.

Yapmamız gereken ortadaki tip farkını kaldırmaktır.

Görüldüğü üzere .ToList metodu sayesinde bu işlemi başarıyla gerçekleştirebilmekteyiz.

Burada da DbSet<T> tipiyle yapılan çalışmalarda dikkatli ve tetikte olmanızı bir kez daha vurgulamış olalım. 😉 🙂

Evet…
Bir uzun ve zahmetli yazının daha sonuna gelmiş bulunmaktayız.
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Mobil sürümden çık