2016-11-10 60 views
0

我试图根据几个条件列表创建记录(合作伙伴)列表。问题在于LINQ生成的SQL选择至少遵守其中一个条件的合作伙伴,我只希望尊重必须应用的条件的合作伙伴(serviceId或/和brandId和/或TraillerService)。根据条件使用LINQ和MVC将过滤器应用到表C#

模型(简体):

public class Partner 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<PartnerServiceBrand> PartnerServiceBrands { get; set; } 

} 

// A partner can have multiple services, brands and in each case, can have, or not have trailler service 
public class PartnerServiceBrand 
{ 
    [Key] 
    public int Id { get; set; } 

    public virtual Partner Partner { get; set; } 
    public virtual Service Service { get; set; } 
    public virtual Brand Brand { get; set; } 

    public bool TrailerService { get; set; } 
} 

public class Service 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<PartnerServiceBrand> PartnerServiceBrands { get; set; } 
} 

public class Brand 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<PartnerServiceBrand> PartnerServiceBrands { get; set; } 
} 

我想申请基于过滤器,我具备的条件:

IQueryable<Partner> partners = dbContext.Partners; 

if (search.ServiceId > 0) 
{ 
    partners = dbContext.Partners.Where(p => p.PartnerServiceBrands.Select(psb => psb.Service.Id).Contains(search.ServiceId)); 
} 

if (search.BrandId > 0) 
{ 
    partners = partners.Where(p => p.PartnerServiceBrands.Select(psb => psb.Brand.Id).Contains(search.BrandId)); 
} 

if (search.TrailerService == true) 
{ 
    partners = partners.Where(x => x.PartnerServiceBrands.Any(y => y.TrailerService == true)); 
} 

我得到的查询是:

SELECT[Extent1].[Id] AS[Id], [Extent1].[Name] AS[Name] 
    WHERE(EXISTS (SELECT 1 AS[C1] 
    FROM [dbo].[PartnerServiceBrands] AS [Extent2] 
    WHERE ([Extent1].[Id] = [Extent2].[Partner_Id]) AND([Extent2].[Service_Id] = 7) 
         )) AND(EXISTS (SELECT 1 AS[C1] 
             FROM [dbo].[PartnerServiceBrands] AS [Extent3] 
             WHERE ([Extent1].[Id] = [Extent3].[Partner_Id]) AND([Extent3].[Brand_Id] = 1153) 
         )) AND(EXISTS (SELECT 1 AS[C1] 
             FROM [dbo].[PartnerServiceBrands] AS [Extent4] 
             WHERE ([Extent1].[Id] = [Extent4].[Partner_Id]) AND(1 = [Extent4].[TrailerService]) 
         )) 

随着这个查询,我得到了拖车服务至少有1个服务的合作伙伴,这不是我想要的。我只想要尊重所有条件的合作伙伴。

+0

您正在查询两个不同的表Partner_Id和PartnerServiceBrands。所以你需要加入这两个表格,然后过滤连接的结果。看到msdn:https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

+0

嗨,谢谢!你想为我的案例提供一个例子吗? – Patrick

+0

您需要通过ID参加课程。如果所有的ID都相同,或者哪些类使用相同的ID和哪些ID是不同的ID,我无法从类中判断。 – jdweng

回答

1

尝试是这样的:

var baseQuery = db.PartnerServiceBrands.AsNoTracking().AsQueryable(); 

if(filterTrailer.hasValue){ 
    baseQuery = baseQuery.Where(x=> x.TrailerService == filterTrailer.Value); 
} 

if(filterServiceId.hasValue){ 
    baseQuery = baseQuery.Where(x=>x.ServiceId == filterServiceId); 
} 

if(filterServiceId.hasValue){ 
    baseQuery = baseQuery.Where(x=>x.BrandId == filterBrandId); 
} 

var results = baseQuery.Select(x=>x.Partner) 
         .ToList(); 

TODO:一组由也增加了没有重复的合作伙伴。调整最终的“选择”以获得所需的额外信息。

+1

嗨,谢谢!它工作正常!我似乎在过滤错误的实体Partners-> PartnerServiceBrands – Patrick

0

翻转你的逻辑。

if (search.ServiceId == 0) 
{ 
    return new Partner[] {}; 
} 

if (search.BrandId == 0) 
{ 
    return new Partner[] {}; 
} 

if (search.TrailerService != true) 
{ 
    return new Partner[] {}; 
} 

return dbContext.Partners 
    .Where(p => p.PartnerServiceBrands 
       .Select(psb => psb.Service.Id) 
       .Contains(search.ServiceId)) 
    .Where(p => p.PartnerServiceBrands 
       .Select(psb => psb.Brand.Id) 
       .Contains(search.BrandId)) 
    .Where(x => x.PartnerServiceBrands 
       .Any(y => y.TrailerService == true)); 
+0

嗨,谢谢,但我不明白你的代码:( – Patrick

+0

,所以你需要所有的三个品质是错误的,通过执行完整的查询。如果任何3测试失败,你返回一个空所以我做的是翻转你的测试的逻辑,如果你的服务ID是0,那么返回一个空的列表,如果BrandId为0,返回一个空的list.if ....一旦所有这些检查都通过了。完整的查询,全部3个谓词颂歌可以清理成1个Where子句,但可以像我一样将它们链接在一起。 – Fran

+0

我想这里的问题是,测试都在同一类方法 – Patrick