Linq 查询产生不正确的结果

Posted

技术标签:

【中文标题】Linq 查询产生不正确的结果【英文标题】:Linq query producing incorrect result 【发布时间】: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 我也更新了我的问题 【参考方案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平面)并定义查询以将您的输入转换为目标结构。

以上是关于Linq 查询产生不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

未使用 MVC 从 Json Result 获取 Ajax 成功方法中的 LINQ 连接查询结果,但结果显示正确

TSQL:外部连接表的计数产生不正确的结果

LINQ to XML 查询不返回任何结果

即使使用 DefaultIfEmpty,Linq 查询也不返回预期结果

返回 LINQ 查询结果的控制器方法

LINQ 和 SQL 中看似等效的查询返回不同的结果 [重复]