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


Overcoming the Barriers Around Using Custom Classes in ASP.NET

Custom classes and collections are often better choices than using a DataSet or DataTable, because they're truly object oriented, letting developers employ robust OOP programming techniques.

ompared to classic ASP, ASP.NET makes a big leap forward in bringing you the advantages of object-oriented programming. However, some aspects like the SQL and .NET data type mismatch, lack of useful common interfaces for all data types, data access, and data binding in Web forms seem to not favor the object-oriented approach and result in lots of coding.

DataSet and DataTable are Microsoft's solutions to these problems. Microsoft provides lots of built-in support for DataSet and DataTable classes in their development tools and in the .NET Framework library. But the DataSet and DataTable are far from object-oriented. Besides, they have lots of overhead. Developers often resort to building custom classes, but unfortunately, the .NET Framework and Visual Studio 2005 don't provide good support for custom classes. As a result, developers often encounter the following three barriers around using custom classes.

  • Data Access. Though Microsoft makes data access with ADO.NET very straightforward and easy to use, developers still have to spend a considerable amount of time to develop the code connecting a custom class to the database. If you take a look at the Pet Shop reference project and the famous CSLA.NET framework you will find that this is never an easy job. The major difficulties come from filling a custom class with data from DataReader and building the SqlParameters, and they prevent further encapsulation of the data access into a truly object-oriented component.
  • Data Binding. Conceptually you can map a custom class or business object to a group of server controls in a Web Form. Two-way data binding and the ObjectDataSource introduced in ASP.NET 2.0 are designed to resolve this problem, but this approach has many restrictions and thus limits the developers' programmatic control of data source.
  • Business Object Template. Here the template refers to the well-known template pattern (References, [1]), not the code generation template. It turns out that abstracting common functionalities into a business object template is difficult or even impossible for custom classes. Developers typically use code generation as a remedy to this problem, but code generation may be a big concern for later upgrade and maintenance as functionalities and the application's code size increases.
Personally I think these three barriers are due to three more fundamental inadequacies in the .NET Framework:

  • The type mismatch between SQL and the .NET Framework. There is no strict 1:1 mapping between the SQL data types and the .NET data types. When you convert a SQL data type to a .NET data type, the data loses its SQL type information. This leads to big problems with custom class data access.
  • Run-time identity loss of custom class properties. Business objects often don't support getting or setting property values using the property name--property names often have little resemblance to the corresponding data field. In contrast, you can identify data in SQL and Web Forms via its identity (table column name and unique control ID). You can use reflection to remedy this problem but you'll sacrifice some performance.
  • Lack of a common interface for the .NET data types and objects. A common interface should contain a common set of properties and methods. For example, the data types in web applications require the support of nullability, state tracking, string formatting and parsing, strong typing, etc.
System.Object is too general to meet this requirement. In terms of composite design pattern (References, [2]), this can be a very serious problem.

In this article I will present a solution to address these three fundamental inadequacies. The solution can completely overcome the barriers around custom class data access and data binding. The solution also allows you to easily abstract common functionalities into business object templates.

The solution consists of two common interfaces called xType and xObject for data type and custom classes respectively. The xType interface always maintains its SQL type information. The xObject interface supports manipulating custom class properties by name. The common set of properties and methods for xType include strong typing, nullability, state tracking, string formatting and parsing, clone, etc. xObject includes two common operations: retrieve a custom class property by name and resolve the real name of the property. The "real name" refers to the corresponding table column name in the database. These two operations suffice to fix the second inadequacy above. You can augment xObject to include other common operations such as iteration, serialization, and so on. Before I jump to the detailed implementation of the common interfaces, here's an early look at how xType and xObject can overcome the three barriers.

  • Data access. Reduce the process of filling custom classes with data from DataReader and building the SqlParameters to one line of code, as shown below. This means that you can build a truly object-oriented data access component to support a custom class:
  •    void FillBizObject(xObject obj, IDataReader dr);
       IList FillBizObjectCollection(
          xObject objSeed, IDataReader dr);
       SqlParameter[] BuildSqlInputParameters(
          xObject obj, params string[] objPropertyNames);
       SqlParameter[] BuildSqlOutputParameters(
          xObject obj, params string[] objPropertyNames);
  • Data binding. Establish the mapping between a group of Web Form fields and a custom class with one line of code, but we need to provide all related server controls a common interface with respect to data binding. These controls are called xControl in this article:
  •    static void BindDataFromBizObjectToWeb(xObject 
          obj, params xControls[] arrxControls);
       static void BindDataFromWebToBizObject(xObject 
          obj, params xControls[] arrxControls);
       static void BindDataFromBizObjectToWeb(xObject 
          obj, Control container, params string[] 
       static void BindDataFromWebToBizObject(xObject 
          obj, Control container, params string[] 
  • Create reusable business object templates. The common interfaces make it possible to abstract the common functionalities into the business object templates. The template classes do not only centralize your code, but they also allow you the flexibility to override the default functionalities with your own. In this article I will illustrate this flexibility by wrapping the Active Record and the Dynamic Object into the business object templates.
In the rest of the article I will introduce xType and xObject and their implementations. Then I will illustrate how to use xType and xObject to achieve the goals above. I will conclude with examining some representative code from the Microsoft .NET Pet Shop project and discuss how you can use xType and xObject in practical Web applications. You will see the benefits that xType and xObject offer.

Editor's Note: This article was first published in the May/June 2007 issue of CoDe Magazine, and is reprinted here by permission.

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