【问题标题】:Help with querying a DataTable using LINQ帮助使用 LINQ 查询 DataTable
【发布时间】:2011-08-24 15:57:57
【问题描述】:

假设我有这个初始代码:

        DataTable table = new DataTable();
        table.Columns.Add("column1", typeof(int));
        table.Columns.Add("column2", typeof(int));
        table.Columns.Add("column3", typeof(string));
        table.Rows.Add(1, 0, "a");
        table.Rows.Add(2, 1, "b");
        table.Rows.Add(3, 1, "c");
        table.Rows.Add(4, 3, "d");
        table.Rows.Add(5, 3, "e");

如何使用 LINQ 完成这些操作?

一个。返回 column1 中的值也出现在 column2 中的 DataRows。

到目前为止,我是这样做的:

var x = (from t1 in table.AsEnumerable()
         select t1.Field<int>(0)).Intersect
        ((from t2 in table.AsEnumerable()
         select t2.Field<int>(1)).Distinct());

但问题是,只返回 column1 的值,我在上面使用了foreach。可能是因为 select t1.Field&lt;int&gt;(0) 部分,但我不知道如何返回 DataRows 本身。

b.返回 column3 的值,其 column1 中的值也出现在 column2 中。

与[a]几乎相同的问题。我只能返回 column1 行,因为我已经使用了它。我不知道如何返回除 column1 之外的 DataRows 和其他列(例如 column3)。

我也试过这个:

var x1 = from t in table.AsEnumerable()
         select t;
var x2 = (from t in table.AsEnumerable()
          select t.Field<int>(1)).Distinct();

我希望在 x1 和 x2 上使用 Intersect(),但我不知道如何。特别是因为 x1 有点像 DataRow[] 而 x2 有点像 int[]。

c。将 [a] 中的答案用于另一个查询。

或者将 LINQ 中的某些内容用于另一个 LINQ。我完全知道如何做这样的事情。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    一种方法:

    a)    var result = (from t1 in table.AsEnumerable() 
                       join t2 in table.AsEnumerable() on t1.Field<int>(0) equals t2.Field<int>(1)  select t1).Distinct();
    

    上面的查询返回IEnumerable&lt;DataRow&gt;。从这个结果中,您可以选择column3的值,例如t2.Field&lt;int&gt;(2) for b)场景。

    【讨论】:

    • [c] 呢?我应该只扩展 LINQ 吗?或者我可以在另一个 LINQ 上使用 var 结果吗?
    • 如果您需要 [a] 查询的输出,请使用 result 的值。
    • 另外,我想你的意思是select t1
    • 对。我更改了查询并在末尾添加了Distinct()
    • 您可以执行var resultInteresct = table.AsEnumerable().Select(i=&gt;i.Field&lt;int&gt;(0)).Intersect(table.AsEnumerable().Select(j=&gt;j.Field&lt;int&gt;(1))); 之类的操作来获取列中存在的int 值。之后,您可以对表进行另一个查询以选择具有这些值的行。
    【解决方案2】:

    我将为三列创建一个新类。然后为新类创建一个 Iqueryable 或 List 并将表行添加到其中。那么 Linq 表达式应该可以工作了。

    public class myClass
    {
        public int column1
        {
            get;
            set;
        }
        public int column2
        {
            get;
            set;
        }
        public stringcolumn3
        {
            get;
            set;
        }
    }
    

    Linq

    一个。返回 column1 中的值也出现在 column2 中的 DataRows。

    var x = (from l1 in myList
             where (from l2 in myList
                    select l2.column2).contains(l1.column1)
             select l1);
    

    b.返回 column3 中 column1 中的值也出现在 column2 中的值。

    var col3Values = (from l1 in myList
                      where l1.column2 = l1.column3
                      select l1.column3);
    

    【讨论】:

    • myList 是不是这样:List&lt;int&gt; myList = new List&lt;int&gt;() {1,2,3,4,5};(contents of column1)?
    • 否... 创建一个具有三个属性的类。列出.
    【解决方案3】:

    在这里的人和其他一些网站的帮助下,我刚刚发现了如何实际执行上述 [b]。

    这会返回 column3 中的值,其 column1 中的值没有出现在 column2 中:

       from t in table.AsEnumerable()
           join t2 in table.AsEnumerable().Select(i => i.Field<int>(0)).Except(table.AsEnumerable().Select(j => j.Field<int>(1)))
           //the inner Select() returns column1 whose values in it also appears in column2
           //I can use either this or the first LINQ I made above
           //By the way, I said **does not** because I don't think I can use inner join on the opposite of [b]
           //unlike the Select() with lambda above; I can just change the Intersect() to Except() :)
           on t.Field<int>(0) equals t2
       where t.Field<int>(1) > 2          //If I need some other condition
       select t.Field<string>(2);
    

    对于[c],我又做了一个表:

            DataTable tableA = new DataTable();
            tableA.Columns.Add("columnA", typeof(string));
            tableA.Columns.Add("columnB", typeof(string));
            tableA.Rows.Add("apple", "red");
            tableA.Rows.Add("banana", "yellow");
            tableA.Rows.Add("carrot", "orange");
            tableA.Rows.Add("dog", "commonly brown");      //ok, I can't think of a fruit/vegetable that starts with 'd' right now...
            tableA.Rows.Add("eggplant", "purple");
    

    并将第一个表重命名为 table1 以避免/减少混淆

        var x = from tA in tableA.AsEnumerable()
            from t1 in (
                from t1 in table1.AsEnumerable()
                join t2 in ((from t2_1 in table1.AsEnumerable()
                                select t2_1.Field<int>(0)).Except
                            ((from t2_2 in table1.AsEnumerable()
                                select t2_2.Field<int>(1))).Distinct())
                on t1.Field<int>(0) equals t2
                where t1.Field<int>(1) > 2        //extra condition
                select t1.Field<string>(2))
            where tA.Field<string>(0).StartsWith(t1)
            select tA;
    

    这会返回tableA中的Rows,其columnA以返回的table1的column3开头,column1的值没有出现在column2中,并且column2的值大于2。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多