序列包含多个元素


110

我在通过Linq获取类型为“ RhsTruck”的列表并使它们显示时遇到一些问题。

RhsTruck仅具有属性Make,Model,Serial等... RhsCustomer具有属性CustomerName,CustomerAddress等...

我不断收到错误消息“序列包含多个元素”。有任何想法吗?我是否以错误的方式处理此问题?

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 <>,与SQL Top()聚合函数相同,.Take(1).SingleOrDefault();
Thein 2013年

Answers:


254

问题是您正在使用SingleOrDefault。仅当集合包含恰好包含0或1个元素时,此方法才会成功。我相信您正在寻找FirstOrDefault无论集合中有多少元素都能够成功。


8
加尔文,在这种情况下,您应该接受此答案作为解决方案
Dejan Milicic 2010年

24
-1 “问题在于您正在使用SingleOrDefault” -从我可以收集的信息中,OP正在寻找一个应该唯一的客户ID(我认为),因此,SingleOrDefault实际上比更为合适FirstOrDefault。而且,这实际上给OP的数据库设计带来了一个更严重的问题,因为它表明可以添加2个具有相同ID的客户!
詹姆斯

27
@ James,OP表示我的回答是正确的,但异常情况清楚地表明,集合中有多个要素无法SingleOrDefault正常工作。的确,这里可能有更好的数据库设计,但这似乎更适合作为OP的注释,而不是-1。
JaredPar 2010年

9
IMO的根本问题是数据库设计,因为它表明可以向数据库添加2个唯一的客户ID。SingleOrDefault之所以抛出异常,是因为该方法所期望的结果与所发现的结果之间存在不一致之处。因此,尽管您的回答阻止了例外,但对我来说,它实际上并不能解决问题,更多的是“摆脱监狱”卡,因此是-1。
詹姆斯

2
这是误导!SingleOrDefault然后,当您希望一个集合包含0或1个项目并且您想每次都检查这种情况时,它的用途就出现了
Achilles

23

SingleOrDefaultException如果序列中有多个元素,则方法抛出。

显然,您的查询中GetCustomer找到了多个匹配项。因此,您要么需要优化查询,要么很可能需要检查数据,以了解为什么对于给定的客户编号,您会获得多个结果。


5
Use FirstOrDefault insted of SingleOrDefault..

SingleOrDefault返回SINGLE元素;如果未找到任何元素,则返回null。如果在您的Enumerable中找到2个元素,则它将引发您所看到的异常

FirstOrDefault返回找到的FIRST元素;如果未找到任何元素,则返回null。因此,如果有2个元素与您的谓词匹配,则第二个元素将被忽略

   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

仅供参考,如果EF迁移尝试在未配置Db的情况下(例如在测试项目中)运行,也会出现此错误。

在我弄清楚它在查询中出错之前,已经进行了数小时的追踪,但这并不是因为查询,而是因为Migrations开始尝试创建Db。


0

正如@Mehmet指出的那样,如果您的结果返回的结果多于1个要素,那么您需要调查数据,因为我怀疑它不是设计使您拥有客户共享的客户编号。

但至此我想给您一个快速的概述。

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

欲了解更多Linq表达式,请查看System.Linq.Expressions

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.