EF LINQ - 仅选择父实体

时间:2015-06-24 21:48:32

标签: c# linq entity-framework linq-to-sql

我遇到了一个有趣的问题。

我有一个Node实体。节点可能有也可能没有孩子,也可能有或没有父母。

对于我的UI,当用户搜索节点时,如果搜索结果包含父节点及其一个或多个子节点,我只想返回父节点(因为父节点具有子节点导航属性) )。

搜索包含" ParentA"

的名称时的结果
  • ParentA
  • ParentA_ChildA
  • ParentA_ChildB

期望的结果:

  • ParentA(因为 ParentA.Children 将包含 ParentA_ChildA ParentA_ChildB

这是我当前的LINQ查询:

var results = await dbContext.Nodes.
                        Include(c => c.Parent).
                        Where(c => c.NodeName.Contains(query)).
                        OrderBy(n => n.NodeName).
                        ToPagedListAsync(page ?? 1, pageSize);

节点实体:

public class Node
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long Id { get; set; }

    [Required, MaxLength(50)]
    [DisplayName("Node Name")]
    public string NodeName { get; set; }

    [ForeignKey("Parent")]
    public Nullable<long> ParentId { get; set; }
    public virtual Node Parent { get; set; }

    public virtual ICollection<Node> Children { get; set; }
}

3 个答案:

答案 0 :(得分:1)

您可以使用Any这样的方法:c.Children.Any(x => x.NodeName.Contains(query))

var results = await dbContext.Nodes.
                        Include(c => c.Parent).
                        Where(c => c.NodeName.Contains(query)).
                        Where(c => c.Children.Any(x => x.NodeName.Contains(query))).
                        OrderBy(n => n.NodeName).
                        ToPagedListAsync(page ?? 1, pageSize);

答案 1 :(得分:0)

您不需要包含父级,您可以搜索子级并返回父级。如果您需要,您也可以返回孩子。

dbContext.Nodes.Where(
     n =>n.NodeName.Contains(query)) || n.Children.Any(
         c=>c.NodeName.Contains(query))).
                    OrderBy(n => n.NodeName).
                    ToPagedListAsync(page ?? 1, pageSize);

答案 2 :(得分:0)

请试试这个......

dbContext.Nodes
     .Where(c => c.NodeName.Contains(query))
     .Select(c=>GetParentOrSelf(c,query))
     .OrderBy(n => n.NodeName)
     .ToPagedListAsync(page ?? 1, pageSize);    


private Node GetParentOrSelf(Node n)
{
    if (n.Parent==null)
        return n;
    else
    {
        if (n.Parent.NodeName.Contains(query))
            return GetParentOrSelf(n.Parent,query);
        else
            return n;
    }
}