跨嵌套集合的一对多 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 那里得到的是一种类似于闭包的东西。

感谢您花时间阅读本文;任何建议不胜感激!

跨嵌套集合的一对多 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[]。我认为这是你第二个问题的答案——>懒惰的结果