2016-11-10 11 views
0

いくつかの条件リストに基づいてレコード(パートナー)のリストを作成しようとしています。問題は、LINQによって生成されたSQLが条件の少なくとも1つを尊重するパートナーを選択しており、適用する必要のある条件(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

2つの異なるテーブルPartner_IdとPartnerServiceBrandsを照会しています。したがって、2つのテーブルを結合し、結合された結果をフィルタリングする必要があります。 msdn:https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

+0

を参照してくださいありがとうございます!私の場合の例を示唆したいですか? – Patrick

+0

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を返します。これらのチェックがすべて合格したらrunすべての3つの述語を持つ完全な照会。そのc odeは1 Where句にクリーンアップすることができますが、私が行ったときと同じようにチェーン化することができます。 – Fran

+0

ここで私が思う問題は、テストはすべて同じクラスのメソッドであるということです – Patrick

関連する問題