Saya punya pertanyaan ini:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
Apa yang akan terjadi maxShoeSize
jika perusahaan 8 tidak memiliki pekerja sama sekali?
UPDATE:
Bagaimana saya bisa mengubah kueri untuk mendapatkan 0 dan bukan pengecualian?
maxShoeSize
?" jika Anda sudah mencobanya.Jawaban:
Titik nol
DefaultIfEmpty
tidak perlu.sumber
Max()
urutan kosong menghasilkan kesalahan.Saya tahu ini adalah pertanyaan lama dan jawaban yang diterima berfungsi, tetapi pertanyaan ini menjawab pertanyaan saya tentang apakah set kosong seperti itu akan menghasilkan pengecualian atau
default(int)
hasil.Namun jawaban yang diterima, meskipun berhasil, bukanlah solusi IMHO yang ideal, yang tidak diberikan di sini. Jadi saya memberikannya dalam jawaban saya sendiri untuk kepentingan siapa saja yang mencarinya.
Kode asli OP adalah:
Ini adalah bagaimana saya akan menulisnya untuk mencegah pengecualian dan memberikan hasil default:
Ini menyebabkan tipe
Max
fungsi yang dikembalikanint?
, yang memungkinkannull
hasilnya dan kemudian??
menggantikannull
hasilnya dengan0
.EDIT
Hanya untuk memperjelas sesuatu dari komentar, Entity Framework saat ini tidak mendukung
as
kata kunci, jadi cara untuk menuliskannya ketika bekerja dengan EF adalah:Karena itu
[TypeOfWorkers]
bisa menjadi nama kelas yang panjang dan membosankan untuk ditulis, saya telah menambahkan metode ekstensi untuk membantu.Ini hanya menangani
int
, tapi sama bisa dilakukan untuklong
,double
, atau jenis nilai lain yang Anda perlu. Menggunakan metode ekstensi ini sangat sederhana, Anda hanya meneruskan fungsi pemilih Anda dan secara opsional memasukkan nilai yang akan digunakan untuk null, yang defaultnya ke 0. Jadi di atas bisa ditulis ulang seperti:Semoga itu membantu orang lebih banyak.
sumber
DefaultIfEmpty
hanya berfungsi dengan baik ketikaMax
tidak melakukan evaluasi.Select
sebagai perantara ketika saya hanya akan menggunakan fungsi agregat sepertiMax
pada hasilnya. Saya juga berpikir (saya belum menguji ini) bahwa SQL yang dihasilkan akan menggunakan query subselect tambahan dengan melakukan itu, sementara saya hanya akan berurusan dengan set kosong dengan mengembalikan nol. Terima kasih atas upvote dan umpan baliknya! ;)ShoeSize
itu benar-benar dalam terkaitUniform
entitas, saya tidak akan menggunakanWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, bukannya saya hanya akan menjaga seluruh evaluasi dalamMax
fungsi:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Saya lebih suka menggunakan metode sesedikit mungkin dalam pertanyaan saya untuk memungkinkan EF memiliki kebebasan terbesar dalam memutuskan bagaimana membangun pertanyaan secara efisien. ;-)public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
Maks () tidak akan mengembalikan apa pun dalam hal ini.
Ini akan meningkatkan InvalidOperationException karena sumber tidak mengandung elemen.
sumber
InvalidOperationException
jika objek dalam daftar adalah tipe yang tidak dapat dibatalkansumber
Jika ini Linq to SQL, saya tidak suka menggunakan
Any()
karena menghasilkan beberapa permintaan ke SQL server.Jika
ShoeSize
bukan bidang yang dapat dibatalkan, maka hanya menggunakan.Max(..) ?? 0
tidak akan berfungsi tetapi akan berikut:Ini benar-benar tidak mengubah SQL yang dipancarkan, tetapi mengembalikan 0 jika urutannya kosong karena mengubah
Max()
untuk mengembalikanint?
bukanint
.sumber
(dengan asumsi itu
ShoeSize
adalah tipeint
)Jika
Workers
aDbSet
atauObjectSet
dari Entity Framework kueri awal Anda akan melemparInvalidOperationException
, tetapi tidak mengeluh tentang urutan kosong tetapi mengeluh bahwa nilai yang terwujud NULL tidak dapat dikonversi menjadiint
.sumber
Max akan melempar System.InvalidOperationException "Urutan tidak mengandung elemen"
sumber
NB: permintaan dengan
DefaultIfEmpty()
mungkin jauh lebih lambat . Dalam kasus saya itu adalah kueri sederhana dengan.DefaultIfEmpty(DateTime.Now.Date)
.Saya terlalu malas untuk menggambarkannya, tetapi jelas EF mencoba untuk mendapatkan semua baris dan kemudian mengambil
Max()
nilainya.Kesimpulan: terkadang penanganan
InvalidOperationException
mungkin merupakan pilihan yang lebih baik.sumber
Anda dapat menggunakan terner di dalam
.Max()
untuk menangani predikat dan menetapkan nilainya;Anda perlu menangani
Workers
koleksi menjadi nol / kosong jika itu suatu kemungkinan, tetapi itu tergantung pada implementasi Anda.sumber
Anda dapat mencoba ini:
sumber
Anda dapat memeriksa apakah ada pekerja sebelum melakukan Max ().
sumber