Linq внутри Linq вызывает последовательность, которая не возвращает результатов - PullRequest
3 голосов
/ 07 октября 2011

Вот мои классы:

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

Идентификатор разделяется между ними, чтобы связать X и XDetail (отношение один ко многим).Я читаю в файле, используя следующий запрос linq, и формирую анонимный тип:

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

Эти данные используются для проверки существующего X / XDetail для внесения соответствующих изменений или добавления новых записей.XList - это список, а XDetailList - это список.

Оттуда я пытаюсь выполнить причудливый запрос linq для сопоставления соответствующих элементов:

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

Таким образом, я могу получить результаты, которые ищуfor сформированный в этот новый анонимный тип, но когда я попытался добавить в этот Result = ... внутренний запрос linq, весь мой набор превращается в: Sequence не содержит элементов.Если я удаляю это, я получаю набор результатов, который я намеревался.X / XDetail - это действительно типизированные DataRow, которые мне нужно использовать при дальнейшей обработке с использованием соответствующего Result, но без этого мне потребуется выполнить более поздний запрос linq, чтобы найти совпадение.Я надеялся сделать это псевдо-круто в один шаг.

Я пытался изменить Result, чтобы не иметь условия where, и я могу получить результат, но результат, на который я надеюсь соответствовать.Есть ли лучший способ написать это или способ заставить набор результатов работать снова?

Ответы [ 2 ]

4 голосов
/ 07 октября 2011

Одной из проблем является то, что результатом является IEnumerable - поэтому вы запрашиваете его каждый раз, что приводит к выполнению File.ReadAllLines(file) - фактически вы звоните File.ReadAllLines(file) N раз, что не кажется здоровым.

Вместо этого вы хотите перенести это перечисление в память один раз - принудительное выполнение с помощью 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();
1 голос
/ 07 октября 2011

Попробуйте изменить .Single на .SingleOrDefault.Возможно, вы находите строку, в которой данное x.Detail.Name отсутствует в наборе результатов.

(переход от комментария к ответу, чтобы его можно было соответствующим образом пометить)

...