![]() |
Web Development »
ASP.NET Controls »
General
Intermediate
Populating custom business objects by binding business objects to a GridView using the ObjectDataSource in ASP.NET 2.0By siva pinnakaA complete article on how to populate custom business objects using a common method, binding these objects to a GridView using the ObjectDataSource control. |
Windows, .NET2.0, ASP.NET, ADO.NET, WebForms, VS2005, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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:
DataTable from a DataReader.
ConnectionString section from web.config.
ObjectDataSource control. 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.
This project contains a database helper class, a custom attribute class, a business objects base class and two sample business objects.
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.
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;
}
}
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.
[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;}
}
}
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.
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;
}
}
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:
//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:
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));
}
No written code is necessary here. Just dragging and configuring controls. I am giving here, the steps in order:
ObjectDataSource" control to the web page.
TypeName and SelectMethod from the data source configuration wizard.
GridView" control to the webpage.
DataSourceID.
GridView fields. The code in the aspx page looks like this:
<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.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 20 Jan 2006 Editor: Smitha Vijayan |
Copyright 2006 by siva pinnaka Everything else Copyright © CodeProject, 1999-2010 Web21 | Advertise on the Code Project |