EF Intersect Syntax

本文关键字:Syntax Intersect EF | 更新日期: 2023-09-27 17:57:26

UI允许用户选择一个或多个标记。我想选择所有与用户输入的所有标签相关联的节点,而不是只有一个标签。

public JsonResult SearchNodesByTags(string[] tags)
{
    var dbTags = _DbContext.Tags.Where(t => tags.Contains(t.DisplayName)).ToList();
    var nodes = _DbContext.Nodes.Where(n => n.Tags.Intersect(dbTags).Any());  
    // Error about intersection with non primitive
    return Json(nodes);
}

EF Intersect Syntax

您可以在一个语句中做到这一点:

var nodes = _DbContext.Nodes
            .Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)));

您的语句不正确,因为dbTags是包含Tag对象的本地列表。在LINQ to Entities表达式中使用此列表时,无法将这些对象转换为SQL变量。这只有在原始值的情况下才有可能。

var nodes = _DbContext.Nodes.Where(n => n.Tags.Intersect(dbTags).Any());

首先,你不能在Linq-to-Entities表达式中使用对象,所以你必须使用这样的东西来进行比较:

n.Tags.Select(t => t.DisplayName).Intersect(tags)

其次,Intersect将为您提供两个给定集合中的一组项,因此您最终会得到所有具有任何标记的Node,而不是所有具有所有标签的节点。


如果您想要包含tags中每个Tag的所有Node,您可能需要在子集上使用以下答案:

_DbContext.Nodes
    .Where(n => !tags.Except(n.Tags.Select(t => t.DisplayName)).Any()) 
    .Select(...
  • set1.Except(set2)包含set1中不在set2中的元素
  • 如果set2包括set1的每个元素,则!set1.Except(set2).Any() == true