【问题标题】:Linq query producing incorrect resultLinq 查询产生不正确的结果
【发布时间】:2017-04-06 00:00:37
【问题描述】:

考虑以下linq查询

var result = from a in 
                 from b in filledTable
                 join c in distinctList on b[0].SerialNumber equals c.Field("SERIAL NUMBER")
                 select new { b, c }
             group a by new { a.b[0].SerialNumber } into d
             select new
             {
               Id = d.Select(x => x.b[0].Id),
               SerialNumber = d.Select(x => x.b[0].SerialNumber),
               // This part is not producing the correct output.
               ImportTable = d.Select(w => w.c.Table
                                              .AsEnumerable()
                                              .GroupBy(y => y.Field("SERIAL NUMBER"))
                                              .Select(z => z.First())
                                              .CopyToData‌​Table())
             };

filledTable 在我的 linq 查询中是 List<dynamic>,它由从 sproc 返回的值填充,distinctListList<DataRow>,我将来自 DataTable 的值区分为如下:

List<DataRow> distinctList = dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList();

我的Linq 查询产生以下JSON

[
{
"FilledTableList":[
  [
    {
      "Id":[
        2
      ],
      "SerialNumber":[
        "1073410"
      ],
      "ImportTable":[
        [
          {
            "SERIAL NUMBER":"1073410",
            "PRODUCT TYPE":"Product A"
          },
          {
            "SERIAL NUMBER":"1073411",
            "PRODUCT TYPE":"Product B"
          }
        ]
      ]
    },
    {
      "Id":[
        -1
      ],
      "SerialNumber":[
        "1073411"
      ],
      "ImportTable":[
        [
          {
            "SERIAL NUMBER":"1073410",
            "PRODUCT TYPE":"Proeduct A"
          },
          {
            "SERIAL NUMBER":"1073411",
            "PRODUCT TYPE":"Product B"
          }
        ]
      ]
    }
  ]
]
}]

但我想要以下JSON 输出

[
{
"FilledTableList":[
  [
    {
      "Id":[
        2
      ],
      "SerialNumber":[
        "1073410"
      ],
      "ImportTable":[
        [
          {
            "SERIAL NUMBER":"1073410",
            "PRODUCT TYPE":"Product A"
          }
        ]
      ]
    },
    {
      "Id":[
        -1
      ],
      "SerialNumber":[
        "1073411"
      ],
      "ImporTable":[
        [
          {
            "SERIAL NUMBER":"1073411",
            "PRODUCT TYPE":"Product B"
          }
        ]
      ]
    }
  ]
]
}]

所以ImportTable节点只包含与上面FilleTabledList节点中的序列号匹配的信息。除此之外,其他一切似乎都按Linq 查询的预期工作。谁能告诉我哪里出错了

更新:

我的filledTable 包含以下两项:

{ Id = 2, SerialNumber = "1073410"}
{ Id = -1, SerialNumber = "1073411"}

最终我将在列表中包含更多项目,但为了弄清楚为什么更多 linq 查询不起作用,我将其范围缩小到仅项目

【问题讨论】:

  • 所以你想要 return public List> FilledTableList { get;放; }?这是您尝试返回的内容。您的 JSON 仍然不正确。
  • @mww 是的,如果可能的话
  • 很难重现您的问题,因为您没有提供任何源数据。您能否为您希望从中生成输出的填充表(4 - 10 个元素)填写一些源数据(我认为 distinctList 仅包含一个序列号为 1073411 的元素)?
  • @Oliver 我的DataTable 中的初始值由我手动组成的 4 个序列组成,分别由 1073410*、**10734101073411, 1073410 所以当我使用dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList(); 来获取不同的值时,我会得到两个元素,它们分别是 10734101073411跨度>
  • @Oliver 我也更新了我的问题

标签: c# json linq


【解决方案1】:

created a fiddle,这样可以更轻松地传达可用数据和预期结果。

当我理解正确时,您喜欢获取所有产品的列表,列在填充表中,然后从数据表中找到具有相同序列号的所有元素。

如果这是正确的,那么 LINQ 查询必须是:

    var result = filledTable.GroupJoin(distinctList, product => product.SerialNumber, row => row.Field<string>("SERIAL NUMBER"), (Product, Rows) => new { Product, Rows })
                            .Select(group => new
                                    {
                                        Id = group.Product.Id,
                                        SerialNumber = group.Product.SerialNumber,
                                        ImportTable = group.Rows.CopyToDataTable()
                                    });

结果是

[
  {
    "Id": 2,
    "SerialNumber": "1073410",
    "ImportTable": [
      {
        "SERIAL NUMBER": "1073410",
        "PRODUCT TYPE": "Product A"
      }
    ]
  },
  {
    "Id": -1,
    "SerialNumber": "1073411",
    "ImportTable": [
      {
        "SERIAL NUMBER": "1073411",
        "PRODUCT TYPE": "Product B"
      }
    ]
  }
]

【讨论】:

  • 实际上,据我了解,distinctList 中的每个特定序列号最多会有一行。因此,如果您尝试压缩 json,则不需要当前形式的 ImportTable
  • 谢谢你,我会试试看的。如果我要从ImporTable 中移动这些项目并将它们全部作为一个项目,那只是一个快速的。即来自filledTabledistinctList 的所有项目我将如何进行查询?
  • 我没有完全理解您的要求。您能否提供一些示例输入数据和所需的输出?
  • 抱歉,如果我希望我的 json 看起来像 this 网站,但包含来自 filledTabledistinctList 的所有信息作为一个 List&lt;T&gt;或其他合适的集合类型
  • 不完全理解问题出在哪里,但如果您只是想将单个元素导出为元素列表,您可以例如写Id = new[] { group.Product.Id }
【解决方案2】:

我不太确定,但是这样的方法有用吗?

       var result = (from a in (from b in filledTable join c in distinctList on b[0].SerialNumber equals c.Field<string>("SERIAL NUMBER") select new { b, c })
                      group a by new { a.b[0].SerialNumber } into d
                      select new
                      {
                          Id = d.Select(x => x.b[0].Id),
                          SerialNumber = d.Select(x => x.b[0].SerialNumber),
                          ImportTable = d.Select(w => w.c.Table.AsEnumerable()
                          .Where(y=>y.Field<string>("SERIAL NUMBER") == d.Key.ToString())
                          .GroupBy(y => y.Field<string>("SERIAL NUMBER")).Select(z => z.First()).CopyToData‌​Table())
                      });

【讨论】:

  • 在添加的Where 子句中添加d.Key.SerialNumber 不是更有意义吗?此外,我认为这个答案是获得预期结果的最小更改集,但它没有解决任何底层设计问题(简单结果的过于复杂的查询)。
  • @grek40 确实如此,尽管提供了相当奇怪的输入和输出数据(例如,结果中的大多数数组可能不应该是数组)我认为修复设计问题不在答案的范围。虽然查询简化确实可以提供一些帮助。
【解决方案3】:

这是一个可以使用的简化查询:

var result =
    from entry in filledTable
    join row in distinctList on entry[0].SerialNumber equals row.Field<string>("SERIAL NUMBER")
    group new { entry, row } by entry[0].SerialNumber into items
    select new
    {
        Id = items.Select(x => x.entry[0].Id),
        SerialNumber = new[] { items.Key }.AsEnumerable(),
        ImportTable = items.Select(x => x.row).CopyToDataTable()
    };

它应该等同于所需的输出,并处理原始查询处理的大多数奇怪的数据组合。

【讨论】:

  • 我想我的查询方式太复杂了,就像你提到的那样。在@bashis 上阅读您的 cmets 答案后,我需要重新考虑这部分。我会试试你的答案,看看我的进展如何。最终,我希望我的最终 json 对象看起来像 this 网站上的样子。因此,如果我能以某种方式获得一个 List 或包含我的 filedTabledistinctList 的所有信息作为一个完整项目的东西
  • 您绝对应该首先定义所需的结果数据集(对于每个条目,需要哪些信息,一个条目中不能重复!),然后考虑它的结构(json或其他,嵌套vs平面)并定义查询以将您的输入转换为目标结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 2015-10-12
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多