Filter on a value in a SubPath entity

Posts   
 
    
neilx
User
Posts: 267
Joined: 02-Nov-2007
# Posted on: 16-Sep-2010 23:34:31   

LLB v2.6 Oct 9th Final Win 7

I am trying to filter an entity collection by a value that appears deep in a subpath graph:

[code] public IQueryable<TopicTextEntity> CreateDataSource() { var topicTextEntities = (from a in metaData.TopicText where !a.ReadyforPublication && a.TopicBase.TopicRegion.All(m =>m.Region.ActiveDirectoryLogonCollectionViaCountriesByConsultant.Where(n=>n.Logon == userInfo.Username).Count() > 0) select a) .WithPath(c => c.Prefetch<TopicBaseEntity>(d => d.TopicBase) .SubPath(e => e.Prefetch<TopicRegionEntity>(f => f.TopicRegion) .SubPath(g=>g.Prefetch<RegionBaseEntity>(h=>h.Region) .SubPath(i => i.Prefetch<CountriesByConsultantEntity>(j => j.CountriesByConsultant) .SubPath(k=>k.Prefetch<ActiveDirectoryLogonEntity>(l=>l.ConsultantsLogon)))))); return topicTextEntities; } [code]

This method works without the second filter. I was trying to make sure all the TopicRegionEntities contain valid rows for the currently logged on user as defined in the CountriesByConsultant entity:

                                    && a.TopicBase.TopicRegion.All(m =>m.Region.ActiveDirectoryLogonCollectionViaCountriesByConsultant.Where(n=>n.Logon == userInfo.Username).Count() > 0)

Can anyone suggest a better direction for me to investigate to achieve the filtering of an entity by a value in a SubPath entity?

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 16-Sep-2010 23:48:15   

What is the actual issue - ie what is not working when you include the second filter...? What does the generated SQL look like in both cases ?

Matt

neilx
User
Posts: 267
Joined: 02-Nov-2007
# Posted on: 18-Sep-2010 00:42:53   

It was crashing. I think I have sorted that now. I have also stripped out the predicate and used it on the whole link. It looks a bit clearer that way:


public IQueryable<TopicTextEntity> CreateDataSource()
{
    var languageCode = HttpContext.Current.Request.QueryString["LanguageCode"] ?? "en";
    var topicTextEntities = ((from a in metaData.TopicText
                                where a.ReadyforPublication == false && a.LanguageCode == languageCode
                                select a).IncludeFields(a => a.Topic)
        .WithPath(d => d.Prefetch<TopicBaseEntity>(e => e.TopicBase)
                            .SubPath(f => f.Prefetch<TopicRegionEntity>(g => g.TopicRegion)
                                .SubPath(h => h.Prefetch<RegionBaseEntity>(i => i.Region)
                                    .SubPath( j => j.Prefetch<CountriesByConsultantEntity>( k => k.CountriesByConsultant)
                                        .SubPath( l => l.Prefetch <ActiveDirectoryLogonEntity>( m => m.ConsultantsLogon)))))))
        .Where( n => n.TopicBase.TopicRegion.Any( o => o.Region.CountriesByConsultant.Where(p => p.ConsultantsLogon.Logon == userInfo.Username). Count() > 0));
    return topicTextEntities;
}

I needed to understand what .Any and .All do:-)

The SQL is very fast (5x faster than my old joined tables script!) so well done to the team for knowing how to get high performing - if a little obscure - script:

I am still not sure my .Count() > 0 is a good thing though even though it seems to work. I have used it as the .Where needs a boolean to be returned and I couldn't think of a simpler way to do that. So any suggestions on this point would be most welcome.

I don't understand the SQL well enough to see if there are any pitfalls:


DECLARE @ReadyforPublication1 BIT = 0
DECLARE @LanguageCode2 varchar(6) = 'en'
DECLARE @Logon4 nvarchar(50) = 'fred'
DECLARE @LPFA_13 INT = 0

SELECT TOP 1
        COUNT(*) AS [LPAV_]
FROM    ( [dbo].[v2_Topic_Base] [LPA_L1]
          INNER JOIN [dbo].[v2_Topic_Text] [LPA_L2] ON [LPA_L1].[IDTopic] = [LPA_L2].[IDTopic]
        )
WHERE   ( ( ( ( ( ( ( ( [LPA_L2].[ReadyforPublication] = @ReadyforPublication1 )
                AND ( [LPA_L2].[LanguageCode] = @LanguageCode2 ))))
              )
          AND EXISTS ( SELECT   [LPLA_3].[IDTopic]
                       FROM  [dbo].[v2_TopicRegion] [LPLA_3]
                       WHERE    ( [LPA_L1].[IDTopic] = [LPLA_3].[IDTopic]
                                  AND ( ( SELECT    COUNT(*) AS [LPAV_]
                                          FROM    ( ( [dbo].[REGION] [LPA_L3]
                                                        INNER JOIN [dbo].[CountriesByConsultant] [LPA_L4] ON [LPA_L3].[CountryCode] = [LPA_L4].[CountryCode]
                                                                                                             AND [LPA_L3].[RegionCode] = [LPA_L4].[RegionCode]
                                                      )
                                                      INNER JOIN [dbo].[ConsultantsLogon] [LPA_L5] ON [LPA_L5].[IDCounter] = [LPA_L4].[IDContact]
                                                    )
                                          WHERE  ( ( [LPA_L3].[CountryCode] = [LPLA_3].[CountryCode]
                                                        AND [LPA_L3].[RegionCode] = [LPLA_3].[RegionCode]
                                                      )
                                                      AND ( [LPA_L5].[Logon] = @Logon4 )
                                                    )
                                        ) > @LPFA_13 )
                                ) )))
        )

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 18-Sep-2010 13:14:03   

Seems like if that is the only way. When you need to filter deep down you need to do it in the main query, not in the subpath, so I think your query is ok.

David Elizondo | LLBLGen Support Team
neilx
User
Posts: 267
Joined: 02-Nov-2007
# Posted on: 18-Sep-2010 14:40:54   

daelmo wrote:

Seems like if that is the only way. When you need to filter deep down you need to do it in the main query, not in the subpath, so I think your query is ok.

OK. I'll stick with it as works and is fast:-) Thanks for commenting.