ADO NET Tutorial - 16
ADO NET Tutorial - 16
NET
ADO.NET is a model intended primarily for disconnected data access. ADO.NET provides two
strategies for you to work with this model.
1. Store data in a dataset, which is an in-memory cache of records you can work with
while disconnected from the data source. To use a dataset, you use a data adapter to
fill it from the data source. You then work with the data in the dataset.
2. Perform operations directly against the database. In this strategy, you use a data
command object. You can then open a connection, execute the command to perform
the operation, and then close the connection.
Each strategy has its own advantages. So you should choose a strategy based on what your
data-access requirements are.
Advantages of Storing Data in Datasets
The advantages of the dataset model are:
• Data exchange with other applications - A dataset provides a powerful way to
exchange with other components of your application and with other applications.
• Moving data between tiers in a distributed application - By keeping data in a dataset,
you can easily move it between the presentation tier, business tier, and data tier of
your applications.
• Working with multiple tables - A dataset can contain multiple tables. You can work with
the tables individually or navigate between them as parent-child tables.
• Maintaining records for reuse - A dataset allows you to work with the same records
repeatedly without re-querying the database.
• Manipulating data from multiple sources - The tables in a dataset can represent data
from many different sources. Once the data is in the dataset, you can manipulate it
and relate it as if it had come from a single source.
• Data binding - If you are working with forms, it is usually easier to bind controls to
data in a dataset than it is to programmatically load data values into the control after
executing a command.
• Ease of programming - When you work with a dataset, you can generate a class file
that represents its structure as objects. This makes it easier, clearer, and less error-
prone to program with, and is supported by Visual Studio tools such as IntelliSense,
the Data Adapter Configuration wizard, and so on.
Advantage of performing Database Operations Directly
The advantages of performing database operations directly:
• More control over execution - By using commands, you get more direct control over
how and when an SQL statement or stored procedure is executed and what becomes
of the results or return values.
• Less overhead - By reading and writing directly in the database, you can bypass
storing data in a dataset. Because the dataset requires memory, you can reduce some
overhead in your application. This is especially true in situations where you intend to
use the data only once. In that case, creating and filling a dataset might be an
unnecessary step in displaying the data.
• Extra functionality - There are some operations, such as executing DDL commands,
that you can run only by executing data commands.
• Less programming in some instances - In a few instances, particularly Web
applications, there is some extra programming required to save the state of a dataset.
If you use a data reader to read directly from the database, you avoid the extra steps
required to manage the dataset.
Recommendations for Accessing Data
The following sections provide recommendations for which data-access strategy to use with
specific types of applications.
Web Forms
Use data commands in general; use a data reader to fetch data. Because Web Forms pages
and their controls and components are recreated each time the page makes a round trip, it
often is not efficient to create and fill a dataset each time, unless you also intend to cache it
between round trips.
Use datasets under the following circumstances:
• You need to perform extensive processing with each record you get from the database.
• You want to work with multiple separate tables or tables from different data sources.
• If your data processing involves interdependent records.
• If you want to perform XML operations such as XSLT transformations on the data.
• You are exchanging data with another application or a component such as an XML Web
service.
• If you prefer the ease of programming provided by datasets.
XML Web Services
XML Web services are ASP.NET Web applications, and therefore use the same model as Web
Forms pages: the XML Web service is created and discarded each time a call is made to it. This
suggests that the data-access model for an XML Web service is largely the same as it is for
Web Forms. However, XML Web services are often middle-tier objects, and an important part
of their purpose is often to exchange data with other applications across the Web.
Use a dataset if:
• Your XML Web service sends and receives data.
• For any of the reasons listed above for Web Forms.
Use a data command if:
• The XML Web service is performing a non-query operation, such as a DDL command.
• The XML Web service is retrieving a scalar value.
• The XML Web service is calling a stored procedure to execute logic within the
database.
Windows Forms
In general, in a Windows Form, use a dataset. Windows Forms are typically used on rich
clients where the form is not created and discarded with each user operation, as with Web
Forms. Windows Forms applications also traditionally offer data-access scenarios that benefit
from maintaining a cache of records, such as displaying records one by one in the form.
Use a dataset if:
• You are using the Windows Forms data-binding architecture, which is specifically
designed to work with datasets.
• You are working with the same records repeatedly, such as allowing a user to navigate
between records.
• For any of the other reasons listed under Web Forms above.
Use a data command if:
• You are performing a non-query operation, such as a DDL command.
• You are getting a scalar value from the database
• You are getting read-only data to display in a form — for example, creating a report.
Stated differently, if there is no need to keep the data available after accessing it, use
a data command.
What is ADO.net
ADO.net is data access architecture for the Microsoft .NET Framework.
Difference between ADO and ADO.net
• ADO used connected data usage, while ADO.net used disconnected data environment.
• ADO used OLE DB to access data and is COM-based, while ADO.net uses XML as the
format for transmitting data to and from your database and web application.
• In ADO, Record set, is like a single table or query result, while in ADO.net Dataset, can
contain multiple tables from any data source.
• In ADO, it is sometime problematic because firewall prohibits many types of request,
while in ADO.net there is no such problem because XML is completely firewall-proof
Difference between ADO.net Dataset and ADO Recordset
• A DataSet can represent an entire relational database in memory, complete with
tables, relations, and views.
A DataSet is designed to work without any continuing connection to the original data
source.
Data in a DataSet is bulk-loaded, rather than being loaded on demand.
There's no concept of cursor types in a DataSet.
DataSets have no current record pointer You can use For Each loops to move through
the data.
You can store many edits in a DataSet, and write them to the original data source in a
single operation.
Though the DataSet is universal, other objects in ADO.NET come in different versions
for different data sources.
ADO.net Terms
• Data Source: It can be a database, text file, excel spread sheet or an XML file.
• Data Provider: A set of libraries that is used to communicate with data source. Eg:
SQL data provider for SQL, Oracle data provider for Oracle, OLE DB data provider for
access, excel or mysql.
• SQL Connection: It establishes connection.
• SQL Command: It allows to manipulate database by executing stored procedure or
sql statements.
• SQL DataReader: It provides a forward-only, read-only, connected recordset.
• DataSet: dataset is a disconnected, in-memory representation of data. It can
contain multiple data table from different database.
• SQL DataAdapter: It populates dataset from data source. It contains a reference to
the connection object and opens and closes the connection automatically when reading
from or writing to the database.
• DataView: It provides a means to filter and sort data within a data table.
It seems safe, but it isn't. A user might enter something like this as her user name:
' OR 1>0 --
When this is plugged into the SQL statement, the result looks like this:
SELECT FROM users WHERE username = '' OR 1>0 -- AND password = ''
This injection comments out the password portion of the statement. It results in a list of all the
names in the users table, so any user could get into your system.
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
The easiest way to prevent this sort of injection is to parse the SQL string and remove any
occurrences of "--" before passing the statement. <!--[if !supportEmptyParas]--> <!--
[endif]-->
Example 2:
You also have to beware of injections that contain semicolons because semicolons delimit SQL
statements. Think about the implications of a user name like this:
' OR 1>0 ; DELETE Customers ; --
There are numerous ways a malicious user might penetrate your system using SQL injection
and various defenses, but the simplest approach is to avoid dynamic SQL. Instead, use stored
procedures everywhere. Thanks to the way SQL passes parameters, injections such as those
above will produce errors, and the stored procedure will not execute.
ADO.NET
(B)What is the namespace in which .NET has the data functionality classes ?
Following are the namespaces provided by .NET for data management :-
System.data This contains the basic objects used for accessing and storing relational data, such as
DataSet,DataTable, and DataRelation. Each of these is independent of the type of data source and the
way we connect to it.
System.Data.OleDB
Contains the objects that we use to connect to a data source via an OLE-DB provider, such as
OleDbConnection, OleDbCommand, etc. These objects inherit from the common base classes, and so
have the same properties, methods, and events as the SqlClient equivalents.
System.Data.SqlClient:
This Contains the objects that we use to connect to a data source via the Tabular Data Stream (TDS)
interface of Microsoft SQL Server (only). This can generally provide better performance as it removes
some of the intermediate layers required by an OLE-DB connection.
System.XML
This Contains the basic objects required to create, read, store, write, and manipulate XML documents
according to W3C recommendations.
Dataset object represents disconnected and cached data.If you see the diagram it is not in direct
connection with the data store (SQL SERVER , ORACLE etc) rather it talks with Data adapter , who is
responsible for filling the dataset.Dataset can have one or more Datatable and relations.
(B)What are the two fundamental objects in ADO.NET ?
Datareader and Dataset are the two fundamental objects in ADO.NET.
(B) How can we fine tune the command object when we are expecting a single row or a
single value ?
Again CommandBehaviour enumeration provides two values SingleResult and SingleRow. If you are
expecting a single value then pass “CommandBehaviour.SingleResult” and the query is optimized
accordingly , if you are expecting single row then pass “CommandBehaviour.SingleRow” and query is
optimized according to single row.
(B)What are the various methods provided by the dataset object to generate XML?
Note:- XML is one of the most important leap between classic ADO and ADO.NET. So this question is
normally asked more generally how can we convert any data to XML format.Best answer is convert in
to dataset and use the below methods.
√ ReadXML: Read’s a XML document in to Dataset.
√ GetXML: This is function’s which return’s a string containing XML document.
√ WriteXML: This write’s a XML data to disk.
(B) How can we save all data from dataset ?
Dataset has “AcceptChanges” method which commits all the changes since last time “Acceptchanges”
has been executed.
(B) How can we check that some changes have been made to dataset since it was loaded ?
Twist :- How can we cancel all changes done in dataset ? , How do we get values which are changed
in a dataset ?
For tracking down changes Dataset has two methods which comes as rescue “GetChanges “and
“HasChanges”.
GetChanges
Return’s dataset which are changed since it was loaded or since Acceptchanges was executed.
HasChanges
This property indicate’s has any change’s been made since the dataset was loaded or acceptchanges
method was executed. If we want to revert or abandon all change’s since the dataset was loaded use
“RejectChanges”.
(B) How can we add/remove row’s in “DataTable” object of “DataSet” ?
“Datatable” provides “NewRow” method to add new row to “DataTable”.”DataTable” has
“DataRowCollection” object which has all rows in a “DataTable” object.Following are the methods
provided by “DataRowCollection” object :-
Add: Add’s a new row in DataTable
Remove: Remove’s a “DataRow” object from “DataTable”
RemoveAt: Remove’s a “DataRow” object from “DataTable” depending on index position of the
“DataTable”.
Relation’s can be added between “DataTable” object’s using the “DataRelation” object.Above sample
code is trying to build a relationship between “Customer” and “Addresses” “Datatable” using
“CustomerAddresses” “DataRelation” object.
Be careful while using “DeriveParameters” method as it needs a extra trip to the Datastore which can
be very inefficient.
√ When we call “Update” method of DataAdapter it handles locking internally.If the DataSet values
are mot matching with current data in Database it raises Concurrency exception error.We can easily
trap this error using Try. Catch block and raise appropriate error message to the user.
√ Define a Datetime stamp field in the table.When actually you are firing the UPDATE SQL
statements compare the current timestamp with one existing in the database.Below is a sample SQL
which checks for timestamp before updating and any mismatch in timestamp it will not update the
records.This is the best practice used by industries for locking.
Update table1 set field1=@test where LastTimeStamp=@CurrentTimeStamp
√ Check for original values stored in SQL SERVER and actual changed values.In stored procedure
check before updating that the old data is same as the current.Example in the below shown SQL
before updating field1 we check that is the old field1 value same.If not then some one else has
updated and necessary action has to be taken.
Update table1 set field1=@test where field1 = @oldfield1value
Locking can be handled at ADO.NET side or at SQL SERVER side i.e. in stored procedures.for more
details of how to implementing locking in SQL SERVER read “What are different locks in SQL
SERVER ?” in SQL SERVER chapter.
(A)Can you explain the difference between an ADO.NET Dataset and an ADO Recordset?
There two main basic differences between recordset and dataset :-
√ With dataset you an retrieve data from two databases like oracle and sql server and merge them in
one dataset , with recordset this is not possible
√ All representation of Dataset is using XML while recordset uses COM.
√ Recordset can not be transmitted on HTTP while Dataset can be.
See code example below, where a DataRelation has been setup between the Employee table
and the Salary table...
'Code Below in VB.NET
Dim Conn As SqlConnection
Dim da As SqlDataAdapter
Dim ds As DataSet
Dim RowParent As DataRow
Dim RowChild As DataRow
Conn = New _
SqlConnection(ConfigurationSettings.Appsettings("SomeConnectionStringWrittenInWeb.Config
"))
da = New SqlDataAdapter("SELECT * FROM Employees", Conn)
ds = New DataSet()
Try
Conn.Open()
da.Fill( ds,"Employees")
da.SelectCommand = New SqlCommand("SELECT * FROM Salary", Conn)
da.Fill(ds, "Salary")
Catch ex As SqlException
Response.Write(ex.ToString())
Finally
Conn.Dispose()
End Try
C#
customerOrders.Relations.Add("CustOrders",
customerOrders.Tables["Customers"].Columns["CustID"],
customerOrders.Tables["Orders"].Columns["CustID"]);
A DataRelation also has a Nested property which, when set to true, causes the rows from
the child table to be nested within the associated row from the parent table when written as
XML elements using WriteXml
{
string connstr;
connstr = "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data
Source=c:db.mdb;Mode= ReadWrite";
OleDbConnection cnn;
OleDbDataAdapter da;
DataSet ds = new DataSet();
cnn = new OleDbConnection(connstr);
da = new OleDbDataAdapter("select * from customers", cnn);
da.Fill(ds, "customers");
pk(0) = ds.Tables(0).Columns("custid");
ds.Tables("customers").PrimaryKey = pk;
DataRow r;
r = ds.Tables("customers").NewRow();
r.Item("custid") = "CUST1";
r.Item("custname") = "MyCustomer1";
ds.Tables("customers").Rows.Add(r);
ForeignKeyConstraint fk;
fk = new ForeignKeyConstraint("fk", ds.Tables(0).Columns("custid"),
ds.Tables(1).Columns("custid"));
fk.DeleteRule = Rule.Cascade;
fk.UpdateRule = Rule.Cascade;
ds.Tables(1).Constraints.Add(fk);
ds.EnforceConstraints = true;
DataRow r;
r = ds.Tables(1).NewRow;
r.Item("OrdId") = "New_OrdID";
r.Item("custid") = "CustID_not_available";
ds.Tables(1).Rows.Add(r);
Here we populated the dataset with Customers table. Primary Key Constraint Now, we will add
primary key constraint to the customers table from our dataset.
pk(0) = ds.Tables(0).Columns("custid")
ds.Tables("customers").PrimaryKey = pk
We have declared an array of DataColumn object. Our customers table has only one field that
acts as primary field i.e. CustID hence we declared array to hold only one element. In case
you have more fields simple increase size of the array. Next, we assigned which column to be
treated as primary key. Finally, we set PrimaryKey property of the DataTable object. In order
to test our code simply try inserting duplicate values in the data table. You may use code
similar to following fragment :
Dim r As DataRow
r = ds.Tables("customers").NewRow()
r.Item("custid") = "CUST1"
r.Item("custname") = "MyCustomer1"
ds.Tables("customers").Rows.Add(r)
Foreign Key Constraints Before proceeding further we will add some code to the listing 1.1 that
fills the dataset with another table "Orders"
In our example database the two tables are related on field CustID. CustID is foreign key in
Orders table. Add following code that establishes foreign key constraints between them.
Dim fk As ForeignKeyConstraint
fk = New ForeignKeyConstraint("fk", ds.Tables(0).Columns("custid"),
ds.Tables(1).Columns("custid"))
fk.DeleteRule = Rule.Cascade
fk.UpdateRule = Rule.Cascade
ds.Tables(1).Constraints.Add(fk)
ds.EnforceConstraints = True
Here we have created an object of ForeignKeyConstraint with name "fk" that sets foreign key
of orders table. Next, we have also set rulaes for cascade update and deletes. Finally we have
added this constraint to the constraints collection of the datatable. To test our code add some
record that violates the constraint
Dim r As DataRow
r = ds.Tables(1).NewRow
r.Item("OrdId") = "New_OrdID"
r.Item("custid") = "CustID_not_available"
ds.Tables(1).Rows.Add(r)
You will get error indicating that the dataset is being tested for foreign key constraints. Unique
Constraints This final example shows how to add unique key constraints to the datatable.
Dim uc As New Data.UniqueConstraint(ds.Tables(0).Columns(1))
ds.Tables(0).Constraints.Add(uc)
Here, we added unique constraint for Customer name column of the customers table via
UniqueConstraint class. As before you can check that the constraint is working by adding some
duplicate values in the customer name field.
In the transaction control we generally define code in between a block where we perform
mission critical operation. If all operations get completed successfully then that part is
committed in the database otherwise what ever modification you might have done during the
process is roll backed from the database so that it never affect other user's operations.
If you are using SqlClient (namespace System.Data.SqlClient) Managed Provider you can
SqlTransaction object.
If you are using Oledb (namespace System.Data.Oledb) Managed Provider you can
OledbTransaction object.
If you are using Odbc (namespace Microsoft.Data.Odbc) Managed Provider you can
OdbcTransaction object
Let us discuss a simple block of transaction control. In this block I am taking SqlClient
Managed Provider
In Above Block
BeginTransaction method of the Connection object to mark the start of the transaction,
which returns a Transaction object.
The newly created transaction object is assigned to CommandObject so that what ever the
database operation is performed by that commandObject can be managed by Transaction
Object.
If anything gets wrong the Transaction object will raise an Exception otherwise it will run
through a normal process.
Call the Commit method of the Transaction object to complete the transaction if everything
works fine otherwise call the Rollback method to cancel the transaction.
Concurrency Control
While doing certain modification in the database some time you need to lock the data so that
no one can else perform modification in that data. There are two commonly known approaches
for locking database they are optimistic locking and pessimistic locking.
Both these approaches are used to maintain concurrency in the database. Pessimistic
concurrency locking is done at rows of the data source to prevent users from modifying data in
a way that affects other users. In a pessimistic model, when a user performs an action that
causes a lock to be applied, no one else can perform action until unless owner releases that
lock. But this is not case with optimistic currency model. In optimistic concurrency model user
does not lock row while reading it, while user only locks the row while updating changes to the
database.
In .NET we use DataSet object for modifying changes in the database. The DataSet object
uses optimistic concurrency model with the help of DataAdaptor. The DataSet object is
designed to encourage the use of optimistic concurrency for long-running activities such as
when you are working in distributed environment.
In real time execution DataSet maintains the versions of data that means if anyone modify
any data in the DataSet then it get maintain in the dataset as old version and new version.
While updating modified data in the database if any of the concurrency conflict occur it raises
Exception, which sets DataRow's HasError Boolean value. This we can easily handle with
DataAdaptor event and with our own programming logic.
Here I am giving a simple code sample, which explains you how can you manage, concurrency
control in .NET environment
Explanation of Code:
In this code you have SqlDataAdaptor, which is retrieving supplier record from a database and
filling it in a DataSet supplierData. After that you have performed certain modification in that
data via DataSet. After modifying data we have used dataAdaptor to update that changes in
the database.
So what is new in this code? You might have noticed that in this code we have defined a event
handler on dataAdaptor's RowUpdated event. This event will be fired when row is updated in
the database and in that event handler mechanism we can define different status to argument
so that further action can be take place.
In the main code I have specified code to write all those rows in which error has occurred
during modification.
There are different type of status is available for SqlRowUpdatedEventArgs by which you can
direct the updating process. Those status are as follows
Status Description
Continue - Continue the update operation.
ErrorsOccurred - Abort the update operation and throw an exception.
SkipCurrentRow - Ignore the current row and continue the update operation.
SkipAllRemainingRows - Abort the update operation but do not throw an exception.
Transactions
So far we haven't used explicit transaction handling and therefore auto-commit has been
enabled. This means that all commands have been executed in their own transaction, and that
might not be what we want. Fortunately, transaction handling is quite easy and
straightforward in ADO.NET using the OdbcTransaction class.
All SQL statements that we want to be part of the transaction have to be associated with the
transaction object. This can be done by passing the transaction through the constructor of the
OdbcCommand or by setting the Transaction property. When we are done with the work we
simply call OdbcTransaction.Commit() or OdbcTransaction.Rollback() to commit or roll back
the transaction.
try
{
OdbcConnection con = new OdbcConnection("...");
con.Open();
As you can see, we simply commit when we are done and if an OdbcException is thrown we do
a roll back. Note that the trans.RollBack() method can throw an OdbcEvent itself and is
therefore surrounded by its own try-catch.
This adds a new XSD to the project. The schema created may be viewed as an XML. When this
xsd file is compiled, two files are created by Visual Studio. The first file that contains the .vb or
.cs extension contains the information about the proxy class. This class contains methods &
properties that are required to access the database data. The second file has an extension xsx
and this contains information about the layout of the XSD.