【问题标题】:Deep filtering in Grouped collection of Entities实体分组集合中的深度过滤
【发布时间】:2019-06-20 09:05:48
【问题描述】:

我有以下实体方案:

class Container
{
 Forest Forest;
 Tree Tree;
}
class Forest 
{
  int Id;
  string Name;
  List<Trees> Trees;
}

class Tree 
{
 int Id;
 string Name;
 Forest Forest;
 List<Leaf> Leafs;
}

class Leaf 
{
 int Id;
 string Name;
 Tree Tree;
}

我收集了 Forest 的集合,其中包含从数据库中读取的 Trees and Leafs

我怎样才能做到以下几点:

根据以下规则过滤出Forests 的集合: 以 [Name] 包含一些 "filter value" 的 Forest 条目为例 或者那些有Trees [Name] 包含"filter value" 或者Leaf[Name]的人包含"filter value"

我需要返回 Forest 的层次结构,而不是 Forest 的平面视图

我尝试展平结构以过滤条目,例如来自INNER JOIN 视图的数据库中的表

IEnumerable<Container> containers;
var groupped = forests.Select(f => new {f.Forest, f.Tree})
  .GroupBy(f => f.Forest)
  .ToList().Select(fs => new {Forest = fs.Key, Leafes = fs.SelectMany(g => g.Tree.Leafes) }).ToDictionary(fx => fx.Forest, fx => fx.Leafes);

var flat = new List<Tuple<Forest, Tree, Leaf>>;
foreach (var i in groupped)
{
 foreach (var l in i.Value) 
 {
  flat.Add((i.Key, l.Tree, l));
 }
}
flat.Where(d => d.Item1.Name.Contains("") 
  || d.Item2.Name.Contains("")
  || d.Item3.Name.Contains(""));       

但实际上在这里我不能将它们组合回Forest -&gt; Tree -&gt; Leaf的层次结构

因此,我不想拥有List&lt;Tuple&lt;Forest,Tree,Leaf&gt;&gt; 的一些类似表格的结构,而是希望有一个普通的集合List&lt;Forest&gt; 并过滤掉TreesLeafs

【问题讨论】:

  • 您是要在数据库级别还是在应用程序级别过滤掉它?
  • 为什么你的Container 类有一个Forest 成员和一个Tree 成员? Tree 成员的意义是什么?您说“过滤出森林集合”,但您的代码没有Forests 的集合。 “过滤掉树木和树叶”是什么意思?

标签: c# .net entity-framework linq


【解决方案1】:

您可以很容易地从Containers 列表中生成Container 的过滤器集合,只需完全按照您编写的方式实现所需的过滤器。 (这不是(必然)最有效的搜索方式,但可能非常接近。)

var ans = src.Where(c => c.Forest.Name.Contains(fv) || // Forest name contains filter value
                         c.Forest.Trees.Any(t => t.Name.Contains(fv) || // a Tree name contains filter value
                                                 t.Leafs.Any(l => l.Name.Contains(fv))) // a Leaf name contains filter value
                    );

如果您的层次结构中的树很少而叶子很多,您可能希望将搜索更改为首先搜索树,然后进行单独的树->叶子搜索,即使这会两次遍历树。

var ans2 = src.Where(c => c.Forest.Name.Contains(fv) || // Forest name contains filter value
                          c.Forest.Trees.Any(t => t.Name.Contains(fv)) || // a Tree name contains filter value
                          c.Forest.Trees.Any(t => t.Leafs.Any(l => l.Name.Contains(fv))) // a Leaf name contains filter value
                    );

【讨论】:

    猜你喜欢
    • 2019-07-10
    • 2017-07-14
    • 1970-01-01
    • 2013-03-23
    • 2012-11-14
    • 2017-09-18
    • 2016-12-27
    • 2016-02-15
    • 1970-01-01
    相关资源
    最近更新 更多