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())
.CopyToDataTable())
;
filledTable
在我的 linq 查询中是 List<dynamic>
,它由从 sproc
返回的值填充,distinctList
是 List<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*、**1073410、1073411, 1073410 所以当我使用dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList();
来获取不同的值时,我会得到两个元素,它们分别是 1073410 和 1073411跨度>
@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
中移动这些项目并将它们全部作为一个项目,那只是一个快速的。即来自filledTable
和distinctList
的所有项目我将如何进行查询?
我没有完全理解您的要求。您能否提供一些示例输入数据和所需的输出?
抱歉,如果我希望我的 json
看起来像 this 网站,但包含来自 filledTable
和 distinctList
的所有信息作为一个 List<T>
或其他合适的集合类型
不完全理解问题出在哪里,但如果您只是想将单个元素导出为元素列表,您可以例如写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()).CopyToDataTable())
);
【讨论】:
在添加的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 网站上的样子。因此,如果我能以某种方式获得一个 ListfiledTable
和 distinctList
的所有信息作为一个完整项目的东西以上是关于Linq 查询产生不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章
未使用 MVC 从 Json Result 获取 Ajax 成功方法中的 LINQ 连接查询结果,但结果显示正确