Mam pewne problemy z przechwyceniem listy typu „RhsTruck” przez Linq i wyświetleniem ich.
RhsTruck ma tylko odpowiednie cechy Marka, model, numer seryjny itp ... RhsCustomer ma właściwości CustomerName, CustomerAddress itp ...
Ciągle otrzymuję błąd „Sekwencja zawiera więcej niż jeden element”. Jakieś pomysły? Czy podchodzę do tego w niewłaściwy sposób?
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();
}
.Take(1).SingleOrDefault();
Odpowiedzi:
Problem w tym, że używasz
SingleOrDefault
. Ta metoda powiedzie się tylko wtedy, gdy kolekcje zawierają dokładnie 0 lub 1 element. Wierzę, że szukasz tego,FirstOrDefault
który odniesie sukces bez względu na ilość elementów w kolekcji.źródło
SingleOrDefault
jest bardziej odpowiedni niżFirstOrDefault
. Ponadto spowodowało to poważniejszy problem z projektem bazy danych PO, ponieważ pokazuje, że możliwe jest dodanie 2 klientów o tym samym identyfikatorze!SingleOrDefault
działanie. Prawdą jest, że można tu mieć lepszy projekt bazy danych, ale wydaje się to bardziej odpowiednie jako komentarz do PO, a nie -1 do odpowiedzi.SingleOrDefault
zgłasza wyjątek, ponieważ istnieje niespójność między tym, czego oczekuje metoda, a tym, co znajduje. Więc chociaż twoja odpowiedź zatrzymuje wyjątek, dla mnie tak naprawdę nie rozwiązuje problemu, jest to raczej karta „wyjdź z więzienia bez więzienia”, stąd -1.SingleOrDefault
to przypada wtedy, gdy spodziewasz się, że kolekcja zawiera 0 lub 1 elementów i chcesz sprawdzić, czy dzieje się to za każdym razem ...SingleOrDefault
metoda zgłasza,Exception
jeśli w sekwencji jest więcej niż jeden element.Wygląda na to, że Twoje zapytanie w programie
GetCustomer
znajduje więcej niż jedno dopasowanie. Musisz więc albo zawęzić zapytanie, albo, najprawdopodobniej, sprawdzić dane, aby zobaczyć, dlaczego otrzymujesz wiele wyników dla danego numeru klienta.źródło
SingleOrDefault zwraca SINGLE element lub null, jeśli nie zostanie znaleziony żaden element. Jeśli w twoim Enumerable znajdują się 2 elementy, zgłasza wyjątek, który widzisz
FirstOrDefault zwraca PIERWSZY znaleziony element lub wartość null, jeśli nie zostanie znaleziony żaden element. więc jeśli istnieją 2 elementy, które pasują do twojego orzeczenia, drugi jest ignorowany
źródło
FYI, można również uzyskać ten błąd, jeśli migracje EF próbuje uruchomić bez skonfigurowanej bazy danych, na przykład w projekcie testowym.
Goniłem za tym przez wiele godzin, zanim zorientowałem się, że to błąd w zapytaniu, ale nie z powodu zapytania, ale dlatego, że wtedy włączyły się migracje, aby spróbować utworzyć bazę danych.
źródło
Jak wskazuje @Mehmet, jeśli Twój wynik zwraca więcej niż 1 elerment, musisz przyjrzeć się swoim danym, ponieważ podejrzewam, że nie jest to zgodne z projektem, że masz klientów udostępniających niestandardowy numer.
Ale do tego stopnia chciałem dać ci szybki przegląd.
więcej wyrażeń Linq znajdziesz w System.Linq.Expressions
źródło