Menyelesaikan masalah LINQ Joins dan In-Memory Collections
Ralat "Tidak dapat mencipta nilai tetap jenis... Hanya jenis primitif atau jenis penghitungan disokong dalam konteks ini" sering muncul apabila cuba memasukkan koleksi dalam memori (seperti ppCombined
dalam contoh ini) secara langsung ke dalam pertanyaan LINQ pangkalan data. Ini kerana pertanyaan pangkalan data beroperasi semata-mata pada data pemastautin pangkalan data; penyertaan dengan data dalam memori tidak disokong secara langsung.
Masalah itu biasanya nyata dalam klausa Select
pernyataan Join
. Percubaan untuk mencipta objek PersonDTO
, termasuk harta yang dihuni daripada koleksi dalam memori, menyebabkan konflik.
Punca Kegagalan LINQ JOIN
Ralat timbul daripada percubaan untuk melakukan operasi penapisan (Where
klausa) pada ppCombined
koleksi dalam pernyataan Select
pertanyaan pangkalan data. Enjin pangkalan data tidak dapat menterjemahkan operasi dalam memori ini kepada yang setara dengannya sendiri.
Penyelesaian: Pangkalan Data Asingkan dan Operasi Dalam Memori
Penyelesaian adalah untuk memisahkan pertanyaan pangkalan data daripada pemprosesan dalam memori. Ini melibatkan pelaksanaan pertanyaan pangkalan data terlebih dahulu, kemudian melakukan penapisan dan manipulasi data pada set data dalam memori yang terhasil. Kaedah AsEnumerable()
adalah kunci di sini. Ia memaksa pelaksanaan pertanyaan pangkalan data, mengembalikan hasil sebagai objek IEnumerable
, membenarkan operasi seterusnya berlaku sepenuhnya dalam ingatan.
Ini kod yang diperbetulkan:
<code class="language-csharp">var persons = db.Favorites .Where(f => f.userId == userId) .Join(db.Person, f => f.personId, p => p.personId, (f, p) => new { personId = p.personId, addressId = p.addressId, favoriteId = f.favoriteId }) .AsEnumerable() // Database query completes here .Select(x => new PersonDTO { personId = x.personId, addressId = x.addressId, favoriteId = x.favoriteId, personProtocol = ppCombined .Where(p => p.personId == x.personId) .Select(p => new PersonProtocol { personProtocolId = p.personProtocolId, activateDt = p.activateDt, personId = p.personId }) .ToList() });</code>
Dengan menggunakan AsEnumerable()
, pertanyaan pangkalan data dimuktamadkan dan pernyataan Select
berikutnya beroperasi semata-mata pada data yang diambil daripada pangkalan data, menyelesaikan ketidakserasian dengan koleksi ppCombined
dalam memori. Ini memastikan pertanyaan dilaksanakan dengan jayanya.
Atas ialah kandungan terperinci Mengapa LINQ JOIN Saya Gagal Apabila Menggunakan Koleksi Dalam Memori?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!