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

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

问题描述

我正在尝试排除以下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 if set2 包含 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 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天全站免登陆