Linq 内部的 Linq 导致序列不返回结果

发布于 2024-12-08 16:31:28 字数 1614 浏览 0 评论 0原文

这是我的类:

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 是一个列表,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
                  };

这样我就可以获得我正在寻找的结果,形成新的匿名类型,但是当我尝试添加 Result = ... 内部 linq 查询时,我的整个set 变为:序列不包含元素。如果我删除它,我会得到我想要的结果集。 X/XDetail 实际上是类型化的 DataRows,我需要在使用匹配的 Result 进行进一步处理时使用它们,但如果没有该 Result,我将需要执行稍后的 linq 查询来查找匹配项。我希望以一种伪酷的一步法来做到这一点。

我尝试将 Result 更改为没有 where 子句,并且可以获得结果,但我希望结果能够匹配。有没有更好的方法来编写这个或让结果集再次工作的方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白色秋天 2024-12-15 16:31:28

一个问题是结果是一个 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();

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();
一身软味 2024-12-15 16:31:28

尝试将 .Single 更改为 .SingleOrDefault。您可能会发现给定的 x.Detail.Name 不在结果集中的行。

(从评论转移到答案,以便可以对其进行适当标记)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文