2016-12-02 24 views
3

をフェッチ私はASP.NETコアMVCを使用して、いくつかのフィルタのフィルタビューモデルを持っていEFコア多対多のクエリ

public class Profile 
{ 
ICollection<Category> Categories { get; set;} 
// One-To-Many 
ICollection<Platform> Platforms { get; set; } 
} 

public class Category 
{ 
ICollection<Profile> Profiles { get; set; } 
} 

public class ProfileCategory 
{ 
public int ProfileId { get; set; } 
public Profile Profile { get; set; } 
public int CategoryId { get; set; } 
public Category Category { get; set;} 
} 

をモデル化し、以下の多対多の関係を持っていますプロファイル名の属性とそれが動作します。カテゴリに基づいてフィルタリングしようとすると

ははるかに困難を実装するために証明した(少なくとも、解決策は、私には明らかにされていません:)

Webからのユーザーはそう、基本的にフィルタリングするために、ゼロ、1または多数のカテゴリを選択することができます私のコントローラに送信されるのはカテゴリIDのリストです。

IQueryable<Profile> query = _context.Profiles.Include(p => p.Categories).Include(p => p.Platforms); 
if(string.IsNullOrEmpty(search.Name)) 
{ 
query = query.Where(p => p.Name.IndexOf(search.Name StringComparison.OrdinalIgnoreCase) > 0); 
} 
if(search.Categories?.Any() != null) 
{ 
    query = query.SelectMany(p => p.ProfileCategories) 
      .Join(search.Categories, pc => pc.CategoryId, cId => cId, (pc,_) => pc.Profile); 
} 

この時点から、Profileオブジェクトは異なっており、Platformsなどの他のナビゲーションプロパティはnullなので、他の部分を壊しています。

プロファイルオブジェクトの元のインスタンスを保持したままで結合を実行するにはどうすればよいですか。私は最初に彼らは同じだろうと思ったが、私は間違っていた。

答えて

2

現在、EFコアは完全ではなく、結合、私は2つのクエリ作るお勧めします。ProfileId

1)を選択リスト(カテゴリリストに基づいて):

var profileIds = await _context.ProfileCategory 
    .Where(x => categoryIds.Contains(x.CategoryId)) // filtering goes here 
    .Select(x => x.ProfileId) 
    .Distinct() 
    .ToListAsync(); 

2)に基づく必要なデータを選択します既知のID:

はい、2つのクエリではなく、2つの単純なクエリで、インデックスを使用して簡単に最適化されます。

+0

私が取ったアプローチはかなりでした:)素早く答えてくれてありがとう! – joacar

関連する問題