【问题标题】:Dynamically select columns in LINQ statement在 LINQ 语句中动态选择列
【发布时间】:2017-09-25 18:25:15
【问题描述】:

存在类似问题,但解决方案不适用。 我正在完成一个允许用户导入 2 个数据表并加入以获得结果的小程序。以下是相关代码:

List<DataRow> list1 = ds1.Tables[0].AsEnumerable().ToList<DataRow>();
            List<DataRow> list2 = ds2.Tables[0].AsEnumerable().ToList<DataRow>();
            var v = (from t1 in list1
                     join t2 in list2
                     on t1.Field<string>(ds1ColInx) equals t2.Field<string>(ds2ColInx)
                     select new
                     {
                         t1,
                         t2
                     }).ToList();

但这显然不能输入DataGridView。现在,对于用户想要查看的每个表和列,我还有一个列名和列索引的string array。如何将其插入select 语句?

【问题讨论】:

  • “很明显,这不能输入 DataGridView”——这对我来说不太明显。你能扩展一下吗?无论如何,关于你真正的问题:为什么需要 LINQ?
  • 这可能会满足您的需求,但是:weblogs.asp.net/scottgu/…
  • “类似问题存在,但解决方案不适用” 有什么具体问题可以参考吗?我很确定这已经被覆盖了。
  • @EdPlunkett 我猜想直接将结果绑定到 DataGridView 的问题是匿名类型,它不是“平面”。这些列将只是两种类型(t1 和 t2)的“ToString”,而不是这两种类型的属性。
  • @jadarnel27 你说得对,谢谢。

标签: c# linq dataset


【解决方案1】:

我建议将v 转换为DataTable 并复制所需的列。使用 cols 作为您想要的列:

string[] cols;
var dt = new DataTable();
var t1cols = ds1.Tables[0].Columns.Cast<DataColumn>().Select(dc => dc.ColumnName).ToHashSet();
var tcols = t1cols.Cast<DataColumn>().Union(ds2.Tables[0].Columns.Cast<DataColumn>()).ToDictionary(dc => dc.ColumnName);

foreach (var cname in cols)
    dt.Columns.Add(new DataColumn(cname, tcols[cname].DataType));

foreach (var vr in v) {
    var nr = dt.NewRow();
    foreach (var cname in cols)
        nr[cname] = t1cols.Contains(cname) ? vr.t1[cname] : vr.t2[cname];
    dt.Rows.Add(nr);
}

现在您可以将dt 分配给GridView.DataSource

请注意,如果t1t2 有任何同名的列,则会发生不好的事情,在这种情况下,您应该使用t1colstcols 中的表前缀重命名它们,并将它们添加到dt.Columns.

【讨论】:

    【解决方案2】:

    您可以引入 Microsoft 开发的“System.Linq.Dynamic”库来实现您的目标。您可以在 NuGet 上找到它:

    http://www.nuget.org/packages/System.Linq.Dynamic/

    来源在这里:

    https://github.com/kahanu/System.Linq.Dynamic

    然后引用 System.Linq.Dynamic,您将可以访问接受字符串而不是表达式的新扩展方法。

    我只将它与基于 lambda 的 LINQ 扩展方法一起使用,这使您能够执行以下操作:

    .Select("column1, column2, column3").ToList();
    

    我尝试使用下面的 lambda 语法重写您的查询,尽管它未经测试:

    var v = list1.Join(
                list2,
                t1 => t1.Field<string>(ds1ColInx),
                t2 => t2.Field<string>(ds2ColInx),
                (t1, t2) => new {t1, t2});
    
    v.Select(columnList).ToList();
    

    注意:在这种情况下,您可能需要对列字符串进行一些操作(例如,我认为您需要在它们前面加上“t1”或“t2”,具体取决于它们实际在哪个表中)。

    【讨论】:

      猜你喜欢
      • 2013-12-27
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-29
      • 2015-02-22
      • 2011-10-25
      相关资源
      最近更新 更多