Urutan berisi lebih dari satu elemen

110

Saya mengalami beberapa masalah saat mengambil daftar jenis "RhsTruck" melalui Linq dan menampilkannya.

RhsTruck hanya memiliki properti Make, Model, Serial dll. RhsCustomer memiliki properti CustomerName, CustomerAddress, dll ...

Saya terus mendapatkan error "Urutan berisi lebih dari satu elemen". Ada ide? Apakah saya melakukan pendekatan ini dengan cara yang salah?

public RhsCustomer GetCustomer(string customerNumber)
{
    using (RhsEbsDataContext context = new RhsEbsDataContext() )
    {
        RhsCustomer rc = (from x in context.custmasts
                          where x.kcustnum == customerNumber
                          select new RhsCustomer()
                        {
                            CustomerName = x.custname,
                            CustomerAddress = x.custadd + ", " + x.custcity
                            CustomerPhone = x.custphone,
                            CustomerFax = x.custfax
                        }).SingleOrDefault();
        return rc;
    }
}

public List<RhsTruck> GetEquipmentOwned(RhsCustomer cust)
{
    using (RhsEbsDataContext context = new RhsEbsDataContext())
    {
        var trucks = (from m in context.mkpops
                      join c in context.custmasts
                        on m.kcustnum equals c.kcustnum
                      where m.kcustnum == cust.CustomerNumber
                      select new RhsTruck
                    {
                        Make = m.kmfg,
                        Model = m.kmodel,
                        Serial = m.kserialnum,
                        EquipID = m.kserialno1,
                        IsRental = false
                    }).ToList();
        return trucks;
    }
}

protected void Page_Load(object sender, EventArgs e)
{
    string testCustNum = Page.Request.QueryString["custnum"].ToString();

    RhsCustomerRepository rcrep = new RhsCustomerRepository();
    RhsCustomer rc = rcrep.GetCustomer(testCustNum);
    List<RhsTruck> trucks = rcrep.GetEquipmentOwned(rc);

    // I want to display the List into a Gridview w/auto-generated columns
    GridViewTrucks.DataSource = trucks;
    GridViewTrucks.DataBind();   
}
Owen Blacker
sumber
1
Gunakan take <> , sama dengan fungsi agregat SQL Top () ,.Take(1).SingleOrDefault();
Thein

Jawaban:

254

Masalahnya adalah Anda sedang menggunakan SingleOrDefault. Metode ini hanya akan berhasil jika koleksi berisi tepat 0 atau 1 elemen. Saya yakin Anda sedang mencari FirstOrDefaultyang akan berhasil tidak peduli berapa banyak elemen yang ada dalam koleksinya.

JaredPar
sumber
8
Calvin, dalam hal ini Anda harus menerima jawaban ini sebagai solusi
Dejan Milicic
24
-1 "Masalahnya adalah Anda menggunakan SingleOrDefault" - dari apa yang saya dapat kumpulkan OP mencari id pelanggan yang (saya asumsikan) harus unik, oleh karena itu, SingleOrDefaultsebenarnya lebih tepat daripada FirstOrDefault. Juga, ini sebenarnya telah menimbulkan masalah yang lebih serius dengan desain database OP karena menunjukkan bahwa dimungkinkan untuk menambahkan 2 pelanggan dengan ID yang sama!
Yakobus
27
@ James, OP menyatakan bahwa jawaban saya benar dan pengecualian dengan jelas menyatakan bahwa koleksi memiliki lebih dari satu elemen yang mencegah SingleOrDefaultuntuk bekerja. Benar itu mungkin mungkin untuk memiliki desain database yang lebih baik di sini tapi yang tampaknya lebih tepat sebagai komentar pada OP dan tidak -1 pada jawaban.
JaredPar
9
IMO masalah yang mendasari pada akhirnya adalah desain DB karena menunjukkan bahwa 2 ID pelanggan unik dapat ditambahkan ke database. SingleOrDefaultmelempar pengecualian karena ada ketidakkonsistenan antara apa yang diharapkan metode dan apa yang ditemukannya. Jadi meskipun jawaban Anda menghentikan pengecualian, bagi saya, itu tidak benar-benar menyelesaikan masalah ini lebih merupakan kartu "keluar dari penjara" maka -1.
Yakobus
2
Ini menyesatkan! Penggunaan untuk SingleOrDefaultkemudian jatuh ketika Anda mengharapkan suatu koleksi memiliki 0 atau 1 item dan Anda ingin memeriksa ini terjadi setiap saat ...
Achilles
23

SingleOrDefaultMetode melempar Exceptionjika ada lebih dari satu elemen dalam urutan.

Tampaknya, kueri Anda di GetCustomermenemukan lebih dari satu kecocokan. Jadi, Anda perlu mempersempit kueri atau, kemungkinan besar, memeriksa data Anda untuk mengetahui mengapa Anda mendapatkan banyak hasil untuk nomor pelanggan tertentu.

Mehmet Aras
sumber
5
Use FirstOrDefault insted of SingleOrDefault..

SingleOrDefault mengembalikan elemen SINGLE atau null jika tidak ada elemen yang ditemukan. Jika 2 elemen ditemukan di Enumerable Anda maka itu melempar pengecualian yang Anda lihat

FirstOrDefault mengembalikan elemen FIRST yang ditemukannya atau null jika tidak ada elemen yang ditemukan. jadi jika ada 2 elemen yang cocok dengan predikat Anda, elemen kedua diabaikan

   public int GetPackage(int id,int emp)
           {
             int getpackages=Convert.ToInt32(EmployerSubscriptionPackage.GetAllData().Where(x
   => x.SubscriptionPackageID ==`enter code here` id && x.EmployerID==emp ).FirstOrDefault().ID);
               return getpackages;
           }

 1. var EmployerId = Convert.ToInt32(Session["EmployerId"]);
               var getpackage = GetPackage(employerSubscription.ID, EmployerId);
Muhammad Armaghan
sumber
1

FYI Anda juga bisa mendapatkan kesalahan ini jika Migrasi EF mencoba untuk berjalan tanpa Db dikonfigurasi, misalnya dalam Proyek Tes.

Mengejar ini selama berjam-jam sebelum saya menemukan bahwa itu adalah kesalahan pada kueri, tetapi, bukan karena kueri tetapi karena saat itulah Migrasi dimulai untuk mencoba membuat Db.

Chris Moschini
sumber
0

Seperti yang ditunjukkan oleh @Mehmet, jika hasil Anda mengembalikan lebih dari 1 elerment maka Anda perlu melihat ke dalam data Anda karena saya curiga bahwa bukan dengan desain bahwa Anda memiliki pelanggan yang berbagi nomor kustom.

Tapi to the point saya ingin memberi Anda gambaran singkat.

//success on 0 or 1 in the list, returns dafault() of whats in the list if 0
list.SingleOrDefault();
//success on 1 and only 1 in the list
list.Single();

//success on 0-n, returns first element in the list or default() if 0 
list.FirstOrDefault();
//success 1-n, returns the first element in the list
list.First();

//success on 0-n, returns first element in the list or default() if 0 
list.LastOrDefault();
//success 1-n, returns the last element in the list
list.Last();

untuk lebih banyak ekspresi Linq, lihat System.Linq.Expressions

Martin Sax
sumber