2016-12-02 73 views
3

我有以下的许多一对多关系建模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;} 
} 

我使用ASP.NET MVC的核心,并有过滤视图模型,其中一些过滤器配置文件名称上的属性,它的作品。

试图根据类别进行过滤证明更难实现(至少该解决方案是不是明显对我:)

从Web用户可以选择零,一个或多个类别来筛选上所以基本上发送给我的控制器的是类别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,因此打破了其他部分。

如何在保留Profile对象的原始实例的同时执行连接。我首先想到他们会是一样的,但我错了。

回答

2

目前,EF核心连接是不完美的,我建议做两个查询:基于

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

2)选择所需的数据:

(基于类别列表

1)的ProfileId选择列表)在已知的ID:

var result = await _context.Profiles 
    .Include(p => p.Categories).Include(p => p.Platforms) 
    .Where(x => profileIds.Contains(x.ProfileId)) 
    .ToListAsync(); 

是的,这是两个查询,而不是一个,但两个简单的查询,使用索引轻松优化。

+0

几乎是我采取的方法:)感谢您的快速答案! – joacar