Monday, October 7, 2013

Filter an IQueryable Datasource on the Fly using Expression Tree

LINQ(Language Integrated Query) is a wonderful language of Microsoft.net Framework. Now a days most of the .net developer using it in their project. LINQ has so many benefits to use. However- there are few limitation of LINQ too. One of the major limitation of LINQ is – lacking of generating LINQ expression dynamically. I know this is probably not a standard feature of any programming language but this is often needed when we use LINQ with other languages. However- there are several solutions exists for this problem. Most acceptable solution probably is using Expression Tree.

Problem Description:
Say, we have following LINQ Query:

image

We like to filter out all the tickets that has expire date and not currently selected by user. User’s selection (selected item ID) will be send to the function dynamically through the function parameter. Therefore, we want to create a expression tree which will generate a LINQ query like below:

image

Solution:
Let’s create the expression tree step by step:

1. Do not forget to add namespace Winking smile

image

2. Define the  column name and data type to filter

image

3. Initialize the Binary Expression and Lamda Expression

image

4. If the selected item is passed through the function parameter, keep it in the exception list and create the lambda expression dynamically based on it.

image

5. Now, we have everything to build the where clause

image

6. Return the result

image

Full Source Code:
Below is the full source code at a glance:

///
/// Filter expired items(ignores selected item) from an IQueryable datasource.
/// Assumption: Datasource should have a column "Expire_Date"
///
/// IQueryable Datasource
/// Data Value Field
/// Selected Value
/// IQueryable Data Items

    public static IQueryable GetFilteredData(IQueryable dataSource, string dataValueField = null, object selectedValue = null)
    {
        try
        {
            //filtered items
            string expiredDateColumnName = "Expire_Date";
            ParameterExpression p = Expression.Parameter(dataSource.ElementType, "p");
            MemberExpression prop = Expression.Property(p, expiredDateColumnName);

            var value = Expression.Constant(null, typeof(DateTime?));

            BinaryExpression binaryExpr1 = Expression.Equal(prop, value);
            LambdaExpression pred = null;

            if (selectedValue != null &&
                !string.IsNullOrEmpty(dataValueField)
                )
            {
                var selectedValueExpr = Expression.Constant(selectedValue, selectedValue.GetType());

                //ignore selected item
                MemberExpression memberExpr2 = Expression.Property(p, dataValueField);
                Expression binaryExpr2 = Expression.Equal(memberExpr2, selectedValueExpr);

                Expression orExpr = Expression.OrElse(binaryExpr1, binaryExpr2);
                pred = Expression.Lambda(orExpr, p);
            }
            else
            {
                pred = Expression.Lambda(binaryExpr1, p);
            }

            var where = Expression.Call(typeof(Queryable), "Where", new[] { dataSource.ElementType }, dataSource.Expression, pred);


            var result = dataSource.Provider.CreateQuery(where);
            return result;
        }
        catch
        {
            throw;
        }
    }



Happy Programming!!!

Session Lost Issue in IE8

I know there are many developers do not like Internet Explorer but still we need to provide support for it because of the popularity/demand. One of main reason of the popularity is probably because it is the default browser of the giant Microsoft Windows Operating System. However- we will discuss on a very interesting problem (Session Lost problem) of IE8 today.

Background:

We were working on a enterprise level project and found that session variables are  getting reset on a specific page during page load event. Strange thing!!! The codes inside the page load event are very straight forward. All it is doing is bind some datagrids based on some session variables.

Initial Thought:

We initially assume that it might be because of buggy source code and our initial focus was the function that retrieve the value from session (e.g. session manager). Next we thought this might be a issue how internet explorer handle cache variable. However- definitely that was not a issue too. Then we got clueless!!! We started debugging using fidler, firebug, etc.

Issue:

We have found that there are some server side Image Tag (<asp:Image />) in the page which do not have any source (<image src=””/>) value defined. Those images are the symbol of expand and shrink panel(+,- sign). Through Fiddler, we have found that those image tag requesting the default page (Default.aspx) of the folder and in our system, we reset few session variables in default page. This is how the session data losing. However- this is not the case for later versions of IE(IE8+) or other browsers (eg. firefox, chrome, etc). We never thought about it earlier. Thanks Fiddler for helping us to find out this!!!

Solution:

The solution was very simple compare to the discovering of the actual problem. We had to set the value of the image src property (ImageURL property for <ASP:Image/> control) to “#” which solves the issue like charm.

<asp:Image ID="imgSampleCollapseExpand" runat="server" ImageUrl="#" />

However, setting any value to the image SRC property (or ASP:Image’s ImageUrl property) will fix the problem.

Moral:

Always specify the image source property of the image tag. Follow the best practices!!!

 

Happy Programming!!!