开发者

Linq inside of Linq causing sequence to return no results

开发者 https://www.devze.com 2023-04-11 16:44 出处:网络
Here are my classes: public class XDetail { public string Name { get; set; } public int ID { get; set; } }

Here are my classes:

public class XDetail
{
    public string Name { get; set; }
    public int ID { get; set; }
}

public class X
{
    public int XID { get; set; }
    public int ID { get; set; }
}

The ID is shared between them to link X and XDetail (one to many relationship). I read in a file using the following linq query and shape an anonymous type:

var results = from line in File.ReadAllLines(file)
              select new
              {
                  XID = int.Parse(line.Substring(0, 8).TrimStart('0')),
                  Name = line.Substring(8, 255).Trim()
              };

This data is used to check against existing X/XDetail to make appropriate changes or add new records. XList is a List and XDetailList is a List.

From there I attempt a fancy linq query to match up the appropriate items:

var changedData = from x in XList
                  join xDetail in XDetailList on x.ID equals xDetail.ID
                  where
   开发者_如何学运维               (!results.Any(p => p.XID.Equals(x.XID))
                  || !results.Any(p => p.Name.Equals(xDetail.Name)))
                  select new
                  {
                      XValue = x,
                      XDetailValue = xDetail,
                      Result = (from result in results 
                                where result.Name.Equals(xDetail.Name) 
                                select result).Single() // This line is my bane
                  };

So I can get the results I'm looking for shaped into that new anonymous type, but when I tried adding in that Result = ... inner linq query my whole set turns to: Sequence contains no elements. If I remove it I get the result set I was intending. X/XDetail are really typed DataRows that I need to use in processing farther down using the matched Result, but without that Result I will need to do a later linq query to find the match. I was hoping to do it in a psuedo-cool one step way.

I have tried changing Result to have no where clause and I can get a result, but the result I'm hoping to match on. Is there a better way to write this or a way to get the result set working again?


One problem is that results is an IEnumerable - so you are re-querying it every time which causes the File.ReadAllLines(file) to execute - effectively you are calling File.ReadAllLines(file) N times which does not sound healthy.

Instead you want to bring this enumeration into memory once - force eager execution with ToList():

var results = (from line in File.ReadAllLines(file)
              select new
              {
                  XID = int.Parse(line.Substring(0, 8).TrimStart('0')),
                  Name = line.Substring(8, 255).Trim()
              }).ToList();


Try changing your .Single to .SingleOrDefault. It is possible you are finding a row where the given x.Detail.Name isn't in your results set.

(Moving from a comment to answer so that it can be marked appropriately)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号