Click here to Skip to main content
Click here to Skip to main content

Using LINQ to Filter by Object Type and Then Quantify

By , 11 Sep 2012
Rate this:
Please Sign up or sign in to vote.

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.

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.

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)

About the Author

Joe Rattz
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 PinmemberMember 313707823-Sep-12 19:52 
QuestionHow does the code work? [modified] PinmemberJeff Lindholm13-Sep-12 8:04 
AnswerRe: How does the code work? PinmemberJoe Rattz13-Sep-12 8:44 
Suggestion.Any() and .All() would be equally efficient PinmemberMatt T Heffron12-Sep-12 7:46 
GeneralRe: .Any() and .All() would be equally efficient PinmemberJoe Rattz13-Sep-12 3:51 
GeneralMy vote of 5 PinmvpKanasz Robert12-Sep-12 3:20 
QuestionFormatting PinmemberKenneth Haugland11-Sep-12 10:33 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 11 Sep 2012
Article Copyright 2012 by Joe Rattz
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid