Saya bekerja dengan C # dan .NET Framework 4.5.1 mengambil data dari database SQL Server dengan Entity Framework 6.1.3.
Aku punya ini:
codes = codesRepo.SearchFor(predicate)
.Select(c => new Tuple<string, byte>(c.Id, c.Flag))
.ToList();
Dan ketika saya menjalankannya, saya mendapatkan pesan ini:
Hanya konstruktor dan penginisialisasi tanpa parameter yang didukung di LINQ ke Entitas.
Saya tidak tahu bagaimana saya harus membuat Tuple karena semua contoh yang saya temukan kebanyakan seperti ini.
Saya sudah mencoba ini:
codes = codesRepo.SearchFor(predicate)
.Select(c => Tuple.Create(c.Id, c.Flag))
.ToList();
Dan dapatkan kesalahan ini:
LINQ ke Entitas tidak mengenali metode 'System.Tuple`2 [System.String, System.Byte] Buat metode [String, Byte] (System.String, Byte)', dan metode ini tidak dapat diterjemahkan ke dalam ekspresi penyimpanan.
Dimana masalahnya?
c#
entity-framework
linq
tuples
VansFannel
sumber
sumber
Jawaban:
Sementara jawaban oleh octavioccl karya, lebih baik untuk proyek pertama hasil query ke dalam jenis anonim, dan kemudian beralih ke Enumerable dan mengubahnya menjadi tupel. Dengan cara ini kueri Anda akan mengambil dari basis data hanya bidang yang diperlukan.
codes = codesRepo.SearchFor(predicate) .Select(c => new { c.Id, c.Flag }) .AsEnumerable() .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) .ToList();
Catatan: Aturan di atas berlaku untuk EF6. EF Core secara alami mendukung tupel (dalam proyeksi atau sebagai kunci gabungan / grup) melalui konstruktor tupel, misalnya kueri asli hanya berfungsi
codes = codesRepo.SearchFor(predicate) .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) .ToList();
tetapi bukan
Tuple.Create
metodenya (EF Core 2.x).sumber
.Select(c => new { c.Id, c.Flag, c.Foo?.Code })
tidak bekerja.?.
tidak didukung di pohon ekspresi. Tetapi selain itu, Anda dapat memperluas tipe anonim dengan nilai sebanyak yang Anda inginkan - jangan lupa untuk menamainya jika diperlukan :) misalnyac => new { c.Id, c.Flag, Code = (int?)c.Foo.Code }
Hanya jawaban yang diperbarui untuk C # 7, sekarang Anda dapat menggunakan sintaks yang lebih sederhana untuk membuat ValueTuple.
codes = codesRepo.SearchFor(predicate) .Select(c => new { c.Id, c.Flag }) .AsEnumerable() .Select(c => (c.Id, c.Flag)) .ToList();
Anda bahkan dapat memberi nama properti tupel sekarang:
codes = codesRepo.SearchFor(predicate) .Select(c => new { c.Id, c.Flag }) // anonymous type .AsEnumerable() .Select(c => (Id: c.Id, Flag: c.Flag)) // ValueTuple .ToList();
Jadi, alih-alih menggunakannya sebagai Item1 atau Item2, Anda dapat mengaksesnya sebagai Id atau Bendera.
Lebih banyak dokumen tentang memilih-antara-anonim-dan-tuple
sumber
Coba ini:
Telah diinformasikan bahwa ini tidak menerima LINQ untuk entitas.
Pilihan lainnya adalah menarik hasil ke dalam memori sebelum memilih. Jika Anda akan melakukan ini, saya akan merekomendasikan melakukan semua pemfilteran sebelum .AsEnumerable () karena itu berarti Anda hanya menarik kembali hasil yang Anda inginkan daripada menarik kembali seluruh tabel dan kemudian memfilter.
serta Tuple.Create (c.Id, c.Flag) dapat diubah menjadi Tuple baru (c.Id, c.Flag) jika Anda ingin membuat kode sedikit lebih eksplisit dalam jenis tupel
sumber
Di linq ke entitas Anda dapat memproyeksikan ke jenis anonim atau ke DTO. Untuk menghindari masalah itu Anda dapat menggunakan
AsEnumerable
metode ekstensi:codes = codesRepo.SearchFor(predicate).AsEnumerable(). .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) .ToList();
Metode ini memungkinkan Anda bekerja dengan Lini ke Objek alih-alih Lini ke Entitas , jadi setelah memanggilnya, Anda dapat memproyeksikan hasil kueri Anda dalam apa pun yang Anda butuhkan. Keuntungan menggunakan
AsEnumerable
sebagai gantinyaToList
adalahAsEnumerable
tidak mengeksekusi kueri, itu mempertahankan eksekusi yang ditangguhkan. Sebaiknya selalu filter data Anda terlebih dahulu sebelum memanggil salah satu metode ini.sumber
Saya telah menemukan jawabannya:
sumber
Gunakan metode ini untuk melakukan ini dan menggunakan async.
var codes = await codesRepo.SearchFor(predicate) .Select(s => new { Id = s.Id, Flag = s.Flag }).FirstOrDefaultAsync(); var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);
sumber
Hanya dua sen saya: ini telah menarik perhatian saya beberapa kali dengan nama tipe:
Beberapa contoh yang tidak tepat:
private Tuple<string, byte> v1() { return new Tuple<string, byte>("", 1); } private (string, int) v2() { return ("", 1); } private (string Id, byte Flag) v3() { return ("", 1); }
Salam.
sumber
public (string Id, byte Flag) SearchFor(Expression predicate)
, tapi ini bukan intinya. Dua sen seharusnya bukan jawaban, tapi komentar.