Click here to Skip to main content
15,882,152 members
Articles / Web Development / ASP.NET
Article

Populating custom business objects by binding business objects to a GridView using the ObjectDataSource in ASP.NET 2.0

Rate me:
Please Sign up or sign in to vote.
4.30/5 (18 votes)
20 Jan 20063 min read 113.2K   1.3K   51   10
A complete article on how to populate custom business objects using a common method, binding these objects to a GridView using the ObjectDataSource control.

Introduction

This article explains how to load custom business objects and bind them to a GridView. Only one common method is required for loading all business objects. I used a simple attribute class to map data from a database field to an object property. The container for business objects is a generics list. For now, I want to keep it simple. In future, I want to extend the functionality and make it more scalable. This project uses the following new features in .NET 2.0:

  • Loading a DataTable from a DataReader.
  • Obtaining the ConnectionString section from web.config.
  • Generics.
  • The ObjectDataSource control.

Solution walkthrough

This solution contains two projects. The first project (class library) explains how to populate custom business objects from database records. The second project (website) explains how to bind custom business objects to a GridView using an ObjectDataSource control. For demo purposes, I used the "AdventureWorks" database which ships with SQL 2005.

Populate Custom Business Objects (Project: AWBusinessObjects)

This project contains a database helper class, a custom attribute class, a business objects base class and two sample business objects.

Database Helper Class: DBHelper.cs

It is useful for loading data from a database to a disconnected DataTable using a DataReader. This feature is introduced in .NET 2.0. The ConfigurationManager of System.Configuration is used to get the database connection information from the web.config file.

C#
class DBHelper
{
    private string strConn;
    private SqlCommand dbCmd;
    private SqlConnection dbConn;
    private SqlDataReader dbReader;
    private DataTable dbTable;
    //Constructor
    public DBHelper()
    {
        ConnectionStringSettings settings = 
          ConfigurationManager.ConnectionStrings["DBConn"];
        if (settings != null)
        {
            strConn = settings.ConnectionString;
        }
    }
    //Retrieve Data
    public DataTable RetrieveTable(string pSqlText)
    {
        try
        {
            dbTable = new DataTable();                
            dbConn = new SqlConnection(strConn);
            dbCmd = dbConn.CreateCommand();
            dbCmd.CommandText = pSqlText;                
            dbConn.Open();
            dbReader = dbCmd.ExecuteReader();
            if (dbReader != null && dbReader.HasRows)
            {
                dbTable.Load(dbReader);
            }
        }
        finally
        {
            dbConn.Close();
        }
        return dbTable;
    }
}

Attribute Class: MapInfo.cs

It defines the information to map data from a database field to a business object property. Nothing special here. It contains two fields. This attribute can be used at class level, or at property level, or at field level. AllowMultiple controls whether the attribute is multi-use.

C#
[AttributeUsage(AttributeTargets.Class | 
     AttributeTargets.Property | 
     AttributeTargets.Field,AllowMultiple=true)]
class MapInfo: System.Attribute
{
    private string dbFieldName;
    private string objPropertyName;   
    public MapInfo(string pDBFieldName, 
                   string pObjPropertyName)
    {
        dbFieldName = pDBFieldName;
        objPropertyName = pObjPropertyName;
    }    
    public string DBFieldName
    {
        get { return dbFieldName;}
    }
    public string ObjPropertyName
    {
        get { return objPropertyName;}
    }    
}

Base Class for Business Objects: AWBase.cs

This contains the common method for populating inherited business objects. Reflection is used here for getting custom attributes and properties. It loops through all rows in a DataTable and sets property values using a custom attribute array. A generic list of the base class type is used as the container for the business objects. If the database value is DBNull then null is used as the property value.

C#
public abstract class AWBase
{
    protected string SqlSelectString;
    protected Type BusObjectType;          
    protected List<AWBase> LoadData()
    {
       List<AWBase> _list = new List<AWBase>();
       DBHelper dbHelper = new DBHelper();
       //Get Data 
       DataTable dtBusinessObject = 
          dbHelper.RetrieveTable(SqlSelectString);
       //Custom Attributes
       object[] attributes = 
         BusObjectType.GetCustomAttributes(typeof(MapInfo), false);
       //Loop through all records in Table
       if (dtBusinessObject != null && dtBusinessObject.Rows.Count > 1)
       {
           for (int introw = 0; introw < 
                dtBusinessObject.Rows.Count; introw++)
           {
               AWBase busObject = 
                 (AWBase)Activator.CreateInstance(BusObjectType);
               //loop through all custom attributes
               for (int i = 0; i < attributes.Length; i++)
               {
                   MapInfo mapinfo = (MapInfo)attributes[i];
                   object DBValue = 
                     dtBusinessObject.Rows[introw][mapinfo.DBFieldName];
                   PropertyInfo pinfo = 
                     BusObjectType.GetProperty(mapinfo.ObjPropertyName);
                   pinfo.SetValue(busObject, DBValue.GetType() 
                     == typeof(DBNull) ? null: DBValue, null);
               }
               _list.Add(busObject);
           }
       }
       return _list;
    }       
}

Business Object: Product.cs

It is a sample class for business objects. This class will be populated from the "Production.Product" table. It has mapping information and public properties. The "GetProducts" method returns a generic list of products. Later, this method is used as SelectMethod in the ObjectDataSource control. For converting a base class to a child class, the generics ConvertAll function is used. Typically, all business objects contain mapping information, public properties, a select method, and an explicit casting method:

C#
//Mapping Information
[MapInfo("ProductID", "ID")]
[MapInfo("Name", "Name")]
[MapInfo("ProductNumber", "Code")]
public class Product : AWBase
{
    private int id;
    private string name;
    private string code;
    ... 
    //Properties    
    public int ID
    {
        get { return id; }
        set { id = value; }
    }    
    public string Name
    {
        get { return name; }
        set { name = value; }
    }    
    public string Code
    {
        get { return code; }
        set { code = value; }
    }    
    ....
    //explict casting
    public Product AWBaseToProduct(AWBase pAWBase)
    {
        return (Product)pAWBase;
    }
    //Get Products
    public List<Product> GetProducts()
    {
        base.SqlSelectString = 
          "select * from Production.Product";
        base.BusObjectType = this.GetType();        
        List<AWBase> list = base.LoadData();
        return list.ConvertAll<Product>(new 
          Converter<AWBase,Product>(AWBaseToProduct));
    }
}

The "GetContacts" method in the Contact business object would look like:

C#
public List<Contact> GetContacts()
{
    base.SqlSelectString = "select * from Person.Contact";
    base.BusObjectType = this.GetType();
    List<AWBase> list = base.LoadData();
    return list.ConvertAll<Contact>(new 
      Converter<AWBase,Contact>(AWBaseToContact));        
}

Bind a Generic list of business objects to a GridView (Project: AWDemo)

No written code is necessary here. Just dragging and configuring controls. I am giving here, the steps in order:

  • Create a new website.
  • Add a Reference to the previously created project.
  • Drag the "ObjectDataSource" control to the web page.
  • Select TypeName and SelectMethod from the data source configuration wizard.
  • Drag the "GridView" control to the webpage.
  • Set the DataSourceID.
  • Configure the paging properties and the GridView fields.

The code in the aspx page looks like this:

HTML
<asp:GridView id="GridView1" runat="server" 
        CellPadding="4" GridLines="None" ForeColor="#333333" 
        DataSourceID="ObjectDataSource1" 
        AutoGenerateColumns="False" AllowPaging="True" 
        PageSize="20" AllowSorting="True" 
        EmptyDataText="No Products Found">
    <FooterStyle BackColor="#1C5E55" 
        Font-Bold="True" ForeColor="White"  />
    <Columns>
        <asp:BoundField DataField="ID" 
          HeaderText="ID" ></asp:BoundField>
        <asp:BoundField DataField="Name" 
          HeaderText="Name" ></asp:BoundField>
        <asp:BoundField DataField="Code" 
          HeaderText="Code" ></asp:BoundField>
        <asp:CheckBoxField DataField="Finished" 
          HeaderText="Finished" ></asp:CheckBoxField>
        <asp:BoundField DataField="Size" 
          HeaderText="Size" NullDisplayText="N/A">
        </asp:BoundField>
        <asp:BoundField DataField="Cost" 
          HeaderText="Cost" NullDisplayText="N/A">
        </asp:BoundField>
        <asp:BoundField DataField="Color" 
          HeaderText="Color" NullDisplayText="N/A">
        </asp:BoundField>
        <asp:BoundField DataField="ModifiedDate" 
          HeaderText="ModifiedDate">
        </asp:BoundField>
    </Columns>
    <RowStyle BackColor="#E3EAEB"  />
    <EditRowStyle BackColor="#7C6F57"  />
    <SelectedRowStyle BackColor="#C5BBAF" 
       Font-Bold="True" ForeColor="#333333"  />
    <PagerStyle BackColor="#666666" 
       ForeColor="White" HorizontalAlign="Center"  />
    <HeaderStyle BackColor="#1C5E55" 
       Font-Bold="True" ForeColor="White"  />
    <AlternatingRowStyle BackColor="White"  />
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" 
    runat="server" SelectMethod="GetProducts" 
    TypeName="Product"></asp:ObjectDataSource>

I hope I kept it simple, and hopefully you will find it useful.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
MCSD.NET Early Achiever,MCDBA SQL 2000,MCITP SQL 2005 Charter Member,MCPD Charter Member

Comments and Discussions

 
QuestionHow to use get and post method which is used in java? Pin
ashishsthakare17-Aug-08 0:52
ashishsthakare17-Aug-08 0:52 
QuestionBusiness Objects Pin
EhsanTabari1-Jul-07 21:28
EhsanTabari1-Jul-07 21:28 
GeneralA base class cann't be typecast into a derived class Pin
Akbarbuneri30-Mar-07 3:31
Akbarbuneri30-Mar-07 3:31 
QuestiondtBusinessObject.Rows.Count > 1? Pin
Wilhelm Berg4-Dec-06 7:36
Wilhelm Berg4-Dec-06 7:36 
GeneralSuggestion Pin
Wilhelm Berg15-Nov-06 7:03
Wilhelm Berg15-Nov-06 7:03 
GeneralRe: Suggestion Pin
siva pinnaka15-Nov-06 9:37
siva pinnaka15-Nov-06 9:37 
That is very good change. good thinking.
I will update code

Thank you
Siva Pinnaka
GeneralRe: Suggestion Pin
Akash Kava10-May-07 8:16
Akash Kava10-May-07 8:16 
QuestionHow about custom paging Pin
iDownload27-Jun-06 21:00
iDownload27-Jun-06 21:00 
GeneralGood start but still need works... Pin
Noogen20-Jan-06 10:33
Noogen20-Jan-06 10:33 
GeneralRe: Good start but still need works... Pin
chris Liang16-Mar-06 18:18
chris Liang16-Mar-06 18:18 

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.