您可以使用List在LINQ连接查询中配置选择器吗?

时间:2018-01-11 22:25:34

标签: c# linq

我加入了两个IEnumerable<DataRow> report1report2

var query = report1
    .Join(report2, 
          row1 => row1.Field<string>("ReportID"), 
          row2 => row2.Field<string>("ReportID"), 
          (row1, row2) => new 
          {
             ReportID = row1.Field<string>("ReportID"),
             CustomerName = row1.Field<string>("CustomerName"), 
             CustomerSpending = row2.Field<string>("CustomerSpending")
          });

现在假设我有两个List<string> fieldsReport1fieldsReport2每个列表包含每个报告中的字段名称,以使其进入最终加入。如何修改上述查询以在结果选择器中包含列表?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你需要这样的东西:

var report1 = new List<DataRow>();
var report2 = new List<DataRow>();

var report1Fields = new List<string> { "ReportId", "CustomerName" };
var report2Fields = new List<string> { "CustomerSpending" };

var query = report1
    .Join(report2,
      row1 => row1.Field<string>("ReportID"),
      row2 => row2.Field<string>("ReportID"),
      (row1, row2) => new
      {
          Report1Data = report1Fields.Select(x => row1.Field<string>(x)).ToList(),
          Report2Data = report2Fields.Select(x => row2.Field<string>(x)).ToList(),
      });

答案 1 :(得分:1)

使用动态字段创建匿名对象没有简单的方法,但是为此设计了另一个类:System.Dynamic.ExpandoObjectExpandoObject支持IDictionary<string,object>接口,允许您动态添加新属性。

使用扩展方法一次添加多个属性并将其链接起来,您可以执行以下操作:

var query = report1
    .Join(report2,
          row1 => row1.Field<string>("ReportID"),
          row2 => row2.Field<string>("ReportID"),
          (row1, row2) => (new ExpandoObject() as IDictionary<string,object>).AddRange(fieldsReport1, f => f, f => row1[f]).AddRange(fieldsReport2, f => f, f => row2[f])
    );

顺便说一句,您将如何使用/提取这些属性取决于您。在某些时候,直接使用Dictionary<string,object>可能更有意义。

这是扩展方法:

public static IDictionary<TKey, TValue> AddRange<TSrc, TKey, TValue>(this IDictionary<TKey, TValue> dictObj, IEnumerable<TSrc> srcFields, Func<TSrc, TKey> keySelector, Func<TSrc, TValue> valueSelector) {
    foreach (var kvp in srcFields)
        if (!dictObj.ContainsKey(keySelector(kvp)))
            dictObj.Add(keySelector(kvp), valueSelector(kvp));
    return dictObj;
}

请注意,如果两个字段名称列表存在冲突,则第一个表会获胜。您可以修改扩展方法以获取密钥冲突解决方案lambda,然后根据需要修复冲突的字段名称。

作为替代方案,您可以创建Dictionary,然后将结果转换为DataTable

public static DataTable AsDataTable(this IEnumerable<IDictionary<string, object>> rows) {
    var dt = new DataTable();
    if (rows.Any()) {
        foreach (var kv in rows.First())
            dt.Columns.Add(kv.Key, kv.Value.GetType());

        foreach (var r in rows)
            dt.Rows.Add(r.Values.ToArray());
    }
    return dt;
}