Section 10.7. Binding to Business Objects

10.7. Binding to Business Objects

Most of the applications that we've looked at in this book have been two-tier, separating the User Interface from the back-end data. Many larger commercial applications, however, are n- tier , with at least a middle business-logic layer to separate retrieval of data from the database from manipulation (and validation) of that data before presentation.

An example of a middle-tier business object would be to create a stateless class to encapsulate business logic, and a "model" class that knows how to load and store data from the database.

This follows the Model View Controller (MVC) design pattern popular with many object-oriented programmers (see, for example, the article "Model-View-Controller" on MSDN.com: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/desmvc.asp).


To illustrate implementing the n-tier MVC pattern, we'll create a stateless business class CustomerBusinessLogic and a "model" of the Customer class named NorthWind customer. We'll bind an ObjectDataSource to the stateless business-logic class which will use the Model class to get and retrieve data about customers in the NorthWind database.

To begin, create a new web application called NTierDataSource. Add a GridView and use the smart tag and the properties to set the columns from the Customer table you'd like to display, as shown in Example 10-16.

Example 10-16. GridView declaration in default.aspx from NTierDataSource
 <asp:GridView ID="GridView1" runat="server"  DataSourceID="ObjectDataSource1"  AllowPaging="True"    AutoGenerateColumns="False"    CellPadding="4" ForeColor="#333333" GridLines="None" >     <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />     <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />     <Columns>         <asp:BoundField DataField="CompanyName" HeaderText="Company" />         <asp:BoundField DataField="ContactName" HeaderText="Contact" />         <asp:BoundField DataField="ContactTitle" HeaderText="Title" />         <asp:BoundField DataField="Address" HeaderText="Address" />         <asp:BoundField DataField="City" HeaderText="City" />         <asp:BoundField DataField="Region" HeaderText="Region" />         <asp:BoundField DataField="PostalCode" HeaderText="Postal Code" />         <asp:BoundField DataField="Phone" HeaderText="Phone" />         <asp:BoundField DataField="Fax" HeaderText="Fax" />     </Columns>     <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />     <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />     <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />     <EditRowStyle BackColor="#999999" />     <AlternatingRowStyle BackColor="White" ForeColor="#284775" /> </asp:GridView> 

The only thing surprising in this declaration is that we've set the DataSourceID to ObjectDataSource1 . Declare that object below the DataGrid :

 <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"  SelectMethod="GetAllCustomers"        TypeName="CustomerBusinessLogic" />  

Two key attributes of this ObjectDataSource are new in ASP 2.0: the SelectMethod attribute tells the ObjectDataSource which method to call on its business object to respond to the DataGrid 's select request (to populate the grid), and the TypeName attribute tells the ObjectDataSource which class will have that method.

The SelectMethod is invoked on the TypeName class using reflection at runtime.


From this declaration, you can see your stateless business-logic class will be named CustomerBusinessLogic , and it will have a (static) method named GetAllCustomers .

To create this class, right-click on the project in the Solution Explorer and add a new Class named CustomerBusinessLogic.cs . VS2005 will offer to put the file in the App_Code directory, which is what you want.

The Business Logic class, which is listed in Example 10-17, is declared to be static because all its members will be static. The member methods represent the capabilities of the business logic class:



GetAllCustomers

Responds to the select method.



UpdateCustomerInformation

Responds to the Update method (stubbed out for this example).



GetCustomer

Gets an individual customer instance given a CustomerID .

Example 10-17. CustomerBusinessLogic
 using System; using System.Data; using System.Data.SqlClient; using System.Collections; using System.Collections.Specialized; using System.Configuration; using System.Text; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; /// <summary> /// Stateless business logic that encapsulates what /// can be done with a Customer object /// All methods are static /// </summary> public static class CustomerBusinessLogic {  public static ICollection GetAllCustomers(  )  {         ArrayList allCustomers = new ArrayList(  );         string connectionString =         "Data Source=Brahams;Initial Catalog=Northwind;Integrated Security=True";         string selectCommand = "Select CustomerID from Customers";         SqlDataSource dataSource =              new SqlDataSource(connectionString, selectCommand);         try         {             // select with no arguments             IEnumerable CustomerIDs =                dataSource.Select(DataSourceSelectArguments.Empty);             IEnumerator enumerator = CustomerIDs.GetEnumerator(  );             while (enumerator.MoveNext(  ))             {                 DataRowView drv = enumerator.Current as DataRowView;                 if (drv != null)                 {                     string customerID = drv["CustomerID"].ToString(  );                     NorthWindCustomer cust = new NorthWindCustomer(customerID);                     allCustomers.Add(cust);                 }   // end if not null             }       // end while enumerating         }           // end try block         finally         {             dataSource.Dispose(  );         }         return allCustomers;     }     public static void UpdateCustomerInformation(NorthWindCustomer customer)     {         bool returnValue = customer.Save(  );         if (returnValue == false)         {             throw new ApplicationException("Unable to update customer");         }     }     public static NorthWindCustomer GetCustomer(string custID)     {         return new NorthWindCustomer(custID);     } } 

The only interesting method is GetAllCustomers , whose job is to return an ICollection to which the grid may bind. You do this by creating an instance of SqlDataSource initialized with the connection string and a select statement that gets all the CustomerIDs from the Customers table. What you get back from calling dataSource.Select (passing in no arguments) is a collection of DataRowViews .

You enumerate the collection, extracting each DataRowView , and from that you extract the CustomerID . Using that CustomerID , you instantiate a NorthWindCustomer object (defined below in Example 10-18) which you add to your ArrayList . Once you have created an instance of the NorthWindCustomer for every ID in the database, that collection is used as the data source for the GridView .

This process allows you to manipulate the data object (the NorthWindCustomer ) to add business logic to any or all of its properties. In this example, the NorthWindCustomer object does nothing more than store the data for a customer from the Customers table, but you can imagine it performing operations on that data or extending the definition of a customer beyond a single table (or even beyond the data in a single database). Example 10-18 shows the definition of the NorthWindCustomer implemented in CustomerBusinessLogic.cs .

Example 10-18. NorthWindCustomer
 public class NorthWindCustomer {     private object customerID;     private string companyName;      public string CompanyName     {         get { return companyName; }         set { companyName = value; }     }     private string contactName;     public string ContactName     {         get { return contactName; }         set { contactName = value; }     }     private string contactTitle;     public string ContactTitle     {         get { return contactTitle; }         set { contactTitle = value; }     }     private string address;     public string Address     {         get { return address; }         set { address = value; }     }     private string city;     public string City     {         get { return city; }         set { city = value; }     }     private string region;     public string Region     {         get { return region; }         set { region = value; }     }     private string postalCode;     public string PostalCode     {         get { return postalCode; }         set { postalCode = value; }     }     private string country;     public string Country     {         get { return country; }         set { country = value; }     }     private string phone;     public string Phone     {         get { return phone; }         set { phone = value; }     }     private string fax;     public string Fax     {         get { return fax; }         set { fax = value; }     }     public bool Save(  )     {         return true;     }     // default constructor     public NorthWindCustomer(  )     {         this.customerID = DBNull.Value;         this.companyName = string.Empty;         this.contactName = string.Empty;         this.contactTitle = string.Empty;         this.address = string.Empty;         this.city = string.Empty;         this.region = string.Empty;         this.postalCode = string.Empty;         this.country = string.Empty;         this.phone = string.Empty;         this.fax = string.Empty;     }     // Business object representing a Customer from the Northwind database  public NorthWindCustomer(string customerID)     {         string connectionString =        "Data Source=Brahams;Initial Catalog=Northwind;Integrated Security=True";         StringBuilder sb =             new StringBuilder("Select CompanyName, ContactName, ContactTitle,");         sb.Append(" Address, City, Region, PostalCode, Country, Phone, ");         sb.Append(" Fax from Customers ");         sb.Append(" where CustomerID = @customerID");         // Create connection object, initialize with         // connection string.         System.Data.SqlClient.SqlConnection connection =            new System.Data.SqlClient.SqlConnection(connectionString);         // declare the command object for the sql statements         System.Data.SqlClient.SqlCommand command =            new System.Data.SqlClient.SqlCommand(sb.ToString(  ), connection);         SqlParameter param =           command.Parameters.AddWithValue("@customerID", customerID);         param.DbType = DbType.String;         param.Direction = ParameterDirection.Input;         SqlDataReader dataReader = null;         try         {             connection.Open(  );             dataReader = command.ExecuteReader(  );             if (dataReader != null && dataReader.Read(  ))             {                 this.companyName = dataReader["companyName"].ToString(  );                 this.contactName = dataReader["contactName"].ToString(  );                 this.contactTitle = dataReader["contactTitle"].ToString(  );                 this.address = dataReader["address"].ToString(  );                 this.city = dataReader["city"].ToString(  );                 this.region = dataReader["region"].ToString(  );                 this.postalCode = dataReader["postalCode"].ToString(  );                 this.country = dataReader["country"].ToString(  );                 this.phone = dataReader["phone"].ToString(  );                 this.fax = dataReader["fax"].ToString(  );             }  else             {                 throw new ApplicationException(                   "Data not found for customer ID" + customerID);             }         }         finally         {             try             {                 if (dataReader != null)                 {                     dataReader.Close(  );                 }                 connection.Close(  );             }             catch (SqlException)             {                 // handle the exception here                 throw;             }         }     }           // end constructor }               // end class 

This code extracts information about a given customer (based on the CustomerID ) from the database and creates instance data from that database-bound data. It starts by creating a parameterized select statement (the at-sign [ @ ] in front of CustomerID indicates it is a parameter that is passed in) that extracts the fields needed to create the business object:

 StringBuilder sb =         new StringBuilder("Select CompanyName, ContactName, ContactTitle,");     sb.Append(" Address, City, Region, PostalCode, Country, Phone, ");     sb.Append(" Fax from Customers ");     sb.Append(" where CustomerID = @customerID"); 

The code creates a connection and command object in the normal way and then adds the parameter with customerID as the value:

 SqlParameter param = command.Parameters.AddWithValue("@customerID", customerID);     param.DbType = DbType.String;     param.Direction = ParameterDirection.Input; 

Within the try block, the connection is opened, and a DataReader is fetched based on the parameterized selection statement:

 connection.Open(  );     dataReader = command.ExecuteReader(  ); 

Assuming you get back data (and it is an exception if you don't), you will populate the fields of the business object from the columns within dataReader :

 if (dataReader != null && dataReader.Read(  ))     {         this.companyName = dataReader["companyName"].ToString(  );         this.contactName = dataReader["contactName"].ToString(  );         this.contactTitle = dataReader["contactTitle"].ToString(  );         this.address = dataReader["address"].ToString(  );         this.city = dataReader["city"].ToString(  );         this.region = dataReader["region"].ToString(  );         this.postalCode = dataReader["postalCode"].ToString(  );         this.country = dataReader["country"].ToString(  );         this.phone = dataReader["phone"].ToString(  );         this.fax = dataReader["fax"].ToString(  );     } 

After you close the DataReader and the connection, your object is fully instantiated and can be used to bind data in the GridView .

In the example shown, the data in the database is isomorphic with the fields in the business object, but in a real-world application, the customer business object might be larger, smaller, or more complex than the data stored in a single table in the database.

When the application is run, the GridView is bound to the ObjectDataSource as previous GridViews have been bound to SqlDataSources , and the data is displayed appropriately based on the bound columns you chose earlier, as shown in Figure 10-18.

Figure 10-18. Binding to a business object



Programming ASP. NET
Programming ASP.NET 3.5
ISBN: 0596529562
EAN: 2147483647
Year: 2003
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net