0% found this document useful (0 votes)
285 views19 pages

C Sharp Chapter 16 - ADO PDF

This document provides an overview of ADO.NET, which is the data access technology used in .NET applications to communicate with databases. It discusses the key ADO.NET classes like Connection, Command, and DataReader that are used to connect to databases, execute queries, and retrieve results. The goals of ADO.NET are to provide simple access to relational data, support for extensibility via data providers, and enable building multi-tier applications through the use of XML.

Uploaded by

Elgen Prestosa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
285 views19 pages

C Sharp Chapter 16 - ADO PDF

This document provides an overview of ADO.NET, which is the data access technology used in .NET applications to communicate with databases. It discusses the key ADO.NET classes like Connection, Command, and DataReader that are used to connect to databases, execute queries, and retrieve results. The goals of ADO.NET are to provide simple access to relational data, support for extensibility via data providers, and enable building multi-tier applications through the use of XML.

Uploaded by

Elgen Prestosa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Chapter 16. ADO.

NET
This is a largely code-based lesson, showing you how ADO.NET (the data access classes in .NET) is
structured and how to accomplish basic data access in a relational database with C#. ADO.NET takes
its name from ADO (ActiveX Data Objects), a widely used set of classes used for data access in the
previous generation of Microsoft technologies. ADO.NET is the preferred data access interface in
the .NET programming environment.

In this lesson, you will be able to:


 Familiarize ADO.NET and the structure of its main classes
 Read data with a DataReader and DataSet.
 Modify the database by adding and deleting records.
 Apply relationships in ADO.NET.
 Direct execution of SQL commands from ADO.NET

16. 1 ADO.NET
ADO.NET is the name for the easy-to-use set of classes you use with C# and the .NET Framework to
access, update data in a relational, table-oriented format. This includes relational databases such as
Microsoft SQL Server and Microsoft Access, as well as other databases and even nonrelational data
sources. ADO.NET is integrated into the .NET Framework and is designed for used with any .NET
language. ADO.NET includes all of the System.Data namespace and its nested namespaces such as
System.Data.SqlClient and System.Data.OleDb, plus some specific data-related classes from the
System. Xml namespace. Physically, the ADO.NET classes are contained in the System.Data.dll
assembly and related System.Data.xxx.dll assemblies with some exceptions such as XML.

Design Goals of ADO.NET


 Simple Access to Relational Data
The primary goal of ADO.NET is to provide simple access, straightforward and easy-to-use classes
(represented by tables, columns, and rows) within relational databases. Also, it introduces the
DataSet class, which represents a set of data from related tables encapsulated as a single unit,
preserving the integrity of the relationships between them.

 Extensibility
It provides a framework for plug-in .NET data providers (also called managed providers) that can be
built to read and write data from any data source. ADO.NET comes with several built-in .NET data
providers, including one for the Microsoft SQL Server database, one for Oracle, one each for the
generic database interfaces ODBC (the Microsoft Open DataBase Connectivity database API) and OLE
DB (Microsoft's COM-based Object Linking and Embedding DataBase API). Almost every database and
data file format has an ODBC or OLE DB provider available for it, including Microsoft Access, third-
party databases, and nonrelational data; thus, ADO.NET can be used to interface to almost any
database or data format through one of the built-in data providers. Many database vendors such as
MySQL and Oracle also provide native .NET data providers for their offerings.

 Support for Multitier Applications


ADO.NET is designed for multitier applications-- the most common architecture today for business and
e-commerce applications. In multitier architecture, different parts of the application logic are
separated into layers, or tiers, and communicate only with the layer around them. One of the most
common approaches is the 3-tier model, which consists of the following:
1. Data tier: Contains the database and data access code.
2. Business tier: Contains the business logic, which defines the unique functionality of this
application, and abstracts this away from other tiers. This tier is sometimes referred to as the
middle tier.
3. Presentation tier: Provides the user interface and control of process flow to the application,
as well as such things as the validation of user input.

ADO.NET uses the open Internet-standard XML format for communications between the tiers, allowing
data to pass through Internet firewalls and allowing the possibility of a non-Microsoft implementation
of one or more tiers.

 Unification of XML and Relational Data Access


Another important goal of ADO.NET is to provide a bridge between relational data in rows and columns,
and XML documents, which have a hierarchical data structure. The .NET technology is built around
XML, and ADO.NET makes extensive use of it.

16 – ADO.Net 1
16.2 Overview of ADO.NET Object Model
Figure 16.1 shows key component classes that are divided into data provider and consumer objects.

Figure 16.1 ADO.Net Object Model

Provider Objects
Provider objects are used to read and write the data in memory using the consumer objects. The
provider objects require an active connection. It is prefaced with a provider-specific name unique to each
type of data source (such as, connection object for the OLE DB provider is OleDbConnection; SQL Server .NET
provider is SqlConnection). The following are objects defined in each .NET data provider:

Connection Object. The connection object provides the basic connection to the data source. When using a
database that requires a user and password or one on a remote network server, the connection object
takes care of the details of establishing the connection and logging in.
SqlConnection thisConnection = new SqlConnection(@"Server=(local)\sqlexpress;
Integrated Security=True;" + "Database=northwind");

Command Object. The Command class (Figure 16.2) represents a set-oriented operation that allows
performing any data-manipulation tasks, such as creating and altering tables, database, retrieving,
update and delete of records in a data source. A Command object is used to execute specific SQL
statement/queries that can be inline text or a Stored Procedure against the data source specified in
the Connection Object. You can execute SQL queries to return data in a DataSet or a DataReader
object. To retrieve, add, update and delete data you use SELECT, INSERT, UPDATE, and DELETE SQL
queries, respectively, meeting a certain condition. A DataAdapter generated has these queries.

Figure 16.2 Command Object

To create a Command object, you need to create a Connection object that will generate a valid open
connection to the data source. To execute the command, the CreateCommand () method is called. The
CreateCommand () method creates and returns a Command object associated with the Connection
object. It allows the Connection object to automatically create the appropriate provider-specific
Command object.
SqlCommand commandObject = connectionObject.CreateCommand();
commandObject.CommandType = CommandType.Text;
commandObject.CommandText = "Insert Into CustomerFile (CustomerCode, CustomerName)" +
"values(@customerCode ,@customerName)";
commandObject.Parameters.AddWithValue("@customerCode",CustomerCodeTextBox.Text );
commandObject.Parameters.AddWithValue("@customerName",CustomerNameTextBox.Text);

The Command object has a property called CommandText, which contains a String value that
represents the command that will be executed in the Data Source. The CommandType property of a
command object specifies how a CommandText is interpreted, either in Text (default),
StoredProcedure (assign the name of the StoredProcedure to CommandText) or TableDirect.

16 – ADO.Net 2
Alternatively, you can pass the connection argument directly to the Command class as in the following.
OleDbCommand cmd = New OleDbCommand(“Select * from CustomerFile”, connectionObject);
The Command constructor takes two parameters. The first is SQL query and the second is the
Connection object. The Connection Object will generate a valid open connection to the data source and
assign the open connection to the connection property of the Command Object for executing the SQL
statements against a Data Source.

Command Object Methods


The following commonly used Command objects methods for executing SQL commands directly with
much more efficient, especially for large tables.

ExecuteScalar() Method -- Retrieving Single Values


This method is used to get a single value (such as the number of records in a given table) from the
database after its execution. This method executes SQL statements or Stored Procedure and returns a
scalar value on first column of first row in the Result Set. If the result set contains more than one
columns or rows, it takes only the first column of first row, all other values will ignore. If the result set
is empty it will return a Null reference.
Example: To get a count of the rows in the Customers table
OleDbCommand thisCommand = thisConnection.CreateCommand();
thisCommand.CommandText = "SELECT COUNT(*) FROM CustomerFile";
Object countResult = thisCommand.ExecuteScalar();
MessageBox.Show("Count of Customers =" + countResult);
The OleDbCommand ExecuteScalar() method executes the query to retrieve the count. This is
equivalent to loading the Customers table into the DataTable object and using the Count property of
the Rows object.

Note: If you have a small amount of data, or are loading all the rows into your DataSet for any other reason, it
makes sense to just use DataTable.Rows.Count. However, if you wanted to count the exact number of rows in a
very large table with 1,000,000 rows, it is much more efficient to issue a SELECT COUNT(*) query with the
ExecuteScalar() method rather than trying to load 1,000,000 rows into memory. It is very useful to use with
aggregate functions ( Count(*),MIN(),MAX(), Sum(),AVG()). ExecuteScalar() uses fewer System resources When
compared to ExecuteReader().

ExecuteNonQuery() Method -- Retrieving No Data


ExecuteNonQuery() method is used for executing statements that do not return result set. Executes
command that changes the data in the database-- Data Definition tasks (such as creating Stored
Procedures and Views) as well as Data Manipulation tasks (Insert , Update and Delete ). This method
returns an integer that is the number of rows affected by the query.

Example: increased all prices by 5 percent for all of its products supplied by the supplier number 12.
SqlCommand command = thisConnection.CreateCommand();
command.CommandText="UPDATE Products SET " + "UnitPrice = UnitPrice*1.05 WHERE
SupplierId=12";
int rowsAffected = thisCommand.ExecuteNonQuery();
if(rowsAffected>0)
Console.WriteLine(“Entries Updated”);
Console.WriteLine("Rows Updated = {0}", rowsAffected);

ExecuteReader() Method -- Direct Execution of SQL Commands


The ExecuteReader() method is used in partnership with the DataReader object. ExecuteReader()
method executes the SQL select statement or a Stored Procedure that contains one or more select
statements to Connection Object of the database. This method returns a DataReader object that can
be used to fill/populate a DataTable object. DataReader returns data to the client as rows can be used
directly for printing reports and so forth.

DataReader Object. The DataReader class (Figure 16.3) provides a pointer based access to the data so
we can get the data in a sequential order. It is used to retrieve data in conjunction with the Command
object to execute a database query (a SQL Select statement). When the query is executed, the first
row is returned to the reader via a data stream. The DataReader object provides the maximum
performance by accessing over the rows in each result set one record at a time and can only move
forward one record at a time in sequential and read-only manner. It requires a live connection with
the data source accessing each column of the result set, read all rows of the set and advance to the
next result set if there are more than one available rows.

Figure 16.3 DataReader Object

16 – ADO.Net 3
The DataReader object cannot be created directly from code, it is created only by binding the
ExecuteReader() method of a Command Object. An open connection must be maintained between
your application and the Data Source through SQL requests. Creating a DataReader with the new
operator doesn't do anything for you. Command object references the connection and the SQL
statement necessary for the DataReader to obtain data.

Features of a DataReader
 It is connection oriented architecture and provides faster access to data from a data source.
This is the best choice when the only requirement for a group of data is for reading one time
and you want the fastest method possible.
 Doesn't have overhead associated with traversing the data or writing back to the data source.
 Appropriate when the need is to simply display the result set, as only one record at a time is
ever present in memory.
 The streaming behavior of the DataReader would be a good choice when the amount of data
needed to read is larger than what is preferred to hold in memory beyond a single call, then
 It can hold multiple tables at a time. To load multiple tables into a DataReader pass multiple
select statements as the argument to the command separated by a colon (;)
Note: use the NextResult() method of the DataReader object to navigate from the current table to the next table.

Drawbacks of a DataReader
 Connection Oriented architecture require/demand a continuous/live connection with the Data
Source to fetch the data, so the performance is decreased if there are a number of clients
accessing the data at the same time.
 It gives only forward direction access to data; it allows going to the next record of the table
but not to the previous record of the table.
 Where data are not updateable or persist across multiple requests.
using System.Data; // Use ADO.NET namespace reference
using System.Data.SqlClient; // Use SQL Server data provider namespace

private void DisplayButton_Click(object sender, EventArgs e) {


// Specify SQL Server-specific connection string, note @ sign prefacing string literal so backslashes in path name;
SqlConnection thisConnection = new SqlConnection( @"Server=(local)\sqlexpress;Integrated
Security=True;" + "Database=northwind");
thisConnection.Open(); // Open connection
SqlCommand thisCommand = thisConnection.CreateCommand();// Create command for this connection

// Specify SQL query for this command


thisCommand.CommandText = "SELECT CustomerCode, CustomerName from CustomerFile";
SqlDataReader thisReader = thisCommand.ExecuteReader(); // Execute DataReader for specified command

// While there are rows to read


while (thisReader.Read()){
// Output ID and name columns
MessageBox.Show("Customer Code "+ thisReader["CustomerCode"]+
“\nCustomer Name ” + thisReader["CustomerName"]);
}

thisReader.Close(); // Close reader


thisConnection.Close(); // Close connection
}
Common Steps To Retrieve The Data Using DataReader Object:
1. Connect to your data source. Create a connection object using a connection string. The connection
string contains the name of the provider for the database you want to connect to, the login
information (database user, password, and so on), and the name of the particular database to use.
Keep in mind that connection strings differ significantly between data providers. Look for the data
provider specific connection information. The line where you create the connection object may look
like this:
SqlConnection thisConnection = new SqlConnection(@"Server=(local)\sqlexpress;Integrated
Security=True;" + "Database=northwind");

SqlConnection is the name of the connection object for the SQL .NET data provider. The connection string consists
of named entries separated by semicolons; let's look at each one. The first is: Server=(=local)\sqlexpress;
This is just the name of the SQL Server you are accessing, in the form computername\instancename. The
computer name (local) is a handy SQL Server shorthand name that refers to the server instance running on the
current machine.

sqlexpress is the SQL Server instance name. Sqlexpress is the default instance name used when you install SQL
Express. If you have another version of SQL Server installed, the instance name will differ — there may be no
instance name (in which case you would use (local) or your machine name by itself), or it may be a different name.

16 – ADO.Net 4
Note that the @ sign prefacing the connection string indicates a string literal, making the backslash in this name
work; otherwise double backslashes (\\) are necessary to escape the backslash character inside a C# string.

The next part of the connection string specifies how to log in to the database; here, you use the integrated security
of the Windows login so no separate user and password need to be specified: Integrated Security=True; This
clause specifies the standard built-in security for SQL Server and Windows. Alternatively, instead of the Integrated
Security clause you could specify a username and password clause, as in User=sa; PWD=secret. Using the built-in
security of your Windows login is preferable to using hard-coded user- names and passwords in connection strings!

Finally, the particular database use is specified, in this case, the Northwind sample: Database = northwind
You must have installed the database to be found. You now have a connection object that is configured for your
machine and database (but the connection is not yet active; to do this you must open it).

2. Open the connection object in order to establishes the connection to the database:
thisConnection.Open(); If the Open() method fails, an exception will be thrown. A particular
message indicates that the program couldn't find the SQL Server database or server. Check that the
server name in the connection string is correct and that the server is running.

To open and close a database connection is an expensive and time-consuming operation. Most
databases have a limit on the number of concurrent connections that they allow. Each connection
consumes a certain amount of resources on the database server and these resources are not infinite.
Most modern OLE DB providers (including SQL Server provider) implement connection pooling. If you
create database connections, they are held in a pool. When you want a connection for an application,
the provider extracts the next available connection from the pool. When your application closes the
connection, it returns to the pool and makes itself available for the next application that wants a
connection.

This means that opening and closing a database connection is no longer an expensive operation. If
you close a connection, it does not mean you disconnect from the database. It just returns the
connection to the pool. If you open a connection, it means it's simply a matter of obtaining an already
open connection from the pool. It's recommended not to keep the connections longer than you need
to. Therefore, you should:
 Open a connection when you need it, and
 Close it as soon as you have finished with it.

3. Issue a SQL query. Create a command object and give it a SQL statement to perform a database
operation (such as retrieving some data). The code to do this is as follows:
SqlCommand thisCommand = thisConnection.CreateCommand();
thisCommand.CommandText = "SELECT CustomerCode, CustomerName from CustomerFile";

4. Read and display the data. Read the data with a DataReader object. The DataReader is a data
stream returned from a query. To get the data, pull data from a table row-by-row one record at a
time (sequential order). Once a row has been read, the previous row is no longer available. To
read that row again, create a new instance of the DataReader and read through the data stream
again.
SqlDataReader thisReader = thisCommand.ExecuteReader();
When a query is executed, the first row is returned to the reader via the stream. Typical method of
reading the data stream is to iterate through each row with a while loop. The DataReader does not
store the actual data, it only provide some sort of a “pointer” to access the database. The Read()
method of the DataReader will populate with the values of the next available record, and returns true
while there is more data available to read and false otherwise.
while (thisReader.Read())
{
MessageBox.Show("Customer Code " + thisReader["CustomerCode"]+
”\nCustomer Name ” thisReader["CustomerName"]);
}
So, while Read() returns true, you can extract each column of the row in two ways. First, with an ordinal numeric
indexer like, thisReader[0], but it isn't very readable. Second, reference the columns as an array reference by
column name, using a string indexer, thisReader[“CustomerCode”] where the string is the column name from the
SQL query. String indexers are much more readable, making the code easier to maintain. Regardless of the type of
the indexer parameter, a DataReader indexer will return type object. Cast the results to a string type when
necessary. Once the values are extracted, display or store the data in another variable.

5. Close the objects you opened (reader object and connection object).
thisReader.Close();
thisConnection.Close();

16 – ADO.Net 5
Note: You can create OleDbConnection, OleDbCommand, and OleDbDataReader objects. These objects
work essentially the same way as their SQL Server counterparts. Accordingly, change the using
directive that specifies the data provider to System.Data.OleDb;

DataAdapter Object. DataAdapter class (Figure 16.4) is a general-purpose class that provides
communication between a DataSet and a DataSource. This is used to provide an easy way to manage
the connection between your application and the underlying database tables, views and Stored
Procedures. DataAdapter manages the communication between the Dataset and the DataSource with
the help of the Connection Object.

The DataAdapter and DataSet objects are combined to perform both data access and data
manipulation operations in the Database, thus, it provides a disconnected data retrieval mechanism.
It can perform Select, Insert, Update and Delete SQL operations in the Data Source. It uses the Select
statement to fill a DataSet and use the other three SQL commands (Insert, Update, Delete) to
transmit changes back to the Database.

Figure 16.4 DataAdapter Object


DataAdapter Properties that allows control on how modifications are made. The four properties that
are set to Command object (Figure 16.2) when data is manipulated:
 SelectCommand
 UpdateCommand
 InsertCommand
 DeleteCommand

OleDbConnection thisConnection=new OleDbConnection(connectionString);


OleDbDataAdapter adapter=new OleDbDataAdapter();
String sql = "Insert Into CustomerFile values('C01','123')";
adapter.InsertCommand = new OleDbCommand(sql, thisConnection);
adapter.InsertCommand .ExecuteNonQuery ();
MessageBox.Show("Entries Recorded");

DataAdapter Common Methods:


 Fill (populates a DataSet with data).
 FillSchema (queries the database for schema information that is necessary to update).
 Update (to change the database, DataAdapter calls the DeleteCommand, InsertCommand and
UpdateCommand properties).

CommandBuilder Object. The CommandBuilder (Figure 16.5) object is used to automatically build SQL
commands for data modification from objects based on a single-table query. It is used to save
changes made in-memory cache of data on backend. The work of CommandBuilder is to generate
command as per changes in DataRows. There is no need to manually code the commands,
CommandBuilder works on add, delete and modified row state only. The CommandBuilder object
generates command on basis of the row state (Unchanged, Added, Deleted, Modified and Detached
(used when object is not created from row state)).

A CommandBuilder is constructed with DataAdapter and immediately generates the remaining


Command objects upon construction. The DataAdapter object is used to manage SelectCommand,
InsertCommand, UpdateCommand, and DeleteCommand properties assigned to the Command objects
to update the database with the data modifications that are run on a DataSet object . These commands
can get quite complicated in .NET because it require complex parameter objects and often involve
large lists of columns.

The CommandBuilder opens the Connection associated with the DataAdapter and makes a round trip
to the server each and every time it's asked to construct the action queries. It closes the Connection
when it's done.
Figure 16.5 CommandBuilder Object

SqlConnection thisConnection = new SqlConnection(connectionString);


string sql = “Select * from CustomerFile” ;
SqlDataAdapter thisAdapter = new SqlDataAdapter(sql,thisConnection);
SqlCommandBuilder thisBuilder = new SqlCommandBuilder(thisAdapter);

16 – ADO.Net 6
Consumer Objects
Consumer objects are used to access and manipulate the data once you have read it into memory.
Consumer objects operate in a disconnected fashion; you can work with the data in memory even if
the database connection is down. These objects aren't related to any specific .NET data provider and
live within the System.Data namespace.

DataSet Object. The DataSet is the king of consumer objects. The DataSet represents a set of
related tables referenced as one unit in your application. For example, Customers, Orders, and
Products might all be tables in one DataSet representing each customer and the products
ordered from a company. With this object, you can get all the data you need from each table
quickly, examine and change it while you're disconnected from the server, and then update
the server with the changes in one efficient operation. The DataSet has features that let you
access lower-level objects that represent individual tables (DataTable) and
relationships(DataRelation).

DataTable Object. This object represents one of the tables in the DataSet, such as Customers,
Orders, or Products. The DataTable object has features that allow you to access its rows and
columns: DataColumn object: This represents one column in the table, for example OrderID or
CustomerName. DataRow object: This represents one row of related data from a table; for
example, a particular customer's CustomerID, name, address, and so on.

DataRelation Object. This object represents the relationship between two tables via a shared
column; for example, the Orders table might have a CustomerID column identifying the
customer who placed the order. A DataRelation object might be created representing the
relationship between Customers and Orders via the shared column CustomerID.

Mandatory Namespaces Used in ADO.Net


The first step in using ADO.NET is to reference the System.Data namespace, in which all the ADO.NET
classes are located. Put the following using directive at the beginning:
using System.Data;

Next, is to reference the .NET data provider for the specific data source to be used.
 SQL Server .NET Data Provider. The best performance and most direct access to the underlying
features is available with the native (SQL Server–specific) .NET data provider when SQL
Server database (version 7 or greater) including the desktop engine (SQL Express or MSDE)
used as the data source, referenced with this using directive:
using System.Data.SqlClient;

 Oracle .NET Data Provider. If you are using the Oracle database, a native Oracle .NET driver is the
best choice, referenced with this using directive:
using System.Data.OracleClient;

 OLE DB .NET Data Provider. OLE DB providers for many common databases are installed with
Windows, notably Microsoft Access as data source, referenced with this using directive:
using System.Data.OleDb;

 ODBC .NET Data Provider. If you have a data source for which no native or OLE DB provider is
available, the ODBC .NET data provider is a good alternative because most databases provide
an ODBC interface. It is referenced with this using directive: using System.Data.Odbc;

Many other database vendors and third-party companies provide native .NET data providers; the
choice between using the native provider and using something generic like the ODBC provider will
depend on your circumstances. If you value portability over performance, then go generic. If you want
to get the best performance or make the best use of a particular database's features, go native.

16.3 DataSet - The Central Object In ADO.Net To Access Tables


A DataSet represents a local copy of extracted information being downloaded and cached in the client-
system. The DataSet can hold multiple tables in cache. It supports disconnected data access and
operations of any complexity, allowing greater scalability because there is no need to be connected to
the database all the time. Changes can be made to the local copy in the DataSet and synchronize the
modifications with the database through an adapter object. Constraints can be added to the locally
stored tables to enforce unique and foreign key constraints.

16 – ADO.Net 7
The DataSet object can be Typed or UnTyped and is made up of two objects:
 DataTableCollection object contain null or multiple DataTable objects. The DataSet object
has a property named Tables that contains a set of DataTable objects representing the
database tables that you are working within the DataSet.

Each DataTable object has DataRow and DataColumn objects representing the rows and columns of
the database table. You can get to all the individual elements of the tables, rows, and columns
through these objects. DataTable is of type DataTableCollection and has an overloaded indexer, that
you can access each individual DataTable in one of two possible ways:
 By table name: thisDataSet.Tables["Customers"] specifies the DataTable called Customers.
 By index (zero-based): thisDataSet.Tables[0] specifies the first DataTable in the DataSet.

A DataTable has a Rows property (a collection of the individual DataRow objects. Rows is of type
DataRowCollection), and is an ordered list, indexed by row number.

Thus myDataSet.Tables["Customers"].Rows[n] DataRow object specifies row number n-1


(remember the index is zero-based) in the Customers DataTable of thisDataSet.

The DataRow object itself has an indexer property that is overloaded, allowing you to access individual
columns:
 by column name: thisDataSet.Tables["Customers"].Rows[n]["CompanyName"];
 by index. thisDataSet.Tables["Customers"].Rows[n][0];
thisDataSet specifies the CompanyName column of row number n-1 in the Customers DataTable
of thisDataSet

 DataRelationCollection object containing null or multiple DataRelation objects which


establish a parent/child relation between two DataTable objects.

How to Populate a DataSet


A DataSet is a container that you have to populate with data in a variety of ways:
 by using DataAdapter objects and Fill method.
DataAdapter object is like a bridge that links the database and a Connection object with the ADO.NET-
managed DataSet object through its SELECT and action query Commands. It specifies what data to
move into and out of the DataSet using the Fill() method. Often, this takes the form of references to
SQL statements or stored procedures that are invoked to read or write to a database.
DataSet thisDataSet = new DataSet();
thisAdapter.Fill(thisDataSet, "CustomerFile");

 by creating DataTable, DataColumn and DataRow objects programmatically.


Create a DataTable and define its structure using columns and constraints, then add new rows of data
to the table.
DataSet ds = new DataSet();
DataTable dtbl = new DataTable();
DataColumn nameColumn = new DataColumn("Name", Type.GetType("System.String"));
dtbl.Columns.Add(nameColumn);
DataRow drow=dtbl.NewRow(); //create a new row
drow["Name"]="Elize"; // manipulate the newly added row using the column name or index by
dtbl.Rows.Add(drow); // 1. add the row to the DataRowCollection or
dtbl.Rows.Add(new object[] {1, "Elective"});// 2. add a new row by passing in an array of values, typed as Object
ds.Tables.Add(dtbl);

 Read an XML document or stream into the DataSet.


protected System.Web.UI.WebControls.Xml XmlDisplay;
SqlConnection thisConnection=new SqlConnection(@". . . . . ");
thisConnectionOpen();
try{
string strSql="SELECT * from FROM AUTHORS FOR XML AUTO, XMLDATA";
SqlCommand cmd=new SqlCommand(strSql, thisConnection);
DataSet thisDataSet=new DataSet();
/* the ExecuteXmlReader() to pass an XmlReader object to the DataSet's ReadXml() allows the DataSet to populate itself from the XmlReader. */
thisDataSet.ReadXml(cmd.ExecuteXmlReader(),XmlReadMode.Fragment);
/*sets the DocumentContent property to the result of the GetXml method of theDataSet. Code.
XML uses the XSL Transformation document authors.xsl (included in the project) to format the XML content displayed by the XML control.*/
XmlDisplay.DocumentContent = thisDataSet.GetXml();
}finally {
thisConnection.Close();
}
16 – ADO.Net 8
 Merge (copy) the contents of another DataSet, with the Merge method.
Two DataSet objects that have largely similar schemas can be merged. Merging is use typically on a
client application to incorporate the latest changes from a data source into an existing DataSet. This
allows the client application to have a refreshed DataSet with the latest data from the data source.
Example: dataset1.Merge(dataset2);

16.4 Database Operations


Retrieving Records From a Table of a Database - A Disconnected Data Access Architecture
Example: To retrieve and display all the records from a Customers table.
using System.Data.SqlClient; // Use SQL Server data provider namespace
public static string connectionString = @" . . . ";
private void DisplayAllButton_Click(. . . Events args)
{
// 1. Specify SQL Server-specific connection string
SqlConnection thisConnection = new SqlConnection(connectionString);
// 2. Create DataAdapter object
SqlDataAdapter thisAdapter =new SqlDataAdapter("SELECT CustomerCode, CustomerName FROM
CustomerFile",thisConnection);
// 3. Create DataSet to contain related data tables, rows, and columns
DataSet thisDataSet = new DataSet();
// 4. Fill DataSet using query defined previously for DataAdapter
/*A table named CustomerFile will be created in this DataSet and filled with data.
. CustomersFile does not refer to the CustomerFile table in the actual database. */
thisAdapter.Fill(thisDataSet, "CustomerFile");

/*access the individual rows and columns. loop through all the DataRow objects in the Rows collection of the CustomerFile table.
For each DataRow, retrieve the values in the CustomerCode and CustomerName column:*/
foreach (DataRow theRow in thisDataSet.Tables["CustomerFile"].Rows)
{
int row = dataGridView1.Rows.Add();
dataGridView1.Rows[row].Cells[“CustomerCodeColumn”].Value = theRow["CustomerCode"];
dataGridView1.Rows[row].Cells[“CustomerNameColumn”].Value = theRow["CustomerName"];
}
}
Note. You have not explicitly opened or closed a connection in this example — the data adapter takes care of this
for us. The data adapter object will open a connection as needed and close it again once it has finished its work.
The data adapter will leave the state of the connection unchanged — so if the connection was open before the data
adapter started its work, it will be still be open after the data adapter has finished.

Updating the Database


The tasks (of updating, inserting, and deleting records) to operate on the database can be
accomplished with the same pattern: Fill a DataSet with the data from the database. Modify (update,
insert, or delete) the data held in the DataSet. Once all the modifications are made, persist the
DataSet changes back to the database.

Example: To change a customer name in the database.


public void UpdateButton_Click(object sender, EventArgs e) {
SqlConnection thisConnection = new SqlConnection(@”. . . . “); // Specify a specific connection string
// Create DataAdapter object for update and other operations
String sql =“SELECT * FROM CustomerFile where CustomerCode=’"+CustomerCodeTextBox.Text+”’”;
SqlDataAdapter thisAdapter = new SqlDataAdapter(sql, thisConnection);
SqlCommandBuilder thisBuilder = new SqlCommandBuilder(thisAdapter);
DataSet thisDataSet = new DataSet();
thisAdapter.Fill(thisDataSet,"CustomerFile"); // Fill DataSet using query defined previously for DataAdapter

if(thisDataSet.Tables[“CustomerFile”].Rows[0][“CustomerCode”])==CustomerCodeTextBox.Text){
thisDataSet.Tables["CustomerFile"].Rows[0]["CustomerName"] = CustomerNameTextBox.Text;
thisAdapter.Update(thisDataSet, "CustomerFile"); // Call Update command to mark changes in the table
MessageBox.Show(“Customer Name is Updated!”);
}

In the SQL query string, “SELECT * FROM Customers where


CustomerCode=’"+CustomerCodeTextBox.Text+”’”; you place a qualifier to select just the rows you
were interested in. Then, the DataAdapter object performs the data access and data manipulation
operations in the data source. The DataAdapter object provides communication between the DataSet
and the Data source with the help of Connection object.

16 – ADO.Net 9
There is no need to worry about the exact SQL syntax for updating the database, all the modifications
to the data in the database can be performed at one time by a CommandBuilder (instead of using
InsertCommand(), UpdateCommand() and DeleteCommand()). Note that you pass thisAdapter to the
SqlCommandBuilder constructor as an argument. The correct SQL commands are generated and
associated with the passed data adapter by the constructor when the SqlCommandBuilder object is
created. The CommandBuilder object takes care of the correct SQL statements for updating
the database. It opens the connection associated with the DataAdapter and makes a round trip to
the servers each and every time it’s asked to construct the action queries. It closes the connection
when it is done.

Now, create your DataSet object (disconnected representation of result sets from data source) and fill
in with data from the query, in this case, it is the CustomerFile table you want, so you call the
associated DataTable in the DataSet by the same name. Now that the DataSet has been filled, you can
access the individual rows and columns.
DataSet thisDataSet = new DataSet();
thisAdapter.Fill(thisDataSet, "CustomerFile");

Validate first the CustomerCode from the input prior to changing the value of a DataColumn:
if(thisDataSet.Tables[“CustomerFile”].Rows[0][“CustomerCode”])==CustomerCodeTextBox.Text)
thisDataSet.Tables["CustomerFile"].Rows[0]["CustomerName"]=CustomerNameTextBox.Text;

However, this change only modifies the value of the column in the DataSet in memory, not in the
database itself. To update the database, you need to call the Update() method, specify the DataSet
you want the update to be based on and the name of the DataTable. It's important that the DataTable
name match the one you used when calling the Fill() method. Like this:
thisAdapter.Update(thisDataSet, "CustomerFile");

The Update() method of the DataAdapter automatically goes through the rows in the
DataTable to check for changes that need to be made to the database. Each DataRow object in
the Rows collection has a RowState property, that keep track whether a row is deleted, added,
modified, or is unchanged. Any changes made are reflected in the database.

Saving Records to the Database


The process for adding a new record to the database is straightforward:
1. Create a new DataRow.
//create the new row object, using the NewRow() method of the DataTable object;
// Creates a new row object using the same columns as the Customers table, but does not actually add it to the DataSet;
DataRow thisRow = thisDataSet.Tables["CustomerFile"].NewRow();

2. Populate it with some data.


//assign some values to the columns
thisRow["CustomerCode"] = "UCBANILAD";
thisRow["CustomerName"] = "University of Cebu - Banilad";

3. Add it to the Rows collection of the DataSet.


//actual adding of the rows using the Add() method of the Rows collection:
thisDataSet.Tables["CustomerFile"].Rows.Add(thisRow);

4. Persist this change back to the database by calling the Update() method of the data adapter.
//the call to Update() is needed to actually add the new row to the database on disk:
thisAdapter.Update (thisDataSet, "CustomerFile");

Remember, the DataSet is an in-memory, disconnected copy of the data; it is the DataAdapter which
is actually connected to the database on disk and, therefore, its Update() method needs to be called to
synchronize the in-memory data in the DataSet with the database on disk.

Finding Rows Before Adding Into The Table


Before adding rows in the table, it is necessary to check or search the row first if the row already exist.
The DataTable Rows collection has a method called Find() that is very useful for this purpose. You
need to set up a DataRow object to get the result. If Find() locates a matching row, it returns the
DataRow matching that row; if it does not find a match, it returns a null reference. The Find() takes a
parameter, which is the value to look up or search.

Before Find() method can be used, setting up a primary key is a necessity. The primary key is what
you will use when searching. A primary key is made of one or more of the columns of the table
and contains a value or set of values that uniquely identifies this particular row in the table,
so that when you search by the key you will find one and only one row.
16 – ADO.Net 10
Two ways to accomplish a primary key set up:
1. An array of objects that is made from a table with multicolumn primary key.
 Create a DataColumn array object — since a table consists of more unique columns, an array
is the natural structure to use;
 assign the first element of the array to the field or column name, and the next element field, if
there is another alternate key in the table;
 assign the array object to the PrimaryKey property of the DataTable object.

Example: A case with two or more primary fields, we use an array of objects for multicolumn primary key; Find()
method takes an array of objects as parameter. The OrderDetails table in the database uses the ProductID and
OrderID column as its primary keys:
public void SaveButton_Click (. . . . )
{
. . . .
<some codes are omitted for clarity>
thisAdapter.Fill(thisDataSet, "OrderDetails");

//setup primary key


DataColumn[] keys = new DataColumn[2];// DataColumn array is named keys
//assign the first element of the keys array, keys[0] to the ProductID column in Product table.
keys[0] = thisDataSet.Tables["OrderDetails"].Columns["ProductID"];
keys[1] = thisDataSet.Tables["OrderDetails"].Columns["OrderID"];
// assign the array keys to the PrimaryKey property of the OrderDetails DataTable object.
thisDataSet.Tables["OrderDetails"].PrimaryKey = keys;

// values to be searched
String [] valuesToSearch = new String[2];
valuesToSearch[0]= PoductCodeTextBox.Text;
valuesToSearch[1]= OrderCodeTextBox.Text;

DataRow findRow = thisDataSet.Tables["OrderDetails"].Rows.Find(valuesToSearch);


if (findRow == null){
DataRow thisRow = thisDataSet.Tables["OrderDetails"].NewRow();
thisRow["ProductCode"] = ProductCodeTextBox.Text;
thisRow["OrderCode"] = OrderCodeTextBox.Text;
thisDataSet.Tables["OrderDetails"].Rows.Add(thisRow);
thisAdapter.Update(thisDataSet, "OrderDetails");
MessageBox.Show("Entries Recorded!",”Order Entry”);
}
else{
MessageBox.Show("Duplicate Entry!");
}
}

2. A primary key that is made up of single column only.


 Explicitly tell ADO.NET to load the primary key information directly from the database by
setting the DataAdapter MissingSchemaAction property before filling the DataSet.

Example: A case for a table with only one primary key column: Find() method takes a single object parameter which is the value you want to look up
public void SaveButton_Click (. . . . )
{
. . . .
<some codes are omitted for clarity>

// Primary key setup by initializing the PrimaryKey property of the DataTable implicitly, simply setup keys object for defining primary key.
thisAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
thisAdapter.Fill(thisDataSet, "CustomerFile"); // Fill DataSet using the query defined for DataAdapter

DataRow findRow = thisDataSet.Tables["CustomerFile"].Rows.Find(CustomerCodeTextBox.Text);


if (findRow == null){
DataRow thisRow = thisDataSet.Tables["CustomerFile"].NewRow();
thisRow["CustomerCode"] = CustomerCodeTextBox.Text
thisRow["CustomerName"] = CustomerName.Text
thisDataSet.Tables["CustomerFile"].Rows.Add(thisRow);
thisAdapter.Update(thisDataSet, "CustomerFile");
MessageBox.Show("Entries Recorded!",”Order Entry”);
}
/* an optional else statement can be placed here to handle exception in case a duplicate data is found!*/
}

16 – ADO.Net 11
If findRow is null, go ahead and add the row. When an error message like “The changes you requested
to the table. . . ..” occur, this indicates that the Add() failed because it would have created a duplicate
row. The definition of the table requires that a field contain unique values, which is required when a
column is designated the primary key.

Deleting A Record From A Table


The DataRow object has a Delete() method that removes the current row. The following code let you
test for findRow not equal to null (in other words, the row you were searching for was found). Then
you remove the row by calling Delete() on findRow.
Example. To delete the row for a specific customer, if found!
.......
<some codes are omitted for clarity purposes>
SqlCommandBuilder thisBuilder = new SqlCommandBuilder(thisAdapter);
DataSet thisDataSet = new DataSet(); // Create DataSet to contain related data tables, rows, and columns
thisAdapter.Fill(thisDataSet, "CustomerFile"); // Fill DataSet using query defined previously for DataAdapter

DataRow findRow= thisDataSet.Tables["CustomerFile"].Rows.Find(CustomerCodeTextBox.Text);


if (findRow != null){ // if the value is found it will be removed from the CustomerFile table!
MessageBox.Show( CustomerTextBox.Text + " is already in Customers table");
findRow.Delete();
thisAdapter.Update(thisDataSet, "CustomerFile");
}

Note. When Delete() is called it doesn't actually remove the row in the database, it just marks it for
deletion until Update is called to commit the change. Each DataRow object in the Rows collection has a
property, RowState, that tracks whether this row is deleted, added, modified, or is unchanged. The
Delete() method sets the RowState of the row to Deleted, and then Update() deletes any rows it finds
in the Rows collection marked as Deleted from the database.

A word of caution about calling the AcceptChanges() method of the DataSet after Delete() — doing so
will remove the row from the DataSet, which means that there will be no effect on the row in the
actual database, because Update() acts only on the rows it finds in the Rows collection, and a missing
row is simply ignored. This same issue applies to the Remove() method; call this only if you want to
remove rows from the Rows collection of the DataSet, but not from the database itself.

16. 5 Accessing Multiple Tables In A DataSet


One of the big advantages of the ADO.NET model lies in the fact that the DataSet object tracks
multiple tables and the relationships between them all within itself. This means that you can pass an
entire set of related data between parts of your program in one operation, and the architecture
inherently maintains the integrity of the relationships between the data.

Relationships in ADO.NET
The DataRelation object is used to describe the relationships between multiple DataTable objects in a
DataSet. Figure 16.6 shows each row of the OrderFile table contains the CustomerID of the customer
placing the order; you match all the order rows containing a particular CustomerID with that
customer's row in the Customers table. The matching CustomerID fields in the two tables define a
one-to-many relationship (each customer may place several orders) between CustomerFile table and
the OrderFile table. Use this relationship creating a DataRelation object to represent it.

Figure 16.6 Match Customer Orders with the Specific Customer


Creating a DataRelation Object
The DataSet has a Relations property that is a collection of all the DataRelation objects representing
relationships between tables in the DataSet. To create a new DataRelation, use the Add() method of
Relations which accepts a string name for the relationship and two DataColumns — the parent column,
followed by the child column.
Example: To create the relationship between the CustomerID of the Customers table and the CustomerID of the Orders table.
custOrderRel =
thisDataSet.Relations.Add("CustOrders",thisDataSet.Tables["CustomerFile"].
Columns["CustomerID"],thisDataSet.Tables["OrderFile"].Columns["CustomerID"]);

16 – ADO.Net 12
Navigating with Relationships
To use the relationship, navigate from a row of one of the tables to the related rows in the other table.
Often navigations consist of traversing from a parent row in the first table to the related children in
the other table. In Figure 16.6, the row in the CustomerFile table can be considered the parent row
and each of the related rows in the OrderFile table can be considered children. Navigations can also go
in the opposite direction.

Fetching the Child Rows


Given a row in the parent table, how do you obtain all the rows in the child table that correspond to
this row? You can retrieve this set of rows with the GetChildRows() method of the DataRow object.
The DataRelation object that you have created between the parent and child tables is passed to the
method, and a DataRowCollection object is returned, which is a collection of the related DataRow
objects in the child DataTable.

For example, with the DataRelation that you created earlier, if the given DataRow in the parent
DataTable (CustomerFile) is customerRow, then customerRow.GetChildRows(custOrderRel);
returns the collection of corresponding DataRow objects from the OrderFile table.

Getting the Related Rows with Multiple Tables


To display the details of each customer order, including the product names, by following the
relationships between four tables: CustomerFile, OrderFile, OrderDetails, and ProductFile tables.
SqlDataAdapter custAdapter = new SqlDataAdapter("SELECT * FROM CustomerFile", thisConnection);
custAdapter.Fill(thisDataSet, "CustomerFile");
SqlDataAdapter orderAdapter = new SqlDataAdapter("SELECT * FROM OrdersFile",thisConnection);
orderAdapter.Fill(thisDataSet, "OrderFile");
SqlDataAdapter detailAdapter =new SqlDataAdapter("SELECT * FROM [OrderDetails]", thisConnection);
detailAdapter.Fill(thisDataSet, "OrderDetails");
SqlDataAdapter prodAdapter = new SqlDataAdapter("SELECT * FROM ProductFile", thisConnection);
prodAdapter.Fill(thisDataSet, "ProductFile");

//build DataRelation objects for each of the relationships between the four tables: and link to the dataset
DataRelation custOrderRel =
thisDataSet.Relations.Add("CustOrders",thisDataSet.Tables["CustomerFile"].Columns["Cus
tomerID"],thisDataSet.Tables["OrderFile"].Columns["CustomerID"]);
DataRelation orderDetailRel =
thisDataSet.Relations.Add("OrderDetail",thisDataSet.Tables["OrdersFile"].Columns["Orde
rID"], thisDataSet.Tables["OrderDetails"].Columns["OrderID"]);
DataRelation orderProductRel =
thisDataSet.Relations.Add( "OrderProducts",thisDataSet.Tables["ProductFile"].Columns["
ProductID"], thisDataSet.Tables["OrderDetails"].Columns["ProductID"]);

foreach (DataRow custRow in thisDataSet.Tables["CustomerFile"].Rows)


{
Console.WriteLine("Customer ID: " + custRow["CustomerID"]);
foreach (DataRow orderRow in custRow.GetChildRows(custOrderRel))
{
Console.WriteLine("\tOrder ID: " + orderRow["OrderID"]);
Console.WriteLine("\t\tOrder Date: " + orderRow["OrderDate"]);

foreach (DataRow detailRow in orderRow.GetChildRows(orderDetailRel))


{
Console.WriteLine("\t\tProduct:"+ detailRow.GetParentRow(orderProductRel)["ProductName"]);
Console.WriteLine("\t\tQuantity: " + detailRow["Quantity"]);
}
}
}
To find the customers and orders, loop through the Rows collection of the Customers table, printing
the CustomerID and CompanyName for each customer. Once displayed the customer, display the
related orders for that customer. To obtain the child rows related to this parent, call the
GetChildRows() method of DataRow and pass the DataRelation object to GetChildRows(), and it
returns a DataRowCollection containing just the related rows in the Orders table for this customer.

Next, print out the additional detail of the OrderDate to the OrderID and then get the OrderDetails for
this OrderID. The innermost loop is different; to get the Product row, call GetParentRow(), which gets
the parent object, going from the many side to the one side of the relationship. Sometimes, this
navigation from child to parent is called navigating upstream, as opposed to the normal parent-to-
child downstream navigation. Upstream navigation requires the GetParentRow() call.
16 – ADO.Net 13
16.6 Checkpoint
Name: _________________________________ Schedule: __________________ Date: ______________
General Instructions: Questions/Clarifications should be forwarded to the instructor only. Write your answers
legibly in INK. Accidentally correct answer will not be given credit. Erasures/Alterations are considered wrong.
Academic policy applies. Do not forget to THINK
I. MULTIPLE CHOICE. Encircle the letter that describes best answer.
1. Each row in a database table represents a ________.
A. file B. field C. record D. cell

2. System.Data contains objects used for accessing and storing relational data. Each of these objects
is independent of the type of data source and the way we connect it. Which of these objects are not
part of the System.Data namespace?
A. DataSet B. DataAdapter C. DataTable D. DataRelation

3. The object in ADO.NET handles the execution of SQL statements for the DataReader and
DataAdapter classes.
A. Command B. DataSet C) OLEDB D) Database

4. The DataReader is used for forward-only reading of data. To be able to reuse data from a database,
manipulate the __________ class.
A. ExecuteNonScalar B. ExecuteReader C. DataSet D. DataBase

5. Which of the following statements is TRUE regarding the DataSet object?


A. DataSet is fast access compared to DataReader.
B. A DataSet can be modified, that is rows can be added or deleted.
C. DataSet releases the records as query executes and do not wait for the entire query to execute.
D. Fetches the record from a database and stores in the network buffer and gives whenever requested.

6. Which Dataset gives easier access to the contents of the table?


A. Typed B. UnTyped C. Mixed D. there are no table typing

7. If we are not returning any records from the database which method is used?
A. ExecuteReader () B. ExecuteScalar () C. ExecuteNonQuery() D. ExecuteReaderOnce()

8. Which ADO.Net object has the best performance, for retrieving the data?
A. DataReader B. Data Provider C. DataSet D. DataAdapter

9. The databases that make up the data in a dataset, __________________.


A. Should be from Single database source
B. Can include many heterogeneous databases sources
C. Can be from multiple databases, which are homogeneous
D. Should be from a compatible data provider

10. You can create a disconnected database access using the _______ class with the dataset class.
A. DataAdapter B. DataReader C. Command D. OleDbConnection

11. When using OleDbConnection, the programmer must close the active connection to the data
source explicitly once no further changes are to be made because,
A. Like DataSets, OleDbCommand objects do not cache data in local memory.
B. Like DataSets, OleDbCommand objects do cache data in local memory.
C. Unlike DataSets, OleDbCommand objects do not cache data in local memory.
D. Unlike DataSets, OleDbCommand objects do cache data in local memory.

12. A connection strings contains:


A. a using directive B. the name of the data source
C. the version number database management system D. the list of fields in the database

13. A program can use instances of class __________ that represents an arbitrary SQL command to
be manipulated on a data source through a(n) _______.
A. CommandText, OleDbCommand B.OleDbCommand, OleDbConnection
C. OleDbCommand, CommandText D. CommandText, OleDbConnection

14. ADO.Net connection object is used to establish a connection between __________________.


A. Application and the DataTable B. Application and the data object
C. Application and DataSet. D. Application and data source

16 – ADO.Net 14
15. Depending on whether there is a primary key in the DataSet, this method can be used to update
and existing table in a DataSet without changes made to the data in the original data source.
A. Fill B. Update C. FillSchema D. Dispose

16. How many records in memory at any given point of time a the DataReader reads the Data.
A. All records pulled by the reader B. Only one record at a time C. depends on the DataSet
D. Depends on the data provider E. Depends on the data source
17. An object of the class is used to avoid writing additional SQL statements to update a live database.
A. DataReader B. DataSet C. CommandBuilder D. DataGrid

18. Which of the following statements is true about Dataset?


A. DataSet can store only one table in its cache
B. Dataset can store multiple tables in cache
C. DataSet cannot store any tables in the cache
D. Dataset stores tables in the cache, only when cache set to true
E. DataSet stores table in the cache, for a certain time period

19. Which of the following is FALSE regarding the DataReader object?


A. Provides a stream-based forward only and read only retrieval of results from a data source.
B. It requires an exclusive use of connection object throughout its lifetime.
C. Update method of the DataReader object transmits changes to the database.
D. Stores one result at a time on a client that results to a significant reduction of memory usage and
system resources.

20. The _____ creates and returns a DataReader object.


A. Command.ExecuteReader B. Command.CommandType C. Command.ExecuteScalar
D. Command.ExecuteNonQuery E. Command.CommandText

21. Which type of Dataset supports schema?


A. Typed B. UnTyped C. Mixed D. All types

22. A data provider provides a set of components that helps to extract data from the database,
except
A. Connection B. DataSet C. DataReader D. DataAdapter

23. Each DataRelation represents a relationship between two tables through _________ objects.
A. Rows B. DataRow C. DataColumn D. both B and C

24. An alternative to creating a DataSet (and DataAdapter) is to create a __________. This provides
connected, forward-only, read-only access to a collection of tables, by executing either a SQL
statement or stored procedures.
A. DataTable B. Command C. CommandReader D. DataReader

25. How do I get data into and out of a DataTable?


1. Use the Fill() method of the ADO.Net DataAdapter
2. Use the Update() method of the ADO.NET DataAdapter.
3. Use the ExecuteReader() method of the DataReader object
4. Use DataReader object HasRows() method.
A. 1,4 B. 2,3 C. 1,2 D. 1,2,3,4

26. How do the SQL classes in .Net communicate to SQL Server?


A. Tabular Data Stream B. Binary Format C. ODBC D. Data

27. When we need to retrieve only a single value from the database, which method is efficient?
A. ExecuteReader() B. ExecuteScalar() C. ExecuteNonQuery() D. ExecuteXmlReader()

28. Opens the connection associated with the DataAdapter object and make round trip to the server
each time it is asked to construct the action queries (build SQL commands).
A. CommandBuilder B. DataReader C. Command D. DataSet

29. Namespaces System.Data.XXX (OleDb,SqlClient,ODBC,OracleClient). Include classes for different:


A. data providers B. file streams C. ADO.NET applicants D. databases

30. The core classes available with each data provider include all the following, except:
A. DataReader B. DataAdapter C. Command D. Dataset

16 – ADO.Net 15
PROJECT DEVELOPMENT
PROJECT OBJECTIVE: To design and implement a Simple Production System.
PROJECT SPECIFICATIONS
1. Database Design
Database Name : PRODUCTION.mdb
Transaction Files
Table Name : JOHeaderFile
Description : Records of the transaction information of the order made by the customer.
Primary Key : JOHNO
Fields Data Type Length Description
JOHNO Long Job Order No.
JOHDATE Date Transaction Date
JOHCUSTNO Text 5 Customer
JOHTOTAMT Currency Total Amount Ordered
JOHPREPBY Text 5 Employee who receives the order (Employee ID)
JOHSTAT Text 2 Order Status
“OP” – Open = the Order is not yet completely delivered
“CL” – Close=Orders Completely delivered
Table Name : JODetailFile
Description : Records of the items bought by the customer.
Primary Key : JODNO + JODPRODCODE
Fields Data Type Length Description
JODNO Long Job Order No.
JODPRODCODE Text 5 Item Code
JODQTYORD Integer Quantity Ordered
JODPRICE Currency Item Price
JODBOMSTAT Text 2 Bill of Materials (BOM) Status
“NC” - BOM not yet generated
“CR” – BOM already generated
JODSTAT Text 2 Ordered Item Status
“OP” – product not yet totally delivered
“CL” – product completely delivered
Table Name : BOMHeaderFile
Description : Keeps the transaction information of the Bill of Materials of a particular product.
Primary Key : BOMHNO
Fields Data Type Length Description
BOMHNO Long BOM Number
BOMHDATE Date Date BOM generated
BOMHJONO Long Job Order No
BOMHPRODCODE Text 5 Product Code
BOMHQTYORD Integer Quantity Billed (Ordered)
BOMHPREPBY Text 5 Employee who prepares BOM
BOMHAPPBY Text 5 Employee who approves BOM
BOMHSTAT Text 2 BOM Status
“OP” – Open (not yet totally purchased /requested)
“CL” – Closed (already purchased/requested)
“CA” – Cancelled
Tablename : BOMDetailFile
Description : Records of the raw materials needed with its corresponding total quantity needed to produce a
particular product.
Primary Key : BOMDNO+BOMDMATCODE
Fields Data Type Length Description
BOMDNO Long BOM Number
BOMDMATCODE Text 5 Raw Material Needed
BOMDQTYNEED Integer Quantity Needed to produce the product
BOMDTOTQTYNEED Integer Total Quantity Needed to produce the product
BOMDQTYRELEASED Integer Quantity Released
BOMDQTYPURCHASED Integer Quantity Purchased
BOMDSTAT Text 2 Material Status
“OP” – Open (material not yet purchased /requested)
“CL” – Closed (material already purchased/requested)
“CA” – Cancelled

Table Name : MaterialReleaseDetailFile


Description : Records of the materials released.
Primary Key : MRDNO + MRDMATCODE
Fields Data Type Length Description
MRDNO Long Material Release No.
MRDMATCODE Text 5 Material Code
MRDQTYRELEASED Integer Quantity Released

16 – ADO.Net 16
Table Name : MaterialReleaseHeaderFile
Description : Records of the transaction information of the materials released from Stockroom/warehouse.
Primary Key : MRHNO
Fields Data Type Length Description
MRHNO Long Material Release No.
MRHDATE Date Release Date
MRHBOMNO Long BOM No
MRHPRODCODE Text 5 Product Code
MRHPREPBY Text 5 Employee who releases the materials
MRHREQBY Text 5 Employee who requests the materials
MRHSTAT Text 2 Release Status
“OP” – Not yet posted/audited
“CL” – Already posted/audited
“CA” – cancelled
Table Name : POHeaderFile
Description : Records of the transaction information of the materials purchase from the supplier.
Primary Key : POHNO
Fields Data Type Length Description
POHNO Long Purchase Order No.
POHDATE Date Transaction Date
POHSUPPNO Text 5 Supplier
POHPREPBY Text 5 Employee who prepares the PO (Employee ID)
POHAPPBY Text 5 Employee who approves the PO (Employee ID)
POHSTAT Text 2 PO Status
“OP” – Open, materials are not yet completely received from supplier
“CL” – Materials Completely received
Table Name : PODetailFile
Description : Records of the materials purchased.
Primary Key : PODNO + PODBOMNO+PODMATCODE
Fields Data Type Length Description
PODNO Long Purchase Order No.
PODBOMNO Long BOM No.
PODMATCODE Text 5 Material Code
PODQTYPURCHASED Integer Quantity Purchased
PODSTAT Text 2 PO Item Status
“OP” – material not yet totally delivered
“CL” – material completely delivered
Reference Files
Table Name : PRODUCTFILE
Description : Records of the products sold by the company.
Primary Key : PRODCODE
Fields Data Type Length Description
PRODCODE Text 5 Product Code
PRODDESC Text 40 Description of the Product
PRODPRICE Currency Price of the Product
PRODUM Text 10 Unit of Measure
PRODSTAT Text 2 Item Status
“AC” – Active
“IN” – Inactive
Table Name : MaterialFile
Description : Records of the raw materials.
Primary Key: MATCODE
Fields Data Type Length Description
MATCODE Text 5 Material Code
MATDESC Text 40 Description of the Material
MATUM Text 10 Unit of Measure
MATQTYONHAND Integer Quantity on Hand
MATQTYADDON Integer Purchase Quantity Add-on
MATSTAT Text 2 Item Status
“AC” – Active
“IN” – Inactive
Table Name : CustomerFile
Description : Records of the customer information.
Primary Key : CUSTNO
Fields Data Type Length Description
CUSTNO Text 5 Customer Account No.
CUSTNAME Text 45 Customer Name
CUSTADDR Text 40 Address
CUSTLIM Currency Customer’s Credit Limit
CUSTBAL Currency Account Balance
CUSTSTAT Text 2 Customer Status
“AC” – Active, “IN” – Inactive
16 – ADO.Net 17
Table Name : ProductMaterialFile
Description : Records of the raw materials needed to produce a product.
Primary Key : PMPRODCODE+PMMATCODE
Fields Data Type Length Description
PMPRODCODE Text 5 Product Code
PMMATCODE Text 5 Material Code
PMQTYNEEDED Integer Quantity Needed to produce a particular product

Table Name : EmployeeFile


Description : Records of the employee information.
Primary Key : EMPNO
Fields Data Type Length Description
EMPNO Text 5 Employee ID
EMPNAME Text 45 Employee Name
EMPADDR Text 40 Address
EMPPOS Text 20 Position
EMPRATE Currency Salary rate
EMPSTAT Text 2 Employee Status
“AC” – Active, “IN” - Inactive
Table Name : SupplierFile
Description : Records of the supplier information.
Primary Key : SUPPNO
Fields Data Type Length Description
SUPPNO Text 5 Supplier Account No.
SUPPNAME Text 45 Name
SUPPADDR Text 40 Address
SUPPSTAT Text 2 Supplier Status
“AC” – Active, “IN” – Inactive

2. User Interfaces & Functions Specifications/Modules


 Bill of Materials Entry
BILL OF MATERIALS
Product Code : Date : ____________
Description : ___________________________ BOM No:
JO No:
Quantity Ordered :

Material Code Material Description Unit of Measure Quantity Needed Total Quantity Needed

Prepared By: ________________________


ID Name SAVE Clear
Approved By: ________________________
ID Name

Input: Date, BOM No (must be unique), JO No (must exists in JO File), Product Code (must exists
in JODetailFile), Prepared by code and Approved by codes (must exists in EmployeeFile)
Output: Upon input of the product code, the program will display its corresponding description and
all the materials needed to produce the specified product with its corresponding quantity needed
and total quantity needed
To Save, store required data into BOMHeaderFile and BOMDetailFile

16 – ADO.Net 18
 Material Release Entry

MATERIAL RELEASE
Product Code : ___________ Date : ____________
Description : ___________________________ MR No:
BOM No:
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Material Code : ___________ Quantity Released :

Material Code Material Description Unit of Measure Total Quantity Quantity Released
Needed

Released By: ___________ ________________________


ID Name SAVE Clear

Requested By: ________________________


ID Name

Input: Date, Input MR No (must be unique),


Input BOM No (must exists in BOM File),
Input a released by code (must exists in EmployeeFile), and a requested by code (must exists in
EmployeeFile), material code (must exists in corresponding BOM) and quantity released (must not be
beyond total quantity needed)
Process: Upon input of the BOM No, corresponding product will be displayed; total quantity needed for
a particular material will also be displayed
To Save, store required data to MaterialReleaseHeaderFile and MaterialReleaseDetailFile. Update BOM
status (if necessary); material quantity on hand; and quantity released of particular material per BOM.

 Purchase Order Entry


PURCHASE ORDER
Supplier Code : ___________ Date : ____________
Name : ___________________________ PO No: __________
Address : ___________________________

-----------------------------------------------------------------------------------------------------------------------------------------------------------
BOM No: Material Code :

BOM No Material Code Material Description Unit of Measure Quantity to Purchase

Summary of Materials to Purchase


Material Code Material Description Unit of Measure Total Quantity
to Purchase

Prepared By: ________________________


ID Name SAVE Clear
Approved By: ________________________
ID Name
Input: Date, PO No (must be unique), Supplier Code (must exists in Supplier File), prepared by code
and approved by code (must exists in EmployeeFile), BOM No (must exists in BOM File) and material
code (must exists in corresponding BOM)
Output: Upon input of the material code, corresponding material information will be displayed; and
quantity to be purchased (the difference of total quantity needed and quantity released) for a
particular material. Then display the summary of materials to purchase.
To Save: store required data to POHeaderFile and PODetailFile. Update BOM status (if necessary); and
quantity purchased of particular material per BOM.
16 – ADO.Net 19

You might also like