Sıra birden fazla öğe içeriyor


111

Linq aracılığıyla "RhsTruck" türü bir liste alma ve bunları gösterme konusunda bazı sorunlar yaşıyorum.

RhsTruck sadece Marka, Model, Seri vb. Özelliklere sahiptir ... RhsCustomer, CustomerName, CustomerAddress vb. Özelliklere sahiptir.

"Sıra birden fazla öğe içeriyor" hatasını alıyorum. Herhangi bir fikir? Buna yanlış şekilde mi yaklaşıyorum?

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();   
}

1
Take <> kullanın , SQL Top () toplama işlevi ile aynı ,.Take(1).SingleOrDefault();
Thein

Yanıtlar:


255

Sorun şu ki, kullanıyorsun SingleOrDefault. Bu yöntem yalnızca koleksiyonlar tam olarak 0 veya 1 öğe içerdiğinde başarılı olacaktır. FirstOrDefaultKoleksiyonda ne kadar öğe olursa olsun hangisinin başarılı olacağını aradığına inanıyorum .


8
Calvin, bu durumda bu cevabı bir çözüm olarak kabul etmelisin
Dejan Milicic

24
-1 "Sorun, SingleOrDefault kullanıyorsunuz" - elde edebileceğim kadarıyla OP, benzersiz olması gereken (varsayıyorum) bir müşteri kimliği arıyor, bu nedenle, SingleOrDefaultaslında daha uygun FirstOrDefault. Ayrıca, aynı ID'ye sahip 2 müşteri eklemenin mümkün olduğunu gösterdiğinden, bu aslında OP'nin veritabanı tasarımında daha ciddi bir problem yarattı!
James

27
@ James, OP cevabımın doğru olduğunu ve istisnanın koleksiyonun SingleOrDefaulthiç çalışmayı engelleyen birden fazla unsuru olduğunu açıkça belirtti . Doğru, burada daha iyi bir veritabanı tasarımına sahip olmak mümkün olabilir, ancak bu OP'ye ilişkin bir yorum olarak daha uygun görünmektedir ve bir yanıt için -1 değil.
JaredPar

9
IMO, veritabanına 2 benzersiz müşteri kimliğinin eklenebileceğini gösterdiğinden, temelde yatan sorun, sonuçta DB tasarımıdır. SingleOrDefaultyöntemin beklediği ile bulduğu arasında bir tutarsızlık olduğu için bir istisna atmaktır. Yani cevabınız istisnayı durdursa da, benim için aslında sorunu çözmüyor, daha çok "hapisten çıkma" kartı, dolayısıyla -1.
James

2
Bu yanıltıcıdır! SingleOrDefaultBir koleksiyonun 0 veya 1 öğeye sahip olmasını beklediğinizde ve bunun her seferinde olduğunu kontrol etmek istediğinizde kullanım o zaman devreye girer ...
Achilles

24

SingleOrDefaultyöntem Exceptiondizide birden fazla öğe varsa bir atar .

Görünüşe göre, sorgunuz GetCustomerbirden fazla eşleşme buluyor. Bu nedenle, sorgunuzu hassaslaştırmanız veya büyük olasılıkla belirli bir müşteri numarası için neden birden fazla sonuç aldığınızı görmek için verilerinizi kontrol etmeniz gerekecektir.


5
Use FirstOrDefault insted of SingleOrDefault..

SingleOrDefault, herhangi bir öğe bulunmazsa TEK bir öğe veya boş döndürür. Numaralandırıcınızda 2 öğe bulunursa, gördüğünüz istisnayı atar

FirstOrDefault, herhangi bir öğe bulunmazsa bulduğu İLK öğeyi veya boş değerini döndürür. yani yükleminizle eşleşen 2 öğe varsa ikincisi yok sayılır

   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);

1

Bilginize, bu hatayı, örneğin bir Test Projesinde, EF Geçişlerinin Db yapılandırılmadan çalıştırmaya çalışması durumunda da alabilirsiniz.

Bunu bir sorguda hata yaptığını anlamadan önce saatlerce takip ettim, ancak sorgu yüzünden değil, Migration'ın Db'yi oluşturmaya çalıştığı zamandı.


0

@Mehmet'in işaret ettiği gibi, eğer sonucunuz 1 elermentten daha fazla dönüyorsa, o zaman verilerinize bakmanız gerekir, çünkü bunun tasarım gereği özel bir numarayı paylaşan müşterileriniz olduğundan şüpheleniyorum.

Ama size hızlı bir genel bakış vermek istedim.

//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();

daha fazla Linq ifadesi için System.Linq.Expressions'a bakın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.