Thursday, August 28, 2008

XML And ADO.NET

A powerful feature of ADO.NET is its ability to convert the data stored in a data source in XML and vice versa. In this article we would read records from a data source and display them in a 'DataGrid' control. At the same time we would write the records in an XML file. The contents of the XML file would get displayed in a text box where we can modify it. The modified contents would get added to the data set and would get displayed in the 'DataGrid' control. We are going to use OLEDB for accessing the database.

Let us first understand few basic issues in the ADO.NET technology. The System.Data namespace is the root namespace of ADO.NET API. The primary namespaces of ADO.NET, System.Data.OleDb and System.Data.SqlClient contain classes that enable programs to connect with and modify the datasources. A datasource can be any file containing records such as a '.mdb' file. The namespace OleDb can be used to work with any datasource. On the other hand SqlClient namespace is used for working with MS SQL Server 2000 datasources.

ADO.NET has two major components-DataSet and .NET Data Providers. A .NET Data Provider is used for connecting to a database, executing commands, and retrieving results.

DataSet is used to cache the data read from the datasource in local memory. The data stored in the memory can be modified and written back to the datasource. The System.Data.DataSet class is provided to take care of the DataSets.

Let us move on and write a program using ADO.NET. Create a Windows application and design the form as shown in the following figure.


The dark gray colored control is the 'DataGrid' control. The controls, their Names and handlers are given in the following table.


Control

Name

Handler

DataGrid dg

-

Write Button wb

Click

Clear Button cb

Click

Read Button rb

Click

TextBox xmltext

-



First of all we would look at the Click event handler for the 'Write' button.

private void wb_Click ( object sender, System.EventArgs e )
{

String constr = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\book.mdb" ;
OleDbConnection con = new OleDbConnection ( constr ) ;
con.Open( ) ;

String comstr = "SELECT Name, Email, Phone FROM addressbook" ;
OleDbCommand com = new OleDbCommand ( comstr, con ) ;

OleDbDataAdapter adapt = new OleDbDataAdapter ( com ) ;
adapt.Fill ( dset, "addressbook" ) ;

dg.SetDataBinding ( dset, "addressbook" ) ;

dset.WriteXml ( "addressbook.xml" ) ;
xmltext.Text = dset.GetXml( ) ;

con.Close( ) ;

}

Interacting with a database using ADO.NET involves connection and command objects. Since we have used OLEDB to access the database, the connection must be established between the database and OLEDB .NET Provider. The class OleDbConnection is used for this job. So, in this method we have firstly created an object of this class passing to it the connection string. The connection string contains the name of the OLEDB .NET Provider and that of the datasource. Our datasource is 'book.mdb' that maintains an address book. This file is already created using Microsoft Access. It contains details like names, e-mail IDs and phone numbers. Only creating object of connection class does not physically open a connection to the database. Calling Open( ) method does. So we have called the Open( ) method in the next statement.

The Command object allows us to execute an SQL statement or a stored procedure in a data source. We have created the command object using the OleDbCommand class and passing to it the command string. The command string contains the SQL statement to select all the records from the datasource.

The command object is used to connect the connection object to a DataAdapter object. A DataAdapter is used to fill data from the database into the DataSet object. To read the records into the DataSet we have used the OleDbDataAdapter.Fill( ) method. To this method we have passed the DataSet object dset and the table name. Add the data member dset of type DataSet to the form class. Initialize the data set object in the constructor as

dset = new DataSet( ) ;

Next, we have called the DataGrid.SetDataBinding( ) method to bind the grid control with the datasource. We have passed the DataSet object as the first parameter to specify whose data the grid control should display. Second parameter is the name of table within the datasource we want to bind to the control. When this function call is executed, the data grid is filled with the records in the DataSet.

Next comes the main part of the program i.e writing records to an XML file. The DataSet.WriteXml( ) method generates the XML representation of the data contained in the DataSet object and writes it to the specified file. We have displayed the same XML data that we have just written to the file in the text box. For this, we have called the DataSet.GetXml( ) method.

The OleDbConnection.Close( ) method closes the connection with the datasource. A part of the XML file is given below.

Meghana
Meg2003@hotmail.com
2242567

….

On clicking the 'Clear' button the grid control should get cleared so that we can display modified contents in it. The code to clear the control is given in the cb_CLick( ) event handler. The handler is given below.

private void cb_Click ( object sender, System.EventArgs e )

{

dset.Clear( ) ;
dg.Update( ) ;

}

Since the grid control is attached to the datasource represented by dset, clearing dset and updating the grid control clears the contents from it.

Now add the following node to the XML data displayed in the text box.

Sanjay
sanju@hotmail.com
227257

Click the 'Read' button. Following handler would get called.

private void rb_Click ( object sender, System.EventArgs e )

{

StreamWriter sw = new StreamWriter ( "addressbook.xml", false ) ;
sw.Write ( xmltext.Text ) ;
sw.Close( ) ;
dset.ReadXml ( "addressbook.xml" ) ;
dg.SetDataBinding ( dset, "addressbook" ) ;

}

Here, we have used the StreamWriter class to write the contents from textbox to the XML file. To read new contents of the file and fill the DataSet with it we have used the ReadXml( ) method. Again to fill the grid control we have called the SetDataBinding( ) method. The result is shown in the following figure.


Note that we must add the following declarations at the beginning of the program.

using System.Data.OleDb ;
using System.IO ;

Tuesday, August 26, 2008

Bank Example in ADO.NET


In the following program we have created a WinForm. In this form we plan to show all the contents of a table. Here too we have used the OLE DB .NET Data Provider. We plan to add functionality to add, delete and modify the table.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb ;
namespace AdoProgram1
{

class bank
{

OleDbDataAdapter dest ;
DataSet ds ;
DataTable dt ;

public bank ( )
{

string str =" Data Source = c:\\bank.mdb; Provider = Microsoft.Jet.OLEDB.4.0";
string cmd = "SELECT accno, name, balance from account" ;


dest= new OleDbDataAdapter( cmd, str ) ;
OleDbCommandBuilder obd = new OleDbCommandBuilder( dest ) ;
ds = new DataSet ( ) ;
dest.Fill ( ds, "account" ) ;
dt = ds.Tables["account"] ;

}

public void addnewrec ( int id, String name, int bal )
{

DataRow r = getrowbyid ( id ) ;

if ( r == null )
{

DataRow nrow = dt.NewRow ( ) ;
nrow[0] = id ;
nrow[1] = name ;
nrow[2] = bal ;
dt.Rows.Add ( nrow ) ;
dest.Update ( ds, "account" ) ;

}
else
{

MessageBox.Show (" Record Already Exists") ;

}

}

public void deleterec ( int id )
{

string exp = " accno = " + id ;
DataRow[] r = dt.Select ( exp ) ;
r[0].Delete ( ) ;
dest.Update ( ds, "account" ) ;

}

public void updaterec ( int id, String name, int bal )
{

string exp = " accno = " + id ;
DataRow[] r = dt.Select ( exp ) ;
r[0][1] = name ;
r[0][2] = bal ;
dest.Update ( ds, "account" ) ;

}

public DataRow getrowbyid ( int id )
{

try
{

string exp = " accno =" + id ;
DataRow[] r = dt.Select ( exp ) ;
return r[0] ;

}

catch ( Exception e )
{

return null ;

}

}

public DataSet dset
{

get
{

return ds ;

}

}

}

public class Form1 : System.Windows.Forms.Form
{

private System.Windows.Forms.TextBox name;
private System.Windows.Forms.TextBox bal;
private System.Windows.Forms.TextBox acc;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button searchbut;
private bank b = new bank ( ) ;
private int m_oper ;
private System.Windows.Forms.Button commitbut;
private System.Windows.Forms.DataGrid dgrid;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button addbut;
private System.Windows.Forms.Button updatebut;
private System.Windows.Forms.Button delbut;
private System.ComponentModel.Container components = null;


public Form1( )
{

m_oper = 0 ;
InitializeComponent( ) ;
dgrid.SetDataBinding ( b.dset, "account" ) ;

}

protected override void Dispose( bool disposing )
{

if( disposing )
{

if ( components != null )
{

components.Dispose ( ) ;

}

}

base.Dispose( disposing ) ;

}

#region Windows Form Designer generated code
private void InitializeComponent ( )
{

//Wizard generated code found in Zip file

}

#endregion

[STAThread]
static void Main ( )
{

Application.Run ( new Form1 ( ) ) ;

}

private void searchbut_Click ( object sender, System.EventArgs e)

{

DataRow r = b.getrowbyid ( Int32.Parse ( acc.Text ) ) ;
if ( r != null )
{

name.Text = r[1].ToString() ;
bal.Text = r[2].ToString ( ) ;
name.Enabled = true ;
bal.Enabled = true ;

}

else

MessageBox.Show ( "Record not found" ) ;

}

private void addbut_Click ( object sender, System.EventArgs e )
{

acc.Enabled = true ;
name.Enabled = true ;
bal.Enabled = true ;
commitbut.Enabled = true ;
searchbut.Enabled = false ;
m_oper = 1 ;

}

private void updatebut_Click ( object sender, System.EventArgs e )
{

acc.Enabled = true ;
name.Enabled = false ;
bal.Enabled = false ;
commitbut.Enabled = true ;
searchbut.Enabled = true ;
m_oper = 2 ;

}

private void delbut_Click ( object sender, System.EventArgs e )
{

acc.Enabled = true ;
name.Enabled = false ;
bal.Enabled = false ;
commitbut.Enabled = true ;
searchbut.Enabled = true ;
m_oper = 3 ;

}

private void commitbut_Click ( object sender, System.EventArgs e )
{

int a = Int32.Parse ( acc.Text ) ;
string n = name.Text ;
int balance = Int32.Parse ( bal.Text ) ;
switch ( m_oper )
{

case 1:

b.addnewrec ( a, n, balance ) ;
break ;

case 2:

b.updaterec ( a, n, balance ) ;
break ;

case 3:

b.deleterec ( a ) ;
break ;

}

acc.Text = "" ;
name.Text = "" ;
bal.Text = "" ;
commitbut.Enabled = false ;
searchbut.Enabled = false ;
acc.Enabled = false ;
name.Enabled = false ;
bal.Enabled = false ;

}

}

}

In this program we have added a control called the Data Grid. We have used the Data Grid control to view the Data. This control is wrapped in a class called the DataGrid class derived from the Control class. We get the following output when we run this program.

To add a new DataRow, we must press the Add button, fill in the entries as shown and press Commit. The values will get added. To delete a row we must type in the accno and press Search. All the values would be shown in the corresponding textboxes. After pressing Commit, the row will get deleted. Same works for updating a row. We must type in the accno and press Search. After doing this we should press Commit for the changes to be made in the data.

If we press the small, depressed arrow on the side of accno field, the rows get sorted according to descending values of accno. On pressing it again they get sorted according to ascending values of accno.

We have wrapped all functionality of adding, deleting and updating the database in a class called bank.

In the constructor of the bank class, we initialized the connection and command string passed it to the constructor of the DataAdapter class. Next we filled the DataSet with account and extracted the table in object dt of the DataTable class.

We have written different functions for adding, deleting and updating rows. We plan to add rows in the table only if the accno is unique. This means every account holder should have just one row. So no two rows with same accno are added. To check this we have written a new function getrowbyid( ). In this method we have used the Select( ) method which gets an array of all DataRow objects that match the filter criteria. The filter criterion in our case is the accno. If such a row is found then it is returned. If such a row is not found an exception will be thrown. If an exception is thrown, we catch it and return just a null. In the addnewrec( ) method if a null is returned by the getrowbyid( ) method it means that no such row is already present. If its so we add a new row. The logic is same as the previous program. If not we just flash a message.

For deletion we have again used the Select( ) method. This method will return the collection of rows satisfying the selection criterion. We will definitely have just one row in the collection because in our table the accno is not repeated. (Such a field, which has unique value and no two rows have the same value, is called the primary key of the table). The Delete( ) method just deletes the specified row. After deleting it from the DataSet we call he Update( ) method to reconcile the changes.

Updating is done by initializing the corresponding field with new values and just calling the Update( ) method. A property dset is also written which gets the DataSet ds.

As shown in the form there are three buttons provided for the three operations viz:- addition of a row, deletion of a row and updating a row, one for searching the table and another for committing the operation. The whole logic behind the working of the form is that we have created a private data member of the bank class in the form class. We have also added an int m_oper, which will hold an int denoting which operation has to be performed. The default operation is 0 i.e. nothing. Events are added for all the buttons.

When the "Add" button is clicked all the texboxes are enabled. The "Commit" button is enabled and the "Search" button is disabled. This is so because we don't have to search the table to add a row. Finally and most importantly m_oper is set to value 1.
When the "Update" button is clicked the Acc no textbox is enabled. The Search button is enabled. This is because we have to search for the record and then update it. On pressing "Search" the search_click( ) event gets called. In this event we first get the row to be updated using the following statement:

DataRow r = b.getrowbyid ( Int32.Parse ( acc.Text ) ) ;

Int32.Parse( ) method converts the text in the acc textbox to an int. This int is passed to the getrowbyid( ) method which returns the specified selected row. After getting the row we set the textboxes with the values from the row and enable them.

name.Text = r[1].ToString ( ) ;
bal.Text = r[2].ToString ( ) ;

We can then change the text in the textboxes to the new values. This is all done in the search_click( ) event. After the control returns back to updatebut_Click( ) event m_oper is set to 2.

When the "Delete" button is clicked a similar thing happens and m_oper is set to 3. We do not change the text in the textboxes and hence the values, because we plan to delete the row and not update it.

After all this is done we press the "Commit" button. This calls the corresponding event. In this event we kept a switch on m_oper and called the corresponding methods of the bank class.

Using DataSet & DataTable

A DataSet is used for the disconnected approach. We connect to the database, fill in the DataSet with the data and go offline. The DataSet is designed as an offline container of data. Actually filling of data in a DataSet need not be necessarily through a database, it could be through any file also or straight away from a device. To fill in a DataSet we need a DataAdapter. A DataAdapter is used to retrieve data from a data source and populate tables within a DataSet. Take a look at the following program. We have used the OLE DB .NET Data Provider. We have used Microsoft Access to create the account table.

class myclass
{

static void Main( string[] args)
{

string str="Provider=Microsoft.Jet.OLEDB.4.0 ;Data
Source=c:\\bank.mdb";
string cmd = "SELECT accno, name, balance from account" ;
OleDbDataAdapter dest= new OleDbDataAdapter( cmd, str ) ;
OleDbCommandBuilder mybuilder= new
OleDbCommandBuilder (dest) ;
DataSet ds = new DataSet ( ) ;
dest.Fill ( ds, "account" ) ;
DataTable dt = ds.Tables["account"] ;
DataRow nrow = ds.Tables["account"].NewRow ( ) ;
nrow[0] = 6;
nrow[1] = "Rashi";
nrow[2] =76000 ;
ds.Tables["account"].Rows.Add ( nrow ) ;
dest.Update ( ds, "account" ) ;

}

}

After initializing the command and connection strings, we created the DataAdapter object. This object is passed to the constructor of the OleDbCommandBuilder class. This is because the DataAdapter class does not automatically generate the SQL statements to make changes in the database. The OleDbCommandBuilder class does so. Now we need to populate a DataSet with the DataAdapter. The Fill( ) method does the filling of DataSet. The statement

ds.Tables["account"]

returns the table "account" from the DataSet. Tables is a property belonging to the DataSet class. It gets the collection of Tables contained in the DataSet. "account" is an indexer on the collection of tables. We collected this "account" table in a new DataTable object: - dt. We then created a new row in the account table. Next we initialized it with values. Now we need to add it to the table. This is achieved through the following

ds.Tables["account"].Rows.Add ( nrow ) ;

Rows is a property belonging to the DataTable class. It gets the collection of rows contained in the table i.e. it returns a DataRowCollection object. This class has a method Add( ) in it. The method Add( ) adds a DataRow to the DataRowCollection. Now to reconcile the changes in the database we use the Update( ) method. This method calls the respective INSERT, UPDATE, or DELETE statements for each inserted, updated, or deleted row in the specified DataSet from a DataTable.

SqlCommand Class

ExecuteReader( ), ExecuteNonQuery( ) and ExecuteScalar( ) are three important methods in the Command class.

ExecuteReader( ):-This method will execute the command and return an SqlDataReader object.

ExecuteNonQuery( ):- Executes the command and returns the number of records affected.

ExecuteScalar( ): - Executes the query and returns a single result such as count on records in a given table or max value of some field etc.


ExecuteReader( )

Below program Shows how to use ExecuteReader( ) Method:

using System;
using System.Data;
using System.Data.SqlClient;
class myclass
{

static void Main( string[ ] args)
{

string str= "Database = bank ; server = kicit ; Trusted_Connection =true";
string cmd = "SELECT accno, name, balance from account" ;
SqlConnection con = new SqlConnection ( str ) ;
SqlCommand com = new SqlCommand ( cmd, con ) ;
con.Open();

SqlDataReader r = com.ExecuteReader ( ) ;

while ( r.Read ( ) )

Console.WriteLine ( r[0] + " " + r[1] + " " + r[2] ) ;

con.Close ( ) ;

}

}

The output is :

1 Rahul 200000
2 Subash 300000
3 Anita 100000
4 Preeti 120000
5 Kapil 8000

First we need to get connected to the database. To do so, we have to write a connection string. The connection string includes database name, server, database provider, user name, password and whether it�s a trusted connection or not. In our program the database name is bank and server name is kicit. We have initialized Trusted Connection to true. This means even if we don�t specify the username and password its fine. If the value is set to false we have to specify a username and password. This connection string is stored in str.

The command string is stored in cmd. cmd contains the query to be executed. The query we have used here is �SELECT accno, name, balance from account�. This is an Sql query, which selects the specified fields:- accno, name and balance from the �account� table.

To make a connection, we pass the connection string to the SqlConnection constructor. To the SqlCommand constructor we pass the connection as well as the command string. The Open( ) method opens a database connection with the property settings specified by the connection string. The SqlDataReader class reads a stream of rows from an SQL Server database. To create an SqlDataReader class we have to call the ExecuteReader( ) method belonging to the SqlCommand class. This method will execute the command and return an SqlDataReader object. The Read( ) method iterates through the records advancing the SqlDataReader by one record every time.


ExecuteNonQuery( )

Now lets have a look at a program using the ExecteNonQuery( ) method.

using System;
using System.Data;
using System.Data.SqlClient ;
class myclass
{

static void Main( string[] args)
{

string str = " Database = bank ; server = kicit ;
Trusted_Connection =true";
string cmd = "Insert into account values ( 6, 'Aakash', 25000 ) ";
SqlConnection con = new SqlConnection ( str ) ;
SqlCommand com = new SqlCommand ( cmd, con ) ;
con.Open ( ) ;
com.ExecuteNonQuery ( ) ;
con.Close ( ) ;

}

}

The "Insert into account values (6, 'Aakash', 25000)" query inserts a new row in the table. After opening the connection, the query is executed and the connection is closed.


ExecuteScalar( )

Now lets look at a program a program using the ExecuteScalar( ) method:

using System;
using System.Data;
using System.Data.SqlClient;
class myclass
{

static void Main( string[] args)
{

string str = " Database = bank ; server = kicit ;
Trusted_Connection=true";
string cmd = "SELECT count(*) from account" ;
SqlConnection con = new SqlConnection ( str ) ;
con.Open ( ) ;
SqlCommand com = new SqlCommand ( cmd, con ) ;
Object o = com.ExecuteScalar( ) ;
Console.WriteLine ( o ) ;
con.Close ( ) ;

}

}

The output here is: - 6. The "SELECT count(*) from account" query counts the no of rows in our database.

Data Providers

MSDE is the Microsoft Database Engine, and is a version of SQL Server; this is shipped along with VS.NET and does not need explicit installation.

SQL Data Providers

To write programs for accessing, manipulating, or updating database, we have to first create a database. To create a database, open the server explorer window. If its not visible press Ctrl+Alt+S.

In the �Servers� tree expand the �SQL servers� node. You will find your computer name added there. Right click on it and select �New Database�. Name the new database as �bank� as shown in the following dialog box:

We have checked the �Use Windows NT Integrated Security� radio button. This program will hence work only when we log on with our username and password. Press OK and a new database called bank will appear in the tree. Now we need to create a table in our database called account. To create a new table, expand the bank node and right click on �Tables�, select �New Table� from the menu. A new blank table would appear. Now we need to fill in the entries and specify the attributes of the table. This is how we want our table to be:

We want three attributes in the table viz:- accno (int), name (varchar) and balance(float). Save the table and name it as: - account. Close this window. Expand the table�s tree and you will find that account has been added. Double click on this and start filling in the entries as shown:

Now lets write a program to access these values and print them out Here the code for the program:

using System;
using System.Data;
using System.Data.SqlClient;
class myclass
{

static void Main( string[ ] args)
{

string str= "Database = bank ; server = kicit ; Trusted_Connection =true";
string cmd = "SELECT accno, name, balance from account" ;
SqlConnection con = new SqlConnection ( str ) ;
SqlCommand com = new SqlCommand ( cmd, con ) ;
con.Open();

SqlDataReader r = com.ExecuteReader ( ) ;

while ( r.Read ( ) )

Console.WriteLine ( r[0] + " " + r[1] + " " + r[2] ) ;

con.Close ( ) ;

}

}

The output is :

1 Rahul 200000
2 Subash 300000
3 Anita 100000
4 Preeti 120000
5 Kapil 8000

Explanation: -

First we need to get connected to the database. To do so, we have to write a connection string. The connection string includes database name, server, database provider, user name, password and whether it�s a trusted connection or not. In our program the database name is bank and server name is kicit. We have initialized Trusted Connection to true. This means even if we don�t specify the username and password its fine. If the value is set to false we have to specify a username and password. This connection string is stored in str.

The command string is stored in cmd. cmd contains the query to be executed. The query we have used here is �SELECT accno, name, balance from account�. This is an Sql query, which selects the specified fields:- accno, name and balance from the �account� table.

To make a connection, we pass the connection string to the SqlConnection constructor. To the SqlCommand constructor we pass the connection as well as the command string. The Open( ) method opens a database connection with the property settings specified by the connection string. The SqlDataReader class reads a stream of rows from an SQL Server database. To create an SqlDataReader class we have to call the ExecuteReader( ) method belonging to the SqlCommand class. This method will execute the command and return an SqlDataReader object. The Read( ) method iterates through the records advancing the SqlDataReader by one record every time. Here we have used the ordinal indexer to access individual values of a row referenced by the SqlDataReader. We could have also used the GetString( ) method which gets the value of the specified column as a string i.e. we could have written:

r.GetString(0)

to get the accno field of the row referenced by the SqlDataReader. There is another way of doing it: -r[�name�]. In the end the connection is closed using the Close( ) method.


OLEDB Data Providers

For OLE DB .NET Data Provider we will have to create our tables in Microsoft Access. These tables should have the same values and fields. After creating such a table in Microsoft Access, save it as bank.mdb in the C directory. The program will look like this:

using System;
using System.Data;
using System.Data.OleDb;
class myclass
{

static void Main( string[ ] args)
{

string str="Provider =Microsoft.Jet.OLEDB.4.0 ; Data Source = c:\\bank.mdb";string cmd = "SELECT accno, name, balance from account" ;
OleDbConnection con = new OleDbConnection ( str ) ;
OleDbCommand com = new OleDbCommand ( cmd, con ) ;
con.Open();

OleDbDataReader r = com.ExecuteReader ( ) ;

while ( r.Read ( ) )

Console.WriteLine ( r[0] + " " + r[1] + " " + r[2] ) ;

con.Close ( ) ;


}

}

The output here remains the same. We have only changed the connection string and the names of classes, just replacing �Sql� everywhere with �OleDb�.

There are three types of OleDb .NET Data Providers viz: - SQLOLEDB, MSDAORA and Microsoft.Jet.OLEDB.4.0. We have used the last one. This is specified in the connection string used.

Introduction to ADO.NET

ADO.NET deals with accessing Databases. It�s a new technology that runs within the .NET environment. It uses the concept of managed code. ADO.NET provides access to data sources such as Microsoft SQL Server, OLE DB and XML. Applications connect to these data sources to access, manipulate or update data.

The traditional difficulties regarding database is that it relies on connection-based two-tier model. Instead programmers today wish to make n-tier applications using a disconnected approach.

A two-tier model means there is a server and a client in the application. The server accesses the client. An n-tier applications means there will be more than a server or a client viz: - one or more databases (data-tier), business tier, and presentation-tier.
In early days the client had to be connected with the server and remain connected till the whole procedure or transaction was completed. This was called the connected approach. In such an approach lots of bandwidth was required because if 100 clients were to use a server, each would need a connection. Time, resources and bandwidth became major constraints on such architectures.

In ADO 2.0 disconnected data approach was used. In this approach ADO used Record Sets. All the contents of the server were copied in the Record Set. This allowed the client to get disconnected from the server, work on the Record Set and copy the changes back to the data store again. This approach did not catch on due to security problems. This approach used COM marshalling to transmit a disconnected data set, it supported only those data types defined by the COM standards and hence required type conversions.

ADO.NET is designed from ground up to help solve these problems. Here transmission of data is in XML format. XML format places no restriction on the data types and requires no type conversion.


ADO.NET Architecture


The ADO.NET architecture consists of two main components:- the DataSet and the NET Data Providers.


DataSet

ADO.NET uses the disconnected approach using the DataSet. The DataSet is explicitly designed for data access independent of any data source. It can be used for data sources, XML data, or used to manage data local to the application. The DataSet acts as a container. All the data coming from the database is dumped in the DataSet for the local machine to use and manipulate. The database is then later updated back with the DataSet. The DataSet contains a collection of one or more DataTable objects made up of rows and columns of data, as well as primary key, foreign key, constraint and relation information about the data in the DataTable objects.

A DataSet can be thought of as a container of data. The DataSet consists of DataTables. DataTables are similar to tables or relations in DBMS (Data Base Management Systems). A table consists of zero or more columns. A table is also generically called as a schema. DataTables contain DataRows and DataColumns. Rows indicate one full entry or a tuple and columns indicate one property or attribute of the table.

The following figure will serve as an example


.NET Data Providers

There are two .NET data providers available: - The SQL Server .NET Data Provider and the OLE DB .NET Data Provider. Depending on the design and data source for our application we can use any one of these two. The SQL Server .NET Data Provider uses its own protocol to communicate with the SQL Server. The OLE DB .NET Data Provider uses native OLE DB through COM interoperability to enable data access. To use the SQL Server .NET Data Provider, you must have access to Microsoft SQL Server 7.0 or later. SQL Server .NET Data Provider classes are located in the System.Data.SqlClient namespace. To use the OLE DB .NET Data Provider, you must use an OLE DB provider (we have used Microsoft Access). OLE DB .NET Data Provider classes are located in the System.Data.OleDb namespace. To use the OLE DB .NET Data Provider, you will have to include the System.Data.OleDb namespace in your applications.

These .NET providers include the Connection object, the Command Object, the DataReader and the DataAdapter in their corresponding namespaces. For e.g. the Connection class in the Sql Server .NET Provider is written as SqlConnection and its equivalent in the OLE DB Service Provider is written as OleDbConnection. In the same way for all the four classes the corresponding names are prefaced with Sql or OleDb accordingly.

The Connection object provides connectivity to a data source. The Command object enables access to database commands to return data, modify data, run stored procedures, and send or retrieve parameter information. A command in its simplest form is nothing but an SQL query. The DataReader provides a stream of read-only and forward-only data from the data source. A read-only data means that it cannot be changed using the DataReader and forward-only means we cannot traverse backwards. Finally, the DataAdapter provides the bridge between the DataSet object and the data source.

You should see the next article to get this clear. We have written two programs using both the .NET Data Providers. Both programs do the same thing.

Search

My Blog List