2

我有这样的结构:

public class Tag
{
        public int TagId { get; set; }
        public virtual ICollection<Vacancy> Vacancies { get; set; }
        // ...
}

public class Vacancy
{
        public int VacancyId { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
        // ...
}

这些实体通过 EF / Code First 方法映射到 MS SQL。

之后,我以某种方式从上下文(基于用户查询)中获取标签列表:

List<Tag> userSelectedTags = ...;

我想选择包含所有(!)这些标签的所有空缺,例如:

List<Vacancy> vacancies = context.Where(v => v.Tags.Intersect(userSelectedTags)).ToList();

但!问题是我可能有大量数据。AFAIK Intersect 并不是最好的方法,因为它会为每个空缺选择所有标签,然后对它们执行 Intersect。我不想过多地加载 SQL Server,我绝对可以为此编写纯 sql 查询。但我想知道 LINQ 是否可以为我做这件事?有没有更温和的方法呢?

4

2 回答 2

5

Arkiliknam 的解决方案非常有效,也许是最有效的解决方案,但它存在一些问题。我开始在评论中指出它们,以改进答案,但这效果不佳。所以这里是 Arkilknam v. 2.0:

var result = context.Vacancies; // IQueryable!
var tags = userSelectedTags.Select(t => t.TagId);

foreach(int i in tags)
{
    int j = i; // prevent modified closure.
    result = result.Where(v => v.Tags.Select(t => t.TagId).Contains(j));
}
result.Select(r => ....

它被转换为带有WHERE EXISTS谓词链的查询(与选定的标签一样多)。

如果这效果不佳,您可以尝试另一种方法:

var r = context.Vacancies
.Where(v => tags.All(i => v.Tags.Select(t => t.TagId).Contains(i)))
.Select (v => ....);

这表示对于所有选定TagId的 s,每个 Id 都应该在 aVacancy的 s 集合中TagId

于 2012-08-17T20:58:35.610 回答
1

不确定这是否会更有效,但我想如果你把它保留为 IQueryable 应该没问题?

IEnumerable<Vacancy> result = vacancies;

foreach(var t in tags){
    result = result.Where(v => v.TagIds.Contains(t));
}
于 2012-08-17T15:48:52.013 回答