EF LINQ - 包含整个集合返回实体 [英] EF LINQ - Return entities that contain an entire collection
问题描述
我试图解决以下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
Node
s where every tag inNode.Tags
has a name in thetags
whitelist, which includesNode
s 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 ofset1
that aren't inset2
!set1.Except(set2).Any() == true
ifset2
includes every element ofset1
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 sameDisplayName
:_dbContext.Nodes .Where(n => n.Tags.Count(t => tags.Contains(t.DisplayName)) == tags.Count) .Select(...
这篇关于EF LINQ - 包含整个集合返回实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!