EF LINQ - 包含整个集合返回实体 [英] EF LINQ - Return entities that contain an entire collection

查看:145
本文介绍了EF LINQ - 包含整个集合返回实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图解决以下LINQ查询:

 公共JsonResult SearchNodesByTags(字符串[]标记)
{    VAR节点= _DbContext.Nodes。
            其中(n => n.Tags.All(T => tags.Contains(t.DisplayName)))
            。选择(N =>新建{n.NodeNativeId,n.NodeName,n.NodeClass.ClassName})
            .ToList();    返回JSON(节点);
}

该查询返回该不与标签相关联的单个节点。我希望它做的,就是返回所有的所有标签的​​任何节点。


解决方案

 。凡(N => n.Tags.All(T => tags.Contains(t.DisplayName)))


这是目前构建的方式,你只会用节点 s其中的每一个的标记<$ C $落得C> Node.Tags 已经在标记白名单,其中包括节点名称取值没有标签。


您可能需要使用从答案<一个href=\"http://stackoverflow.com/questions/332973/check-whether-an-array-is-a-subset-of-another\">here在子集:

  _DbContext.Nodes
    。凡(N =&GT;!tags.Except(n.Tags.Select(T =方式&gt; t.DisplayName))任何())
    。选择(...


  • set1.Except(设置2)包含不在 SET1 元素设置2

  • !set1.Except(设置2)。任何()==真如果设置2 包含的每一个元素 SET1


修改

据指出,在评论中,使用除了能产生问题的查询,所以我想另一种选择是从数据库中获得的超集,并进一步筛选应用程序中的对象:

  _DbContext.Nodes
    //与任何输入标签过滤节点
    。凡(N =&GT; n.Tags.Any(T =&GT; tags.Contains(t.DisplayName)))    //选择所需的信息
    。选择(N =&gt;新建{
        n.NodeNativeId,
        n.NodeName,
        类名= n.NodeClass.ClassName,
        标记名= n.Tags.Select(T =&GT; t.DisplayName)})    //兑现超集与数据库
    .ToList()    //过滤器,只用节点的所有标签仍
    。凡(N =&GT;!tags.Except(n.TagNames)。任何())    //产生结果匿名类
    。选择(N =&gt;新建{n.NodeNativeId,n.NodeName,n.ClassName})
    .ToList();


编辑2

我刚才看到这里的另一个可能会为你工作,但它要求标签.DisplayName 唯一,因为如果你有相同的多个标签可能失败显示名称

  _dbContext.Nodes
     。凡(N =&GT; n.Tags.Count(T =&GT; tags.Contains(t.DisplayName))== tags.Count)
     。选择(...

I am trying to troubleshoot the following LINQ Query:

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 Nodes where every tag in Node.Tags has a name in the tags whitelist, which includes Nodes with no tags.


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).Any() == true if set2 includes every element of set1

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:

_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

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:

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

这篇关于EF LINQ - 包含整个集合返回实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆