EF LINQ - 返回包含整个集合的实体 [英] EF LINQ - Return entities that contain an entire collection
问题描述
我正在尝试排除以下LINQ查询:
public JsonResult SearchNodesByTags(string [] tags)
{
var nodes = _DbContext.Nodes。
其中(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
.Select(n => new {n.NodeNativeId,n.NodeName ,n.NodeClass.ClassName})
.ToList();
返回Json(nodes);
}
查询返回一个与标签无关的单个节点。我想要的是返回任何具有所有标签的节点。
.Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
当前构建的方式,你只会最终得到 Node
s Node.Tags
中的每个标签在标签中有一个名称
白名单,其中包括没有标签的 Node
。
你可能希望使用 here 上的答案:
_DbContext.Nodes
.Where(n =>!tags.Except(n.Tags.Select t => t.DisplayName))。Any())
.Select(...
-
set1.Except(set2)
包含不属于set1
的元素在set2
-
!set1.Except(set2).Any()== true
ifset2
包含set1的每个元素
编辑
在评论中指出,使用Except可能会产生有问题的查询,所以我认为另一个选择是获取来自数据库的超集,并进一步过滤应用程序中的对象:
_DbContext.Nodes
//过滤节点使用任何输入标签
.Where(n => n.Tags.Any(t => tags.Contains(t.DisplayName)))
//选择所需的信息
.Select(n => new {
n.NodeNativeId,
n.NodeName,
ClassName = n.NodeClass.ClassName,
TagNames = n.Tags.Select(t => t.DisplayName)})
//实现数据库
.ToList()
//过滤器,只有具有所有标签的节点保持
.Where(n => !tags.Except(n.TagNames).Any())
//在匿名类中生成结果
.Select(n => new {n.NodeNativeId,n.NodeName, n.ClassName})
.ToList();
编辑2 / p>
我刚刚看到可能适用于您的另一个此处,但是要求 Tag.DisplayName
是 唯一 ,因为如果您有多个标签具有相同的 DisplayName
:
_dbContext.Nodes
.Where(n = > n.Tags.Count(t => tags.Contains(t.DisplayName))== tags.Count)
.Select(...
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 in Node.Tags
has a name in the tags
whitelist, which includes Node
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 same DisplayName
:
_dbContext.Nodes
.Where(n => n.Tags.Count(t => tags.Contains(t.DisplayName)) == tags.Count)
.Select(...
这篇关于EF LINQ - 返回包含整个集合的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!