September 2007 - Posts

Well, it looks like the dog days of summer are over, and the community is once again hopping with activity.  September and October are going to be busy months for me!  In less than a 30 day period I'll be speaking at 2 code camps and REMIX!  I'm pretty excited about the opportunities, and hopefully I'll get to meet some of you at these events.  Here's a quick list of what and where - you can also look at the Infragistics community calendar to see what other events Infragistics will be involved with.

Sept 15, 2007 - Philly Code Camp

Sept 29,30 2007 - Boston Code Camp (Rise of the Silverlight Surfer)

Oct 8,9 2007 - ReMix07 Boston.  BTW, if you're interested in attending REMIX, you can use the following code for a sweet discount - RM07EXTB

Performance Through Custom Paging

These days, just about every ASP.NET application has a grid of some sort in it, which is tied to a back end database through some databinding mechanism.  In many cases this is either a DataSet, SqlDataSource, ObjectDataSource, or in some cases a custom business object layer.  Further pushing the envelope, grids are no longer used to display 50 or 100 records, but thousands to hundreds of thousands have become commonplace.  AJAX can be used to boost performance by enabling paging, while not horribly disrupting the user experience.  In this case, getting the data from you DBMS to your application becomes the bottleneck. 

If you're paging on the front end, and not the back end, you're not working as efficiently as you can.  In the past there was a valid excuse, SQL 2000 didn't support paging.  That's right, I said in the past because SQL 2005 does support this.  Unfortunately, the logic couldn't be built directly into the SQLDataSourceControl for ASP.NET.  The solution lies in the ObjectDataSource, and good old typed DataSets.  ScottGu posted some links on this about a year ago, and 4GuysFromRolla.com has a great article with source code available here.

Putting it to Use

So what's the big deal?  Well, I don't get to work with large datasets very often, so I figured I would setup AdventureWorks on my laptop and give it a go.  I followed the article (mostly) and set up my TypedDataSet and ObjectDataSource.  Then I started setting up the Infragistics WebGrid to do partial databinding.  That's when things started going wrong for me.  See, I had already planned out exactly how I was going to connect my grid to the data, using the PartialDatabinding feature of the grid.  If you've never used this feature before, it's pretty hardcore.  The InitializeDataSource event is used, and the eventargs can be cast to the specialized DataSourceEventArgs.  In short, the event allows you to provide the grid with a page of data, rather than forcing you to bind to a complete set of data.  Well, when I assigned my ObjectDataSource to the Grid's DataSourceID property, my InitializeDataSource event stopped firing - but data was still showing up accordingly.  Confused, I turned to SQL and attempted to use the SQL profiler to find out what was actually going on. 

Off-topic Rant

If you're not in the mood for a story, you can skip this paragraph.. Remember how I said things started going wrong?  this is where they really went wrong.  I only had the Express version of SQL and Management Studio installed, so that meant no profiler.  I popped in the CD for the full version of SQL to install the workstation tools, and started the install.  The install was nice enough to let me know that I could not install the workstation tools, because I already had a newer version of the components installed.  So, I attempted to remove SQL Express and all of its components.  Yes, I attempted.. after 'uninstalling' the components, they were all still there!  I went on to manually uninstall the components, and finally decided to turn of UAC (yes, I was using Vista).  If this ever happens to you, ARPWrapper.exe /remove is your friend.  It took me about 3 hours of installing and uninstalling to finally get to a point where I had the full version of SQL 2005 installed and working. 

Unexpected Surprise

Ok, back to work.. time for some profiling.  I started up the profiler and took a look at the queries and the parameter values.  To my amazement, the WebGrid was already doing the data paging for me.  I didn't need to mess with the custom partial databinding through the InitializeDataSource event, I just had to provide the grid with a pageable datasource.  I didn't really believe it at first, but confirmed it with the SR. Developer on the grid team.  It turns out, he put in support for data paging for datasources a while back as a quasi bug fix, but since the SQLDataSource doesn't support data paging, the feature went pretty much unnoticed for the most part. 

Key Takeaways

One thing to keep in mind is that paging your back end data does not have to be paired with your typical paged results in a grid ie. [First prev next Last].  In the WebGrid for instance, paged data can be displayed through a scrolled interface via the "VirtualScrolling" feature.  The beauty here is that the end user still feels like they're looking at the entire dataset at once - while the grid manages to pull down the appropriate pages of data asynchronously.  You can see what I mean by looking at the ScrollOnDemand sample. When combining this performance and user friendly front end technique with an efficient and speedy paged datasource connecting to your back end, you get the best of both worlds.

A couple of stumbling points.. The ObjectDataSource uses the same signature for the SelectMethod and SelectCountMethod - in otherwords, if you define 2 paramters for your SelectMethod, the ObjectDataSource will use those same parameters for the SelectCountMethod.  I added the dummy parameters to my SelectCountMethod definition in my TableAdaptor to make everyone happy.  Also, sorting is a slightly more complicated issue than you would hope.  The beauty of parameterized queries is defeated when you can't parameterize an ORDER BY.  To get around this a bit of dynamic SQL or a cased SPROC is in order.  There's a great article on how to do that from 4GuysFromRolla.com.

You can download the source here (http://download.infragistics.com/users/tonyl/custompaging.zip)  All you'll need to do is set up the connection string and press play!

I started working with VS2008 pretty regularly about a month ago.  One of the first things I wanted to try out was LINQ.  I had been to assorted sessions at PDC, TechEd, MIX, and some other shows where they covered LINQ, and I was pretty impressed.  In the past, figuring out how to use a new VS feature was almost like a treasure hunt.  You could pick up clues here and there, but putting it all together was challenging.  I'm not sure if it's due to Scott Gu's blogs, or the intuitive nature of LINQ (or both), but I was pleasantly surprised that I could do it! 

Using the LINQ to SQL classes, I created a DataModel which mapped to my SQL tables.  It was then just a bit of simple LINQ to bind the records to my table.  Basically in 20 minutes I had created a LINQ based data structure and hooked up my tables to create a master details view.  Now that's not to say that I've mastered LINQ, but that does speak to it's intuitive nature. 

My back end data was the Adventure Works database served up from SQL.  Here's a look at my DataBinding code:

DataClassesDataContext context = new DataClassesDataContext();
var employees = from emp in context.Employees
                select new
                {
                    EmployeeID = emp.EmployeeID,
                    Name = emp.Contact.LastName + ", " + emp.Contact.FirstName,
                    BirthDate = emp.BirthDate
                };
this.GridView1.DataSource = employees;
this.GridView1.DataKeyNames = new string[]{"EmployeeID"};
this.GridView1.DataBind();

And then my detailsview code:

DataClassesDataContext context = new DataClassesDataContext();
var contact = from c in context.Employees
               where c.EmployeeID == (int)this.GridView1.SelectedDataKey.Value
               select c.Contact;
this.DetailsView1.DataSource = contact;
this.DetailsView1.DataBind();

Something worth pointing out - in the first snippet, notice that I'm doing a "select new"  I'm using an anonymous type here so that I don't have to stub out a class just to represent my data.  This feature is great.  I always thought there must be a better way than stubbing out dummy classes just to act as my business objects.  Now that's not to say that there's no need for creating separate business object classes anymore, but this makes a nice alternative for the simpler cases, where a full business object layer may be overkill.   

Some of you may already know me, or know of me from my long history with Infragistics.  If you've never heard of Infragistics, they're a UI Tools company that deals mainly in the Microsoft spaces including ASP.NET, Windows Forms, WPF, and now Silverlight. 

I've been working with ASP.NET since its initial alphas.  It was always fun to talk about how long I've been working with ASP.NET and have others try and call me out.  What they didn't know was that while they were still in DLL Hell developing in COM, I was rising out of the water into a new world of web development.  If you've ever worked with a brand new technology as I'm sure many of you have (and still are), it's difficult to say the least, as no formal documentation is available yet.  As you're learning it, so are those who will be publishing books over the next year or two.

As many of you have come to realize, working with ASP.NET means you must master multiple technologies, especially if you're on the UI side of things.  So over the years I've come to know Javascript and CSS quite intimately.  We started out as enemies, but I'm happy to say we're really good friends now.  I've also been working my way down the ASP.NET stack, beyond the UI.  Working with HTTP Handlers and Modules, custom config sections and expression builders - all of the pieces that aren't part  of your every day needs, but provide very powerful options when you do need to call on them - and they also make great material for my blog. 

More Posts