Click here to Skip to main content
15,880,905 members
Articles / Programming Languages / SQL
Technical Blog

Using LINQ to Filter by Object Type and Then Quantify

Rate me:
Please Sign up or sign in to vote.
4.90/5 (3 votes)
11 Sep 2012CPOL3 min read 12.2K   2   7
Using LINQ to filter by object type and then quantify.

Introduction

Every so often I run across a case where LINQ comes in so handy that I just want to post a quick article sharing some particular usage of it. For this example I was working on a web page that shows user roles and their permissions within my application. Below is a photo showing how the display looked before my added LINQ code.

457315/RoleDefinitions1.jpg

My web application has other roles not listed in that image. This is why there are some permissions that none of the listed roles are approved for such as "Allow Access To Site/User/Role Maintenance". For this page, I wanted to omit any rows from the display where at least one of the roles wasn't approved for it. After all, these permissions were irrelevant for these roles. Displaying them would only confuse my users and invite support questions.

The data is being displayed in an ASP.NET GridView that has been bound to a DataSet. To omit the rows, I decided I would filter the DataSet prior to assigning the GridView's DataSource property and calling its DataBind method. Please notice that the first column of the GridView will contain a string for the description of the permission and each subsequent column will contain a bool specifying if that role is approved for the permission. One thing not obvious from the image is that the number of roles is driven by the database and is not static. If I add another role to my application there will be another column added here and I wouldn't want to have to modify this code to accommodate the additional role.

Below is my code to call the method to filter the DataSet. GetMyRoleData is just a dummy method to acquire the needed data and I do not show it in this example. I then call the FilterRows method that will delete all the rows from the DataSet for which no role has approval for that row's permission. I then set the GridView's DataSource property and call the DataBind method. Nothing of note so far.

C#
DataSet ds = GetMyRoleData();
FilterRows(ds);
RoleComparisonView.DataSource = ds;
RoleComparisonView.DataBind();

Next comes my method to actually filter the unwanted rows. It would have been very easy to enumerate through each row, which I did, and then enumerate through each column of the row. If every column is set to false, delete the row. Or, if any column is true, don't delete the row. The latter would be more efficient because I could stop checking once the first column had a true value.

But instead of enumerating through each column and checking its value, LINQ can make the code so much simpler. Why not just use the Any operator? If any of the elements in the row's array of items is true, then I don't want to delete the row. Alternatively, I could use the All operator and make sure they are all set to false, but again, this would be less efficient and require every item to be checked. Using the Any operator instead of the All operator allows the code to stop once an item is true.

There is one last complication and that is the fact that the first column of each DataRow is a string for the permission description and not a bool for a role. This can easily be overcome though with the OfType operator. Just call the OfType operator on the array of items, ItemArray, and specify to only return elements of type bool. It's just that simple. Here is the code.

C#
private void FilterRows(DataSet ds)
{
    bool someRoleHasPermission;
    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        someRoleHasPermission = dr.ItemArray.OfType().Any(b => b == true);
        if (!someRoleHasPermission)
        {
            dr.Delete();
        }
    }
}

So, I enumerate through each DataRow in the DataTable's Rows collection. I then call the OfType operator on the row's ItemArray to return only those items that are a bool. Last I call the Any operator and provide a lambda expression returning true if any of the items is set to true. Very simple. I then call the DataRow's Delete method if I got a false back from the LINQ query. Just like that, my permissions have been filtered. Here is one last image showing the GridView after calling the FilterRows method:

457315/RoleDefinitions2.jpg

As you can see, LINQ can make so many chores just that much more simple.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Genuine Parts Company
United States United States
Author: Pro LINQ: Language Integrated Query in C# 2008
Co-author: Pro LINQ: Language Integrated Query in VB 2008

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 313707823-Sep-12 19:52
Member 313707823-Sep-12 19:52 
Great!
QuestionHow does the code work? Pin
Jeff Lindholm13-Sep-12 8:04
Jeff Lindholm13-Sep-12 8:04 
AnswerRe: How does the code work? Pin
Joe Rattz13-Sep-12 8:44
Joe Rattz13-Sep-12 8:44 
Suggestion.Any() and .All() would be equally efficient Pin
Matt T Heffron12-Sep-12 7:46
professionalMatt T Heffron12-Sep-12 7:46 
GeneralRe: .Any() and .All() would be equally efficient Pin
Joe Rattz13-Sep-12 3:51
Joe Rattz13-Sep-12 3:51 
GeneralMy vote of 5 Pin
Kanasz Robert12-Sep-12 3:20
professionalKanasz Robert12-Sep-12 3:20 
QuestionFormatting Pin
Kenneth Haugland11-Sep-12 10:33
mvaKenneth Haugland11-Sep-12 10:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.