Chuỗi chứa nhiều hơn một phần tử


110

Tôi đang gặp một số vấn đề với việc lấy danh sách loại "RhsTruck" thông qua Linq và hiển thị chúng.

RhsTruck chỉ có các thuộc tính Make, Model, Serial, v.v. RhsCustomer có các thuộc tính CustomerName, CustomerAddress, v.v.

Tôi tiếp tục nhận được lỗi "Chuỗi chứa nhiều hơn một phần tử". Có ý kiến ​​gì không? Tôi đang tiếp cận điều này một cách sai lầm?

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
Sử dụng take <> , tương tự với hàm tổng hợp SQL Top () ,.Take(1).SingleOrDefault();
Thein

Câu trả lời:


254

Vấn đề là bạn đang sử dụng SingleOrDefault. Phương pháp này sẽ chỉ thành công khi các tập hợp chứa chính xác 0 hoặc 1 phần tử. Tôi tin rằng bạn đang tìm kiếm FirstOrDefaultthứ sẽ thành công dù có bao nhiêu phần tử trong bộ sưu tập.


8
Calvin, trong trường hợp đó, bạn nên chấp nhận câu trả lời này như một giải pháp
Dejan Milicic

24
-1 "Vấn đề là bạn đang sử dụng SingleOrDefault" - từ những gì tôi có thể thu thập, OP đang tìm kiếm một id khách hàng (tôi giả sử) phải là duy nhất, do đó, SingleOrDefaultthực sự phù hợp hơn FirstOrDefault. Ngoài ra, điều này thực sự đã làm nảy sinh một vấn đề nghiêm trọng hơn với thiết kế cơ sở dữ liệu của OP vì nó cho thấy rằng có thể thêm 2 khách hàng có cùng ID!
James

27
@James, OP đã nói rằng câu trả lời của tôi là đúng và ngoại lệ nói rõ rằng bộ sưu tập có nhiều hơn một phần tử ngăn không cho hoạt SingleOrDefaultđộng. Đúng, thể có một thiết kế cơ sở dữ liệu tốt hơn ở đây nhưng điều đó có vẻ thích hợp hơn khi nhận xét về OP chứ không phải -1 trên câu trả lời.
JaredPar

9
IMO, vấn đề cơ bản cuối cùng là thiết kế DB vì nó cho thấy rằng 2 ID khách hàng duy nhất có thể được thêm vào cơ sở dữ liệu. SingleOrDefaultđang ném ra một ngoại lệ vì có sự không nhất quán giữa những gì phương pháp mong đợi và những gì nó đang tìm kiếm. Vì vậy, mặc dù câu trả lời của bạn dừng ngoại lệ, đối với tôi, nó không thực sự giải quyết được vấn đề mà nó giống như một thẻ "thoát khỏi tù miễn phí" do đó là -1.
James

2
Điều này gây hiểu lầm! Việc sử dụng SingleOrDefaultsau đó rơi vào trường hợp bạn mong đợi một bộ sưu tập có 0 hoặc 1 mục và bạn muốn kiểm tra điều này xảy ra mọi lúc ...
Achilles

23

SingleOrDefaultphương thức ném một Exceptionnếu có nhiều hơn một phần tử trong chuỗi.

Rõ ràng, truy vấn của bạn trong GetCustomerđang tìm nhiều hơn một kết quả phù hợp. Vì vậy, bạn sẽ cần phải tinh chỉnh truy vấn của mình hoặc rất có thể, kiểm tra dữ liệu của bạn để xem tại sao bạn nhận được nhiều kết quả cho một số khách hàng nhất định.


5
Use FirstOrDefault insted of SingleOrDefault..

SingleOrDefault trả về một phần tử SINGLE hoặc null nếu không tìm thấy phần tử nào. Nếu 2 phần tử được tìm thấy trong Enumerable của bạn thì nó sẽ ném ra ngoại lệ mà bạn đang thấy

FirstOrDefault trả về phần tử ĐẦU TIÊN mà nó tìm thấy hoặc null nếu không tìm thấy phần tử nào. vì vậy nếu có 2 phần tử khớp với vị ngữ của bạn thì phần tử thứ hai sẽ bị bỏ qua

   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

FYI bạn cũng có thể gặp lỗi này nếu EF Migrations cố gắng chạy mà không có Db nào được định cấu hình, ví dụ như trong một Dự án thử nghiệm.

Đã theo đuổi điều này trong nhiều giờ trước khi tôi phát hiện ra rằng nó đang mắc lỗi trong một truy vấn, nhưng, không phải vì truy vấn mà vì đó là khi Migrations khởi động để cố gắng tạo Db.


0

Như @Mehmet đang chỉ ra, nếu kết quả của bạn trả về nhiều hơn 1 thư thì bạn cần phải xem xét dữ liệu của mình vì tôi nghi ngờ rằng dữ liệu của bạn không phải do thiết kế mà bạn có khách hàng chia sẻ số tùy chỉnh.

Nhưng tôi muốn cung cấp cho bạn một cái nhìn tổng quan nhanh chóng.

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

để biết thêm các biểu thức Linq, hãy xem System.Linq.Expressions

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.