以下是我的课程:
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; }
}
它们之间共享ID以链接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是List,XDetailList是List。
从那里我尝试一个花哨的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
};
所以我可以得到我正在寻找新的匿名类型的结果,但是当我尝试添加Result = ...内部linq查询时,我的整个集转向:Sequence不包含任何元素。如果我删除它,我得到我想要的结果集。 X / XDetail是真正类型化的DataRows,我需要在使用匹配的Result进行更远的处理时使用它,但如果没有那个Result,我将需要稍后执行linq查询来查找匹配。我希望以一种很酷的方式一步到位。
我已经尝试将Result更改为没有where子句,我可以得到一个结果,但是我希望匹配的结果。是否有更好的方法来编写此方法或使结果集再次运行的方法?
答案 0 :(得分:4)
一个问题是结果是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 :(得分:1)
尝试将.Single更改为.SingleOrDefault。您可能正在查找给定x.Detail.Name不在结果集中的行。
(从评论转到答案,以便可以适当标记)