You are on page 1of 5

VB.NET and C# to Microsoft Access using ADO.

by Steven Nicolaou
Microsoft Certified Solution Developer
Microsoft Certified Professional SQL Server, Visual Basic Desktop & Distributed

Introduction to ADO.NET
For those of you familiar with ActiveX Data Objects (ADO) in Visual Basic, you will be well aware of the concept of
the Connection, the Command and the Recordset. These are the primary classes that constitute ADO’s data
access technology. In the .NET framework, ADO has been through major reengineering and has been renamed
to ADO.NET to reflect its position as the underlying data framework for .NET. Here is a quick overview.

The new Object Model in ADO.NET

The Connection and Command are still there, but the Recordset has been replaced by the DataSet and we have
a new Object called a DataAdapter , which is a toolset that handles processing between a Command and a
Connection . There is also a new Object called a DataReader, which is essentially what would have been a Read-
Only Forward -Only Cursor Records et in ADO and is the most efficient way to get data.

You will notice that the DataSet has a DataTable collection, which reveals its ability to hold resultsets from more
than one table, a big improvement over ADO Recordsets. Moreover, the tables can be related through
Relationship objects, which allow the programmer to perform joins without going back to the database. In addition
to table relationships, ADO.NET is aware of Primary Key, Foreign Key and Unique constraints, as well as
Autonumber (IDENTITY/SEQUENCE) fields.

A very popular way of working with data in VB and ADO was to keep the connection open, while making changes
directly to the database. ADO.NET encourages greater use of the disconnected model. The programmer should
keep a connection to the database open for as little as possible. This improves scalability and makes more sense
in a web-enabled system. The process of retrieving and updating data should be as follows:

1. Open Connection
2. Get DataSet
3. Close Connection
4. Perform Operations on the DataSet

When you are ready to commit the changes back to the database:

5. Open Connection
6. Submit Changes from DataSet
7. Close Connection

And so on.

In the diagram above, Connected Objects are the ones that are normally used while the Connection to the
database is open and Disconnected Objects are the ones that can be used once the connection is closed.
ADO.NET with VB.NET and C# Steven Nicolaou

Note for ASP.NET

ASP.NET no longer relies on VBScript, but is instead powered by the .NET framework, which means that it can
be built using VB.NET or C# for example. The source code in this guide will therefore work equally well, whether
you are making a Windows Application, or a Web Application in ASP.NET

After our brief overview with ADO.NET let’s have a look at how our source code would look. I have provided
examples in both VB.NET and C#. I will be assuming Access as the back-end and will be going through
OLE DB. ADO.NET has a specialised set of classes that are optimised for SQL Server (such as
SqlConnection), but for Access we need to use the regular OLE DB classes.

‘Create the OleDbConnection Object
‘DBPath is a fully qualified path to the MDB File
Private m_Conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &

‘To open the Connection we simply call the Open method

private OleDbConnection m_Conn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=" & DBPath)

Now the Connection is open, we have several options, each of which I will demonstrate. Most of these
objectives can work using a DataSet, but the new methods have been provided to make specialised
operations more efficient. For example, the system shouldn’t be made to go through the trouble of building a
complete DataSet in memory, if all we need is a single value.

Objective Action
Get a DataSet that can be used offline Use a DataAdapter and call Fill
Get a DataReader (can only be used online) Use a Command and call ExecuteReader
Perform a non-DataSet operation on the Database, Use a Command and call
such as UPDATE, INSERT, or DELE TE ExecuteNonQuery
Get a Single value from a query, such as “SELECT Use a Command and call ExecuteScalar

Get a DataSet that can be used offline

‘The DataAdapter Constructor takes 2 parameters in this case: The SQL Text and the Connection
Dim m_ds as DataSet
Dim m_da = New OleDbDataAdapter(sqltext, m_Conn)
m_da.Fill(m_ds) ‘The DataAdapter Fills the DataSet
m_Conn.Close() ‘Close database Connection
DataSet m_ds;
OleDbDataAdapter m_da = new OleDbDataAdapter(sqltext,m_Conn);

The Connection is closed and the DataSet is now filled with data and ready for processing. To better
understand the code below, keep in mind the object hierarchy. A DataSet contains many Tables, which
contain many Rows, which contain Fields.

L Tables as DataTable
L Rows as DataRow

The entire DataSet object model has been attached in Appendix A for your convenience.

Page 2
ADO.NET with VB.NET and C# Steven Nicolaou

Dim emp As DataRow ‘Single Row in the DataSet
For Each emp In m_ds.Tables(0).Rows
EmployeeId = emp("EmployeeId")
FirstName = emp(“FirstName”)
LastName = emp(“LastName”)
Console.WriteLine(CustomerId,FirstName,LastName) ‘Print out the fields
Next row
foreach(DataRow emp in m_ds.Tables[0].Rows)
EmployeeId = emp["EmployeeId"];
FirstName = emp[“FirstName”];
LastName = emp[“LastName”];
Console.WriteLine(CustomerId,FirstName,LastName); //Print out the fields

Get a DataReader (can only be used online)

The one gotcha of DataReaders is that they need the connection to be open to work. DataReaders are ideal
for forward -only, read-only operations that don’t require scrolling, such as populating drop down boxes. It is
therefore assumed that we will need it for a short time, and not for repeated reference.

The CommandBehavior.CloseConnection parameter that is sent to the ExecuteReader constructor

forces the Connection to Close as soon as the DataReader is closed.

Dim m_cmd As As New OleDbCommand(sqlText, m_Conn)
Dim dr As OleDbDataReader
dr = m_cmd.ExecuteReader(CommandBehavior.CloseConnection)
private OleDbCommand m_cmd = new OleDbCommand(sqlText, m_Conn);
private OleDbDataReader dr = m_cmd.ExecuteReader(CommandBehavior.CloseConnection);

To read the records from a DataReader, we need to call the Read method and simply retrieve the fields by
name. We keep calling until Read returns False, at which point we have read all records.

While dr.Read()
EmployeeId = dr("EmployeeId")
FirstName = dr("FirstName")
LastName = dr("LastName")
Console.WriteLine(CustomerId,FirstName,LastName) ‘Print out the fields
End While
dr.Close() ‘Close the DataReader and release the Connection
while (dr.Read())
EmployeeId = dr["EmployeeId"];
FirstName = dr["FirstName"];
LastName = dr["LastName"];
Console.WriteLine(CustomerId,FirstName,LastName); //Print out the fields
dr.Close(); //Close the DataReader and release the Connection

Page 3
ADO.NET with VB.NET and C# Steven Nicolaou

Perform operations that do not return a DataSet, such as UPDATE,

After creating a command object, we need to call the ExecuteNonQuery method. We can optionally get the
number of rows affected by the operation by examining its return value, as in the example.

‘Now we need to make a Command that we’ll use to send the query
‘The OleDBCommand Constructor takes 2 parameters in this case: The SQL Text, and the Connection
Dim RowsAffected as Integer
Dim cmd As New OleDbCommand(sqlText, m_Conn)
RowsAffected = cmd.ExecuteNonQuery()
m_Conn.Close() ‘Don’t forget to close the Connection immediately afterwards
private String sqlText = “DELETE * FROM EMPLOYEES WHERE EMPLOYEE_ID = 5”;
private OleDbCommand cmd = new OleDbCommand(sqlText, m_Conn);
int RowsAffected = cmd.ExecuteNonQuery();
m_Conn.Close(); //Don’t forget to close the Connection immediately afterwards

Get a Single value from a query, such as SELECT COUNT (*)

There is a special method called ExecuteScalar specifically optimised for queries that return single
values. Although a DataSet could be used, ExecuteScalar will be much more efficient. The following
example assumes the returned value is an Integer.

Dim retItem As Integer
Dim cmd As New OleDbCommand(sqlText, m_Conn)
retItem = cmd.ExecuteScalar()
int retItem;
private OleDbCommand cmd = new OleDbCommand(sqlText, m_Conn);
retItem = cmd.ExecuteScalar();

More Information
For more information on ADO.NET and examples using SQL Server visit the MSDN ary/default.asp?url=/library/en-us/Dndotnet/html/Usingadonet.asp

Page 4
ADO.NET with VB.NET and C# Steven Nicolaou

Appendix A: DataSet Object Model

The DataTableCollection
An ADO.NET DataSet contains a collection of zero or more tables represented by DataTable objects. The
DataTableCollection contains all the DataTable objects in a DataSet .

The DataRelationCollection
A DataSet contains relationships in its DataRelationCollection object. A relationship, represented by the
DataRelation object, associates rows in one DataTable with rows in another DataTable. It is analogous to a join
path that might exist between primary and foreign key columns in a relational database. A DataRelation identifies
matching columns in two tables of a DataSet.
Relationships enable navigation from one table to another within a DataSet. The essential elements of a
DataRelation are the name of the relationship, the name of the tables being related, and the related columns in
each table. Relationships can be built with more than one column per table by specifying an array of DataColumn
objects as the key columns. When a relationship is added to the DataRelationCollection, it may optionally add a
UniqueKeyConstraint and a ForeignKeyConstraint to enforce integrity constraints when changes are made to
related column values.

Page 5