简体   繁体   English

EF LINQ-返回包含整个集合的实体

[英]EF LINQ - Return entities that contain an entire collection

I am trying to troubleshoot the following LINQ Query: 我正在尝试对以下LINQ查询进行故障排除:

public JsonResult SearchNodesByTags(string[] tags)
{    

    var nodes = _DbContext.Nodes.
            Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
            .Select(n => new {n.NodeNativeId, n.NodeName, n.NodeClass.ClassName})
            .ToList();

    return Json(nodes);
}

The query is returning a single node that is not associated with a tag. 查询返回的单个节点与标签不相关。 What I want it to do, is return any nodes that have ALL the tags. 我想要它做的是返回具有所有标记的所有节点。

  .Where(n => n.Tags.All(t => tags.Contains(t.DisplayName))) 

The way this is currently constructed, you're only going to end up with the Node s where every tag in Node.Tags has a name in the tags whitelist, which includes Node s with no tags. 当前的构造方式,最后只涉及Node ,其中Node.Tags中的每个标签在tags白名单中都有一个名称,其中包括没有标签的Node


You might want to use the answer from here on subsets: 您可能要在此处使用子集的答案:

_DbContext.Nodes
    .Where(n => !tags.Except(n.Tags.Select(t => t.DisplayName)).Any()) 
    .Select(...
  • set1.Except(set2) contains elements of set1 that aren't in set2 set1.Except(set2)包含set1中不在set2中的元素
  • !set1.Except(set2).Any() == true if set2 includes every element of set1 !set1.Except(set2).Any() == true如果set2包含set1每个元素,则为!set1.Except(set2).Any() == true

Edit 编辑

It was pointed out in the comments that using Except could generate problematic queries, so I was thinking another option was to get a superset from the database, and further filter the objects within the application: 在评论中指出,使用Except可能会生成有问题的查询,因此我在想另一种选择是从数据库中获取超集,并进一步过滤应用程序内的对象:

_DbContext.Nodes
    // filter nodes with any of the input tags
    .Where(n => n.Tags.Any(t => tags.Contains(t.DisplayName)))

    // select the information required
    .Select(n => new {
        n.NodeNativeId, 
        n.NodeName, 
        ClassName = n.NodeClass.ClassName,
        TagNames = n.Tags.Select(t => t.DisplayName) })

    // materialize super set with database
    .ToList()

    // filter so that only nodes with all tags remain
    .Where(n => !tags.Except(n.TagNames).Any())

    // produce result in anonymous class
    .Select(n => new { n.NodeNativeId, n.NodeName, n.ClassName })
    .ToList();

Edit 2 编辑2

I just saw another one here that might work for you, but it requires that Tag.DisplayName is unique , since it could fail if you have multiple tags with the same DisplayName : 我刚刚在这里看到了另一个可能对您Tag.DisplayName ,但是它要求Tag.DisplayName唯一的 ,因为如果您有多个具有相同DisplayName标签,它可能会失败:

_dbContext.Nodes
     .Where(n => n.Tags.Count(t => tags.Contains(t.DisplayName)) == tags.Count)
     .Select(...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM