在LINQ语句中动态选择列

时间:2017-04-27 19:39:20

标签: c# linq dataset

存在类似问题但解决方案不适用。 我正在完成一个小程序,允许用户导入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语句?

2 个答案:

答案 0 :(得分:0)

您可以引入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”,具体取决于它们实际位于哪个表中)。

答案 1 :(得分:0)

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

string[] cols;
var dt = new DataTable();
var t1cols = ds1.Tables[0].Columns;
var tcols = t1cols.Union(ds2.Tables[0].Columns);
foreach (var cname in cols) {
    dt.Columns.Add(new DataColumns(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

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