How pipes and filters pattern with IQueryable simplifies your data access.

Leave a comment

March 3, 2009 by temebele

Pipes and Filters Pattern

Pipes and Filters help you break processing into a sequence of simpler transformations.

ADO.NET Entity Framework with LINQ to Entities gives you flexibility to have a pipe and filter architecture for filtering data as it goes through a pipeline. You use extension methods with IQueryable to achieve this flexibility.

What I really found so handy in my current project was to add a method called "ApplyAllFilters" in your filter class. That method will have the logic to apply different filters based on our business rules. Your repository will only have a single method that takes all possible filter parameters and then it calls ApplyAllFilters extension method.

Example:

Filter class:

using System.Linq;

public static class ServiceZoneFilters
{
    public static IQueryable<SERVICE_ZONE> ForCountry(this IQueryable<SERVICE_ZONE> qry, int countryID)
    {
        return from a in qry
               where a.ZONE.COUNTRY_LOOKUP.COUNTRY_ID == countryID
               select a;
    }

    public static IQueryable<SERVICE_ZONE> ForZoneLabel(this IQueryable<SERVICE_ZONE> qry, string zoneLabel)
    {
        return from a in qry
               where a.ZONE.ZONE_LABEL.ToLower() == zoneLabel.ToLower()
               select a;
    }

    /// <summary>
    /// Zone type CD
    /// Pass ‘RATE’ for base rate and ‘ACC’ for accessorial
    /// </summary>
    /// <param name=”qry”></param>
    /// <param name=”zoneTypeCD”></param>
    /// <returns></returns>
    public static IQueryable<SERVICE_ZONE> WithZoneType(this IQueryable<SERVICE_ZONE> qry, string zoneTypeCD)
    {
        return from a in qry
               where a.ZONE.zone_type_cd == zoneTypeCD
               select a;
    }

    /// <summary>
    /// Applies all fiters
    /// </summary>
    /// <param name=”qry”></param>
    /// <param name=”zoneTypeCD”></param>
    /// <param name=”countryID”></param>
    /// <param name=”zoneLabel”></param>
    /// <returns></returns>
    public static IQueryable<SERVICE_ZONE> ApplyAllFilters(this IQueryable<SERVICE_ZONE> qry, string zoneTypeCD,
                                                           int countryID, string zoneLabel)
    {
        if (zoneTypeCD.Length > 0)
        {
            qry = qry.WithZoneType(zoneTypeCD);
        }

        if (countryID != -1)
        {
            qry = qry.ForCountry(countryID);
        }

        if (zoneLabel.Length > 0)
        {
            qry = qry.ForZoneLabel(zoneLabel);
        }
        return qry;
    }
}

Repository:

//Repository:

#region IZoneRepository Members

/// <summary>
/// Get service zones by carrier,country and zone label
/// </summary>
/// <param name=”countryID”></param>
/// <param name=”zoneLabel”></param>
/// <param name=”carrierID”></param>
/// <param name=”query”></param>
/// <returns></returns>
public IList<SERVICE_ZONE> GetServiceZones(string zoneType,int countryID, string zoneLabel, int carrierID,SortingAndPagingQuery query)
{
    private IQueryable<SERVICE_ZONE> list =
        ContextQueryBuilder<SERVICE_ZONE>.ApplyContextQuery(
            GetCarrierServiceZonesQuery(carrierID).ApplyAllFilters(zoneType, countryID, zoneLabel), query);

return list.ToList();
}

Note: Don’t worry about the ContextQueryBuilder method that is another wrapper used for dynamic sorting and paging.

I hope you find it helpful.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: