【问题标题】:Use List<Tuple<int, int>> to return data in Linq使用 List<Tuple<int, int>> 在 Linq 中返回数据
【发布时间】:2016-05-25 14:22:53
【问题描述】:

给定:

List<int> myList;

如果我想返回此列表中包含记录 ID 的数据,我会这样做:

var q = db.Table.Where(c=> myList.Contains(c.ID));

但是,鉴于:

List<Tuple<int, int>> myList;

如何编写一个 Linq 查询来返回同时满足两个条件的记录?用一个数据点我会写:

var q = db.Table.Where(c=>
            c.ID == myList.Item1
            && c.AnotherValue == myList.Item2);

如何将上述语句转换为List&lt;Tuple&lt;int, int&gt;&gt;

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    Tuple 是一种结构,您的 Linq 提供程序无法将其转换为 sql。一个解决方案可能是切换到 Linq to Objects

    var q = db.Table.AsEnumerable()
                    .Where(c=> myList.Any(tuple => c.ID == tuple.Item1 &&
                                               c.AnotherValue == tuple.Item2));
    

    但这个解决方案的坏处是您将加载该表中的所有行以在内存中进行过滤。

    另一种解决方案可能是使用Linqkit

    var predicate = PredicateBuilder.False<Table>();
    
    foreach (string t in myList)
    {
        predicate = predicate.Or(c =>c.ID == t.Item1 && c.AnotherValue == t.Item2));
    }
    
    db.Table.AsExpandable().Where(predicate);
    

    您将在link 中找到有关最后一个解决方案的更多信息

    【讨论】:

    • 是的,但是对于多个值?如果我有 100 对的列表,我不想对每一对都运行查询。
    【解决方案2】:
    var q = db.Table.AsEnumerable().Where(c => myList.Any(tuple => c.ID == tuple.Item1 &&
                                                   c.AnotherValue == tuple.Item2));
    

    使用Any,您可以检查myList 中是否至少有一个元素符合您的条件。

    但是正如@octaviocci 所指出的,这不能翻译成SQL,所以你需要先调用AsEnumerable() 并在本地进行过滤,如果有很多不相关的记录,这可能不是你想要的。

    【讨论】:

      【解决方案3】:

      这里有一些示例代码说明了一种方法:

      DataTable dt = new DataTable("demo");
      // hydrate your table here...
      
      List<Tuple<int, int>> matches = new List<Tuple<int, int>>();
      
      Func<List<Tuple<int,int>>, DataRow, bool> RowMatches = (items, row) => {
      
              var rowValue1 = (int)row["Id"];
              var rowValue2 = (int)row["SomeOtherValue"];
      
              return items.Any(item => item.Item1 == rowValue1 && item.Item2 == rowValue2);
          };
      
      var results = dt.Rows.Cast<DataRow>().Where(r => RowMatches(matches, r));
      Console.WriteLine(results.Any());
      

      【讨论】:

        【解决方案4】:

        见下面的代码:

        List<Tuple<int, int>> myList;
        
        var set = new HashSet(myList);
        
        var q = db.Table.AsEnumerable().Where(c=> set.Contains(new Tuple(c.ID, c.AnotherValue)));
        

        请注意,哈希集用于对大型 myListWhere 子句的执行进行性能优化。

        【讨论】:

        • 这不是简单地将 set1 的任何项目与 set2 的任何项目匹配吗?
        【解决方案5】:

        由于Tuple不能在Linq to Entities中使用,你可以试试这样:

        List<int> items1 = myList.Select(t => t.Item1).ToList();
        List<int> items2 = myList.Select(t => t.Item2).ToList();
        
        var q = db.Table.GroupBy(m => { m.ID, m.AnotherValue })
                        .Where(g => items1.Contains(g.Key.ID) && 
                                    items2.Contains(g.Key.AnotherValue))
                        .SelectMany(g => g);
        

        【讨论】:

          猜你喜欢
          • 2018-01-25
          • 2011-06-07
          • 1970-01-01
          • 1970-01-01
          • 2014-01-01
          • 2014-11-08
          • 2016-09-07
          • 1970-01-01
          相关资源
          最近更新 更多