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 のソリューションは非常に効率的で、おそらく最も効率的なソリューションですが、いくつかの問題があります。答えを改善できるように、コメントでそれらを指摘し始めましたが、うまくいきませんでした。Arkiliknam 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の の各 Id がVacancyのコレクションに含まれている必要があることを示してい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 に答える