跨嵌套集合的一对多 LINQ 联接
本文关键字:LINQ 联接 一对多 嵌套 集合 | 更新日期: 2023-09-27 18:33:17
我有一个开发方案,其中我将两个集合与 Linq 联接;一个包含表示元数据的列标题对象的单个列表,以及由 Web 服务调用生成的 KV 字典的枚举。我目前可以迭代(for
(字典枚举,并将单个标题列表连接到当前的kv字典中,而不会出现问题。加入后,我为每次迭代发出一个精选的字典值数组。
我想做的是消除for
循环,并将单个标头列表直接连接到整个枚举。我很好地理解 1 对 1 集合的连接,但 1 对 N 语法让我无法理解。
详
我有以下工作方法:
public void GetQueryResults(DataTable outputTable)
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
foreach (var row in odResponse)
{
var rowValues = OutputFields
.Join(row, h => h.Key, r => r.Key,
(h, r) => new { Header = h, ResultRow = r })
.Select(r => r.ResultRow.Value);
outputTable.Rows.Add(rowValues.ToArray());
}
}
odResponse
包含IEnumerable<IDictionary<string, object>>
; OutputFields
包含IList<QueryField>
;该.Join
生成包含匹配字段元数据(.Header
(和响应KV对(.ResultRow
(的匿名枚举;最后,.Select
发出行消耗的匹配响应值。OutputField
集合如下所示:
class QueryField
{
public string Key { get; set; }
public string Label { get; set; }
public int Order { get; set; }
}
声明为:
public IList<QueryField> OutputFields { get; private set; }
通过将字段标题集合连接到响应行,我可以只从响应中提取所需的列。如果标题键包含 { "size"、"shape"、"color" } 并且响应键包含 { "size"、"mass"、"color"、"longitude"、"纬度" },我将得到 { "size"、"shape"、"color" } 的值数组,其中 shape 为 null,质量、经度和纬度值将被忽略。出于此方案的目的,我不关心排序。这一切都是一种享受。
问题
我想做的是重构此方法以返回值数组行的枚举,并让调用方管理数据的消耗:
public IEnumerable<string[]> GetQueryResults()
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
var responseRows = //join OutputFields to each row in odResponse by .Key
return responseRows;
}
后续问题
Linq 为此重构实现的解决方案是否需要立即扫描枚举,还是可以传回延迟结果?重构的目的是在不导致冗余集合扫描的情况下改进封装。我总是可以构建命令式循环来重新格式化响应数据,但我想从 Linq 那里得到的是一种类似于闭包的东西。
感谢您花时间阅读本文;任何建议不胜感激!
完全确定你的意思,但你的意思是这样的吗?
public IEnumerable<object[]> GetQueryResults()
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
// i'd rather you linq here.
var responseRows = from row in odResponse
select new object[]
{
from field in row
join outputfield in OutputFields
on field.Key equals outputfield.Key
select field.Value
};
return responseRows;
}
而不是填充数据表。这将创建一个对象数组并用字段填充它。字段所在的值。键存在于输出字段中。整个事情都封装在一个IEnumerable
.(从 odResponse 中的行开始(
用法:
var responseRows = GetQueryResults2();
foreach(var rowValues in responseRows)
outputTable.Rows.Add(rowValues);
这里的诀窍是,在一个查询中,您可以迭代列表并在字段上创建子查询,并将子查询结果直接存储在object[]
中。仅当迭代responseRows
时,才会创建object[]
。我认为这是你第二个问题的答案——>懒惰的结果。