RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


The Baker's Dozen Doubleheader: 26 Productivity Tips for Managing Data (Part 2 of 2)

The conclusion of a two-part article on managing data with Visual Studio 2005 and SQL Server focuses on .NET generics, provides an introduction to the new ObjectDataSource class, and demonstrates some additional new capabilities in T-SQL 2005.

egardless of whether you work in C# or VB.NET, or whether you spend more time on the front-end or back-end of an application, the ability to manage data will directly impact your contributions to a project.

The new .NET generics classes provide you with near-quantum leap in efficiency by allowing you to write simpler code that accomplishes more. ASP.NET 2.0's ObjectDataSource class helps you to easily integrate middle-tier data-aware classes to data-bound controls on a Web page. Finally, as you saw in Part 1 of this series (and will see again here in Part 2), T-SQL 2005 provides new language capabilities to help database developers be more productive.

In the conclusion of this two-part series on managing data, I will focus on .NET generics, the ASP.NET 2.0 ObjectDataSource, and some more T-SQL 2005 capabilities.

Beginning with the End in Mind: An Entire Potpourri of Data Handling Tips
It's a typical sunny day as I type this from my back porch, and the data-handling capabilities in Visual Studio 2005 and T-SQL 2005 have never been hotter. I just finished a long road trip of presenting at community events and conferences, and I returned with a ton of energy that I'll inject into this issue's tips.

.NET generics classes provide you with near-quantum leap in efficiency by allowing you to write simpler code that accomplishes more. Those whose "holy grail" includes strongly-typed yet flexible code will ultimately fall in love with .NET generics.
So, let's play ball! Here's the lineup for the second game of our Baker's Dozen doubleheader (of course, a baseball lineup has nine players, we have thirteen tips!).

  • Batting first through seventh I'll show seven tips for circling the bases using .NET generics. The Baker's Dozen Spotlight will appear in Tip #7: a generic data access class that fills a typed dataset from a stored procedure.
  • The middle of the line-up (Tip 8) will show basic examples to demonstrate the new ObjectDataSource capability in ASP.NET 2.0.
  • The back-end of the lineup will feature (only fitting) five more tips for the back-end database! Tips 9 through 13 pick up where Part 1 left off: More ways to use T-SQL 2005 to work with data.
Tip 1: An Overview of .NET Generics
In many instances, .NET generics can be explained in terms of tasks developers tried to accomplish in Visual Studio .NET 2003.

Many developers used the ArrayList collection class in Visual Studio 2003 to store a list of objects, as illustrated in the code below. In this example, I am simply storing a list of integers: I could just as easily store a collection of form objects, data tables, or other objects.

   // Visual Studio 2003 code
   ArrayList list = new ArrayList();
   // implicit boxing, must convert value 
   // type to reference type
   int nFirst = (int)list[0];
   int total = 0;
   foreach (int val in list) 
      total = total + val;

Note these three issues with the snippet:

  • First, regardless of what specific type I store in the ArrayList, the ArrayList stores it as an object. So there is an implicit conversion, or "boxing" operation that occurs.
  • Second, when I retrieve a specific item from the ArrayList, .NET must convert the item from an object back to the source data type (and I must specify the data type). So there is an "unboxing" operation that occurs.
  • Finally, I have no compile-time type safety checking. In the ArrayList, I store two integers and then a decimal to the ArrayList. When I iterate through the collection on the last two lines, .NET will generate an error at run time because I am attempting to cast the decimal value (5.0) as an integer.
In Visual Studio 2005, I can use the new List class from the System.Collection.Generic namespace. The List class addresses the issues in the ArrayList class by allowing me to define the specific type I wish to store for a specific instance of the class.

   // Visual Studio 2005 code
   // define the stored data type in the placeholder 
   List aList = new List();
   // The following line generates a compile error
   // no need for unboxing, value type stored in 
   // List as an int, not an object
   int nFirst = aList[0];   
   int total = 0;
   foreach (int val in aList) 
      total = total + val;

Because I am defining the stored type when I create an instance of the List class, .NET does not need to perform any boxing or unboxing. .NET knows that I am storing an integer. Additionally, I do not need to cast a specific item in the List.

While it would take a large number of instantiations to measure a difference in performance, the increased efficiency in storage and compile-time safety are more than enough to appreciate the differences between the ArrayList and List classes.

Still, it's important to know that I'll pay a small performance penalty by using the ArrayList class. The code below creates an ArrayList, stores a million integers, and iterates through the list. It takes approximately two-tenths of a second to run.

   // Visual Studio 2003 code - takes .2 seconds
   ArrayList aBigList = new ArrayList();
   DateTime dt1, dt2;
   dt1 = DateTime.Now;
   for (int nCtr = 0; nCtr < 10000000; nCtr++)
   int nSum = 0;
   foreach (int nn in aBigList)
      nSum += nn;
   dt2 = DateTime.Now;
   TimeSpan ts = dt2.Subtract(dt1);

When I rewrite the code to use the new List class, the code runs in four-hundredths of a second, or five times faster.

   // Visual Studio 2005 code - takes .04 seconds 
   List aBigList = new List();
   DateTime dt1, dt2;
   dt1 = DateTime.Now;
   for (int nCtr = 0; nCtr < 1000000; nCtr++)
   int nSum = 0;
   foreach (int nn in aBigList)
      nSum += nn;
   dt2 = DateTime.Now;
   TimeSpan ts = dt2.Subtract(dt1);

Next I'll take a look at generic methods, which allow developers to create tremendous flexibility in their code. At an MSDN CodeCamp event last year, Carl Franklin (of .NET Rocks! fame) stated that a great use for generics is when you have multiple classes that differ only by type.

Consider some code that compares two values and returns the greater value of the two. I could use it to compare strings, dates, integers, etc. I could write multiple methods, or write one method with multiple overloads, or resort to some other trickery. However, .NET generics allow me to write a single method to cover multiple data types. Here is where .NET generics truly shine.

In the code below, I'll set up a method called CalcMax. Note the use of the letter "T" and the placeholder . I don't need to specifically use the letter T: I could use some other letter or an entirely different word. However T serves as a meaningful designator for a type placeholder.

   public T CalcMax ( T compVal1, T compVal2) 
   where T : IComparable 
      T returnValue = compVal2;
      if (compVal2.CompareTo(compVal1) < 0) 
         returnValue = compVal1;
      return returnValue;

In CalcMax, I define a type placeholder for the return value, and a type placeholder for the two parameters. The only rule is that the type passed must implement IComparable, since I am using the CompareTo method of the parameters.

I can call CalcMax several times, specifying different data types each time.

   double dMax = CalcMax(111.11,333.23);
   int intMax =  CalcMax(2, 3);
   string cMax = CalcMax("Kevin", "Steven");
   DateTime dtMax = CalcMax 
       (DateTime.Today, DateTime.Today.AddDays(1));

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date