EF LINQ - Return 个包含整个集合的实体
EF LINQ - Return entities that contain an entire collection
我正在尝试解决以下 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);
}
查询正在 returning 与标签无关的单个节点。我想要它做的是 return 任何具有所有标签的节点。
.Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
按照目前的构造方式,您只会以 Node
结尾,其中 每个 标签在 Node.Tags
中都有一个名称在 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
如果 set2
包含 set1
的每个元素
编辑
评论中指出使用 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();
编辑 2
我刚看到另一个可能适合你的 ,但它要求 Tag.DisplayName
是 unique,因为如果您有多个具有相同 DisplayName
:
的标签,它可能会失败
_dbContext.Nodes
.Where(n => n.Tags.Count(t => tags.Contains(t.DisplayName)) == tags.Count)
.Select(...
我正在尝试解决以下 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);
}
查询正在 returning 与标签无关的单个节点。我想要它做的是 return 任何具有所有标签的节点。
.Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
按照目前的构造方式,您只会以 Node
结尾,其中 每个 标签在 Node.Tags
中都有一个名称在 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
如果set2
包含set1
的每个元素
编辑
评论中指出使用 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();
编辑 2
我刚看到另一个可能适合你的 Tag.DisplayName
是 unique,因为如果您有多个具有相同 DisplayName
:
_dbContext.Nodes
.Where(n => n.Tags.Count(t => tags.Contains(t.DisplayName)) == tags.Count)
.Select(...