Subtleties dari Ekspresi Lambda di C #

Apa yang saya tulis di artikel, saya menangkap sekitar 10 jam, itu adalah 10 jam debug terus menerus yang dikurangi menjadi perbandingan langkah-demi-langkah dari versi kode yang bekerja dan yang tidak bekerja, bahkan tidak, untuk membandingkan setiap baris dari jendela debug versi versi kode yang bekerja dan yang tidak bekerja.


Untuk seorang programmer yang tidak terbiasa dengan pohon ekspresi, artikel pengantar yang bagus di msdn mengungkapkan secara rinci beberapa langkah dalam membangun pohon yang saya hilangkan dalam artikel.


Dalam hal ini tes ini akan berwarna hijau (add-in EF diaktifkan, di mana crash jika tidak dapat sepenuhnya menerjemahkan permintaan ke dalam SQL ).



  • Pertama, pemetaan bidang PupilName harus ditentukan jika tidak ditentukan. Penyedia Kueri tidak mengenali apa yang perlu diproyeksikan properti PupilName untuk menambahkan ke SQL ORDER BY .
  • Kedua, penyedia harus menguraikan pemetaan ini, misalnya, itu tidak akan berfungsi, EF akan mulai bersumpah (secara default tidak bersumpah, ia meningkatkan entitas dalam memori - LINQ ke Objek , tetapi ini dapat diaktifkan ):




Dan masalahnya adalah Penyedia Kueri tidak mengerti dengan properti apa dari entitas yang ingin kita sortir. Tetapi jika pemetaan ditulis dengan benar, penyedia akan mengatasinya, mengirim kueri SQL , menerima respons, dan membatalkan deserialisasi hasilnya.


Terkadang Anda perlu menulis Ekspresi sendiri, mis. Sesuatu yang serupa:



Saya akan menunjukkan kepada Anda bagaimana menulis Ekspresi ini, tidak begitu sulit, tautan di atas memberikan beberapa contoh serupa:



Kami mengumpulkan lambda langkah demi langkah, pertama-tama parameter, properti, dan kemudian merekatkan semuanya.
Dalam hal ini ini tidak akan berfungsi dan tes akan berwarna hijau (penyedia tidak akan dapat menguraikan ekspresi)?


Tidak tahu Jangan khawatir, saya juga tidak tahu, dan pada akhirnya saya menghabiskan sekitar 10 jam untuk mengerti.
Ini sebuah petunjuk, ini akan berhasil:



PupilDto mewarisi dari PupilDtoBase


Masalahnya adalah bahwa PropertyInfo perlu diambil dari kelas dasar jika properti PupilName itu sendiri milik kelas dasar, jadi C # membangun ekspresi lambda , dan EF mem-parsing mereka, bergantung pada standar bahasa


Bukti

Apa yang ditampilkan debugger jika Anda menulis lambda biasa di OrderBy :



Dan dalam kasus kami, seperti ini:



AutoMapper dan IncludeBase


Jika Anda mencoba untuk tidak menduplikasi kode, maka Anda mungkin menemukan warisan DTO dan IncludeBase :



Bahkan ada situasi yang lebih canggih:



Dan tes ini akan berwarna hijau:



Dan masalahnya sama, sekali lagi PropertyInfo ditarik dari antarmuka:



Bukti

Properti ReflectedType of the Age adalah sebuah antarmuka, IPupilDto , C # membangun lambda, di mana properti Age adalah properti dari kelas PupilDto, bukan antarmuka, tapi inilah cara pembuat mobil membuat lambda:



Bagaimana cara mengatasi masalah ini? Jika IncludeBase Automapper dengan antarmuka tidak sesuai dengan kami (jika Anda menggunakan pemetaan dalam memori - itu tidak akan memengaruhi Anda), maka Anda harus meninggalkan API ini, saya memecahkan masalah ini dengan menyoroti pemetaan dalam metode ekstensi , seperti ini:



Kemudian auto-mapper sendiri akan menemukan tipe properti yang sesuai dengan namanya, buat lambda yang "benar"
Terima kasih atas perhatian anda!

Source: https://habr.com/ru/post/id453720/


All Articles