Ada jenis entitas yang disebut produk yang dihasilkan oleh kerangka kerja entitas. Saya telah menulis kueri ini
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
Kode di bawah ini melempar kesalahan berikut:
"Entitas atau tipe kompleks Shop.Produk tidak dapat dibangun dalam permintaan LINQ ke Entitas"
var products = productRepository.GetProducts(1).Tolist();
Tapi ketika saya menggunakannya select p
malah select new Product { Name = p.Name};
berfungsi dengan benar.
Bagaimana saya bisa membentuk bagian pilih kustom?
c#
entity-framework
Ghooti Farangi
sumber
sumber
Jawaban:
Anda tidak dapat (dan seharusnya tidak dapat) memproyeksikan ke entitas yang dipetakan. Namun, Anda dapat memproyeksikan ke jenis anonim atau ke DTO :
Dan metode Anda akan mengembalikan Daftar DTO.
sumber
Anda dapat memproyeksikan ke tipe anonim, dan kemudian dari itu ke tipe model
Sunting : Saya akan sedikit lebih spesifik karena pertanyaan ini mendapat banyak perhatian.
Anda tidak dapat memproyeksikan ke tipe model secara langsung (pembatasan EF), jadi tidak ada jalan lain untuk hal ini. Satu-satunya cara adalah memproyeksikan ke tipe anonim (iterasi 1), dan kemudian ke tipe model (iterasi ke-2).
Perlu diketahui juga bahwa ketika Anda memuat sebagian entitas dengan cara ini, mereka tidak dapat diperbarui, sehingga mereka harus tetap terpisah, sebagaimana adanya.
Saya tidak pernah benar-benar mengerti mengapa ini tidak mungkin, dan jawaban pada utas ini tidak memberikan alasan kuat untuk menolaknya (kebanyakan berbicara tentang data yang dimuat sebagian). Memang benar bahwa dalam entitas negara yang dimuat sebagian tidak dapat diperbarui, tetapi kemudian, entitas ini akan terlepas, sehingga upaya yang tidak disengaja untuk menyimpannya tidak mungkin dilakukan.
Pertimbangkan metode yang saya gunakan di atas: akibatnya kami masih memiliki entitas model yang dimuat sebagian. Entitas ini terpisah.
Pertimbangkan kode yang mungkin (ingin ada) ini:
Ini juga bisa menghasilkan daftar entitas yang terpisah, jadi kita tidak perlu membuat dua iterasi. Kompiler akan pintar untuk melihat bahwa AsNoTracking () telah digunakan, yang akan menghasilkan entitas yang terpisah, sehingga dapat memungkinkan kita untuk melakukan ini. Namun, jika AsNoTracking () dihilangkan, itu bisa melempar pengecualian yang sama seperti melempar sekarang, untuk memperingatkan kita bahwa kita perlu cukup spesifik tentang hasil yang kita inginkan.
sumber
Ada cara lain yang saya temukan bekerja, Anda harus membangun kelas yang berasal dari kelas Produk Anda dan menggunakannya. Contohnya:
Tidak yakin apakah ini "diizinkan", tetapi berhasil.
sumber
Ini adalah salah satu cara untuk melakukan ini tanpa mendeklarasikan kelas aditional:
Namun, ini hanya digunakan jika Anda ingin menggabungkan beberapa entitas dalam satu entitas. Fungsi di atas (pemetaan produk ke produk sederhana) dilakukan seperti ini:
sumber
Cara sederhana lain :)
sumber
.ToList
permintaan, itu dieksekusi dan menarik data dari server lalu apa gunanya membuatnya lagiAsQueryable
?Anda dapat menggunakan ini dan itu harus berfungsi -> Anda harus menggunakan
toList
sebelum membuat daftar baru menggunakan pilih:sumber
Menanggapi pertanyaan lain yang ditandai sebagai duplikat ( lihat di sini ) saya menemukan solusi cepat dan mudah berdasarkan jawaban Soren:
Catatan: Solusi ini hanya berfungsi jika Anda memiliki properti navigasi (kunci asing) pada kelas Tugas (di sini disebut 'Insiden'). Jika Anda tidak memilikinya, Anda bisa menggunakan salah satu solusi diposting lainnya dengan "AsQueryable ()".
sumber
Anda bisa menyelesaikan ini dengan menggunakan Data Transfer Objects (DTO's).
Ini sedikit mirip dengan viewmodels di mana Anda memasukkan properti yang Anda butuhkan dan Anda dapat memetakannya secara manual di controller Anda atau dengan menggunakan solusi pihak ketiga seperti AutoMapper.
Dengan DTO, Anda dapat:
Saya sudah belajar ini di sekolah tahun ini dan ini adalah alat yang sangat berguna.
sumber
Jika Anda menggunakan kerangka kerja Entity, kemudian coba hapus properti dari DbContext yang menggunakan model kompleks Anda sebagai Entity Saya memiliki masalah yang sama ketika memetakan banyak model ke dalam viewmodel bernama Entity
Menghapus entri dari DbContext memperbaiki kesalahan saya.
sumber
jika Anda Pelaksana,
Linq to Entity
Anda tidak dapat menggunakanClassType
dengannew
dalamselect
penutupan permintaanonly anonymous types are allowed (new without type)
lihat cuplikan proyek saya ini
Anda menambahkan
new keyword
dalam Pilih penutupan bahkan padacomplex properties
Anda akan mendapatkan kesalahan inikarena itu akan diubah menjadi pernyataan sql dan dieksekusi pada SqlServer
jadi kapan saya bisa menggunakan
new with types
padaselect
penutupan?Anda dapat menggunakannya jika Anda berurusan dengan
LINQ to Object (in memory collection)
setelah saya dieksekusi
ToList
pada query ituin memory collection
jadi kami bisa gunakannew ClassTypes
di pilihsumber
Dalam banyak kasus, transformasi tidak diperlukan. Pikirkan alasan Anda menginginkan Daftar dengan tipe sangat, dan evaluasi jika Anda hanya menginginkan data, misalnya, dalam layanan web atau untuk menampilkannya. Tidak masalah jenisnya. Anda hanya perlu tahu cara membacanya dan memeriksa apakah identik dengan properti yang didefinisikan dalam jenis anonim yang Anda tetapkan. Itu adalah skenario optimun, menyebabkan sesuatu yang Anda tidak perlu semua bidang suatu entitas, dan itulah alasan jenis anonim ada.
Cara sederhana adalah melakukan ini:
sumber
Itu tidak akan membiarkan Anda memetakan kembali ke Produk karena itu adalah tabel yang Anda tanyakan. Anda memerlukan fungsi anonim, kemudian Anda dapat menambahkannya ke ViewModel, dan menambahkan setiap ViewModel ke
List<MyViewModel>
dan mengembalikannya. Ini sedikit penyimpangan, tetapi saya memasukkan peringatan tentang menangani tanggal yang dapat dibatalkan karena ini adalah rasa sakit di belakang untuk ditangani, kalau-kalau Anda punya. Beginilah cara saya menanganinya.Semoga Anda memiliki
ProductViewModel
:Saya memiliki kerangka kerja injeksi / repositori dependensi tempat saya memanggil fungsi untuk mengambil data saya. Menggunakan pos Anda sebagai contoh, dalam panggilan fungsi Kontroler Anda, akan terlihat seperti ini:
Di kelas repositori:
Kembali ke controller, Anda lakukan:
sumber
hanya tambahkan AsEnumerable ():
sumber
Anda dapat menambahkan AsEnumerable ke koleksi Anda seperti yang berikut:
sumber