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!!!

Wednesday, June 13, 2012

Using Decimal as Primary key in Entity Framework 4

Entity Framework 4 does some automatic things which is very useful in many scenarios. For example, if we declare a “ID” property for a class, it automatically assumes that property as a primary key for the mapped table in the database. And It also sets the “identity” property of the column to true.

 

int_identity

Figure: Simple model with “integer” type Primary key

 

This works very good in most of the time. Unfortunately, sometimes we may need to use “decimal” data type rather than “integer”, specially for large table.

 

decimal

If we want to see the same behavior for decimal that we have seen for integer before (for example, set primary key and identity property), we need to do some extra configurations:

1. Explicitly add the “DatabaseGenerated” attribute to set the “identity” value of the column in database.

[DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]

2. Specify the precision for the decimal data type. This is because by default it assumes there are two numbers after the decimal for decimal data type. We need to set it 0.

modelBuilder.Entity<User>().Property(x => x.ID).HasPrecision(16, 0);

 

That’s it. Lets see the full view after updating the classes-

user-full

Figure: User class after adding the attribute

 

dbcontext

Figure: Set precision for ID

Now add users in the database through the application. “ID” will be automatically increment by 1 like the integer before.

 

Happy programming!

Monday, May 21, 2012

Left Outer Join Using LINQ

I was in a kind of puzzled while I started searching how to do left outer join with LINQ. Finally, I found the solution and proper explanation of left outer join using LINQ. I am going to explain that here to help those who is still searching and also for my future reference :-)

We know “Join” combines two or more tables in a database. And by definition, left outer join returns all the values from the left table; doesn’t matter whether they match or not with the right table (returns NULL, incase don’t match).

We need to use LINQ’s “DefaultIfEmpty()” function to accomplish the task which returns the default value if the sequence is empty. It also takes default item as the parameter. However- let’s see how can we do a left outer join between Customer and Order table using LINQ:

list = from c in customers
                   join o in orders on c.ID equals o.CID into t_c

                   from r in t_c.DefaultIfEmpty()
                   select new { Name=c.Name, Item=(r!=null)?r.Item:"nothing" };

We have two steps in the above query:

1. Produce a collection by doing inner join between orders and customers table.

2. Use “DefaultIfEmpty” to invoke each element of first collection.

For your reference, below is the Customer and Order classes:

   class Customer {
        public int ID { get; set; }
        public string Name { get; set; }
    }


    class Order {
        public int ID { get; set; }
        public int CID { get; set; }
        public string Item { get; set; }
    }

Please check in MSDN for more details explanation-

http://msdn.microsoft.com/en-us/library/bb397895.aspx

Happy Programming!

Thursday, May 10, 2012

Customizing ASP.Net MVC Template

Asp.net scaffold templates for controller and view are really useful but often we need to change the default template to fit with particular project. It's easy to do. Follow the steps below to customize the ASP.Net MVC3 built-in T4 template:

  1. Go ahead and find the default template from the following location- 
  2. [Visual Studio Installation Directory]\Common7\IDE\ItemTemplates\CSharp\Web\MVC 3 
  3. Copy the "CodeTemplates" folder. 
  4. Paste the "CodeTemplates" folder to the project's root. 
  5. Remove the templates(extension '*.tt') that you do not need to customize from the project's "CodeTemplates" folder. 
  6. Select the templates(press and hold ctrl and click on the template) and go to properties(right click and select properties). 
  7. Clear "Custom Tool" entry. By doing this, it will not run the template automatically every time you build the project. 
  8. Now customize the template as you want and build the project. 
  9. Right click on View folder and select add view. From the add view popup dialog box, select the model class and you will find the customized template in the "scaffold template" drop down list. 

 Happy Programming!

Saturday, April 2, 2011

Top Ten Errors Java Programmers Make

I found a wonderful article while I was tracing an error in my code. Here is the article Top Ten Errors Java Programmers Make. Can you believe, I did the number one error among the listed top ten errors!!! :(

According to the author, Below are the top ten mistakes that java programmer do while they do coding. So look at them and stop doing the same error again and again :)

10. Accessing non-static member variables from static methods (such as main)
9. Mistyping the name of a method when overriding
8. Comparison assignment ( = rather than == )
7. Comparing two objects ( == instead of .equals)
6. Confusion over passing by value, and passing by reference
5. Writing blank exception handlers
4. Forgetting that Java is zero-indexed
3. Preventing concurrent access to shared variables by threads
2. Capitalization errors
1. Null pointers!

For details, please visit the original article.

Happy programming!

Thursday, March 3, 2011

Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack

Suddenly I am getting the error "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack" from my asp.net application. After spending sometimes online, I found the following cause and solution for the error. Hope the solution might help you, if you are facing the same problem.

Error: Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack

Cause: If you use either Response.Redirect or Server.Transfer method, you may face this problem. I was calling Response.Redirect method inside the Try...Catch block. This happens because both methods call Response.End internally.

Solution: Pass "false" to endResponse parameter of Response.Redirect method

Response.Redirect ("xyz.aspx", false);

Thats it. Simple.

Happy programming!