Vous êtes sur la page 1sur 18

Introduction – ADO.

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.

Difference between Dataset and DataReader Object


Points to be consider while choosing between the DataSet and DataReader objects.
DataSet object DataReader object
Read/Write access Read-only access
Supports multiple tables from different Supports a single table based on a single SQL
databases query of one database
Disconnected mode Connected mode
Bind to multiple controls Bind to a single control
Forward and backward scanning of data Forward-only scanning of data
Slower access to data Faster access to data
Greater overhead to enable additional features Lightweight object with very little overhead
Supported by Visual Studio .NET tools Must be manually coded

SQLDataReader makes exclusive use of connection


The SQLDataReader object makes exclusive use of its SQLConnection object as long as it is
open. You are not able to execute any other SqlCommand objects on that connection as long
as the SQLDataReader object is open. Therefore, you should always call
SQLDataReader.close() as soon as you are done retrieving data.

Strongly Typed Dataset Object


Strongly typed Dataset object allows you to create early-bound data retrieval expression.
Advantage of Strongly Typed dataset
It is faster than late-bound data retrieval expression.
Its column name is shown in intellisense as you type code.

Improving Performance with Connection Pooling


Opening a connection is a database-intensive task. It can be one of the slowest operations
that you perform in an ASP.NET page. Furthermore, a database has a limited supply of
connections, and each connection requires a certain amount of memory overhead
(approximately 40 kilobytes per connection).
If you plan to have hundreds of users hitting your Web site simultaneously, the process of
opening a database connection for each user can have a severe impact on the performance of
your Web site.
Fortunately, you can safely ignore these bad warnings if you take advantage of connection
pooling. When database connections are pooled, a set of connections is kept open so that they
can be shared among multiple users. When you request a new connection, an active
connection is removed from the pool. When you close the connection, the connection is placed
back in the pool.
Connection pooling is enabled for both OleDb and SqlClient connections by default.To take
advantage of connection pooling, you must be careful to do two things in your ASP.NET pages.
First, you must be careful to use the same exact connection string whenever you open a
database connection. Only those connections opened with the same connection string can be
placed in the same connection pool. For this reason you should place your connection string in
the web.config file and retrieve it from this file whenever you need to open a connection
To take advantage of connection pooling in your ASP.NET pages, you also must be careful to
explicitly close whatever connection you open as quickly as possible. If you do not explicitly
close a connection with the Close() method, the connection is never added back to the
connection pool.

SQL Injection Problem


SQL injection is a strategy for attacking databases.
Example1:
An ASP page asks the user for a name and a password, and then sends the following string to
the database:
SELECT FROM users WHERE username = 'whatever' AND password = 'mypassword'

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.

(B) Can you give a overview of ADO.NET architecture ?


The most important section in ADO.NET architecture is “Data Provider”.Data Provider provides access
to datasource (SQL SERVER , ACCESS ,ORACLE). In short it provides object to achieve functionalities
like opening and closing connection, retrieve data and update data.In the below figure you can see
the four main sections of a data provider :-
√ Connection.
√ Command object (This is the responsible object to use stored procedures)
√ Data Adapter (This object acts as a bridge between datastore and dataset).
√ Datareader (This object reads data from data store in forward only mode).

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)What is difference between dataset and datareader ?


Following are some major differences between dataset and datareader :-
√ DataReader provides forward-only and read-only access to data , while the
DataSet object can hold more than one table (in other words more than one rowset) from the same
data source as well as the relationships between them.
√ Dataset is a disconnected architecture while datareader is connected architecture.
√ Dataset can persists contents while datareader can not persist contents they are forward only.

(I)What are major difference between classic ADO and ADO.NET ?


Following are some major differences between both
√ As in classic ADO we had client and server side cursors they are no more present in ADO.NET.Note
it's a disconnected model so they are no more applicable.
√ Locking is not supported due to disconnected model.
√ All data is persisted in XML as compared to classic ADO where data was persisted in Binary format
also.

(B)What is the use of connection object ?


They are used to connect a data to a Command object.
√ An OleDbConnection object is used with an OLE-DB provider
√ A SqlConnection object uses Tabular Data Services (TDS) with MS SQL Server
(B)What is the use of command objects and what are the methods provided by the
command object ?
They are used to connect connection object to Datareader or dataset. Following are the methods
provided by command object :-
√ ExecuteNonQuery :- Executes the command defined in the CommandText property against the
connection defined in the Connection property for a query that does not return any rows (an UPDATE,
DELETE or INSERT).Returns an Integer indicating the number of rows affected by the query.
√ ExecuteReader :- Executes the command defined in the CommandText property against the
connection defined in the Connection property. Returns a "reader" object that is connected to the
resulting rowset within the database, allowing the rows to be retrieved.
√ ExecuteScalar :- Executes the command defined in the CommandText property against the
connection defined in the Connection property. Returns only a single value (effectively the first
column of the first row of the resulting rowset). Any other returned columns and rows are discarded.
Fast and efficient when only a "singleton" value is required
(B)What is the use of dataadapter ?
These are objects that connect one or more Command objects to a Dataset object. They provide logic
that gets the data from the data store and populates the tables in the DataSet, or pushes the
changes in the DataSet back into the data store.
√ An OleDbDataAdapter object is used with an OLE-DB provider
√ A SqlDataAdapter object uses Tabular Data Services with MS SQL Server.

(B)What are basic methods of Dataadapter ?


There are three most commonly used methods of Dataadapter :-
Fill:- Executes the SelectCommand to fill the DataSet object with data from the data source. Can
also be used to update (refresh) an existing table in a DataSet with changes made to the data in the
original datasource if there is a primary key in the table in the DataSet.
FillSchema:- Uses the SelectCommand to extract just the schema for a table from the data source,
and creates an empty table in the DataSet object with all the corresponding constraints.
Update:- Calls the respective InsertCommand, UpdateCommand, or DeleteCommand for each
inserted, updated,or deleted row in the DataSet so as to update the original data source with the
changes made to the content of the DataSet. This is a little like the UpdateBatch method provided by
the ADO Recordset object, but in the DataSet it can be used to update more than one table.
(B)What is Dataset object?
The DataSet provides the basis for disconnected storage and manipulation of relational data. We fill it
from a data store,work with it while disconnected from that data store, then reconnect and flush
changes back to the data store if required.

(B)What are the various objects in Dataset ?


Dataset has a collection of DataTable object within the Tables collection. Each DataTable object
contains a collection of DataRow objects and a collection of DataColumn objects. There are also
collections for the primary keys,constraints, and default values used in this table which is called as
constraint collection, and the parent and child relationships between the tables.Finally, there is a
DefaultView object for each table. This is used to create a DataView object based on the table, so
that the data can be searched, filtered or otherwise manipulated while displaying the data.
(B) How can we force the connection object to close after my datareader is closed ?
Command method Executereader takes a parameter called as CommandBehavior where in we can
specify saying close connection automatically after the Datareader is close. pobjDataReader =
pobjCommand.ExecuteReader(CommandBehavior.CloseConnection)
(B) I want to force the datareader to return only schema of the datastore rather than
data ?
pobjDataReader = pobjCommand.ExecuteReader(CommandBehavior.SchemaOnly)

(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) Which is the best place to store connectionstring in .NET projects ?


Config files are the best place to store connection strings. If it’s a web-based application “Web.config”
file will be used and if it’s a windows application “App.config” files will be used.

(B) What are steps involved to fill a dataset ?


Twist :- How can we use dataadapter to fill a dataset ?
Private Sub LoadData()
Dim strConnectionString As String
strConnectionString = AppSettings.Item(“ConnectionString”)
Dim objConn As New SqlConnection(strConnectionString)
objConn.Open()
Dim objCommand As New SqlCommand(“Select FirstName from
Employees”)
objCommand.Connection = objConn
Dim objDataAdapter As New SqlDataAdapter()
objDataAdapter.SelectCommand = objCommand
Dim objDataSet As New DataSet
objDataAdapter.Fill(objDataSet)
End Sub

(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”.

(B) What’s basic use of “DataView” ?


“DataView” represent’s a complete table or can be small section of row’s depending on some criteria.
It’s best used for sorting and finding data with in “datatable”. Dataview has the following method’s :-
Find: Take’s a array of value’s and return’s the index of the row.
FindRow: This also takes array of values but returns a collection of “DataRow”. If we want to
manipulate data of “DataTable” object create “DataView” (Using the “DefaultView” we can create
“DataView” object) of the “DataTable” object. and use the following functionalities :-
AddNew
Add’s a new row to the “DataView” object.
Delete
Deletes the specified row from “DataView” object.

(B) What’s difference between “DataSet” and “DataReader” ?


Following are the major difference between “DataSet” and “DataReader” :-
√ “DataSet” is a disconnected architecture , while “DataReader” has live connection while reading
data.So if we want to cache data and pass to a different tier “DataSet” forms the best choice and it
has decent XML support. √ When application needs to access data from more than one table
“DataSet” forms the best choice.
√ If we need to move back while reading record’s , “datareader” does not support this functionality.
√ But one of the biggest drawbacks of DataSet is speed. As “DataSet” carry considerable overhead
because of relations, multiple tables etc speed is slower than “DataReader”. Always try to use
“DataReader” whereever possible, as it’s meant specially for speed performance.
(B) How can we add relation’s between table in a DataSet ?
Dim objRelation As DataRelation
objRelation=New
DataRelation("CustomerAddresses", objDataSet.Tables("Customer").Columns("Custid")
,objDataSet.Tables("Addresses").Columns("Custid_fk"))
objDataSet.Relations.Add(objRelation)

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.

(B) What’s the use of CommandBuilder ?


CommandBuilder builds “Parameter” objects automatically.Below is a simple code which uses
commandbuilder to load its parameter object’s.

Dim pobjCommandBuilder As New OleDbCommandBuilder(pobjDataAdapter)


pobjCommandBuilder.DeriveParameters(pobjCommand)

Be careful while using “DeriveParameters” method as it needs a extra trip to the Datastore which can
be very inefficient.

(B) What’s difference between “Optimistic” and “Pessimistic” locking ?


In pessimistic locking when user wants to update data it locks the record and till then no one can
update data.Other user’s can only view the data when there is pessimistic locking. In optimistic
locking multiple user’s can open the same record for updating, thus increase maximum
concurrency.Record is only locked when updating the record.This is the most preferred way of locking
practically.Now a days browser based application are very common and having pessimistic locking is
not a practical solution.
(A) How many way’s are there to implement locking in ADO.NET ?
Following are the ways to implement locking using ADO.NET :-

√ 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)How can we perform transactions in .NET?


The most common sequence of steps that would be performed while developing a transactional
application is as follows:
√ Open a database connection using the Open method of the connection object.
√ Begin a transaction using the Begin Transaction method of the connection object. This method
provides us with a transaction object that we will use later to commit or rollback the transaction.
Note that changes caused by any queries executed before calling the Begin Transaction method will
be committed to the database immediately after they execute.Set the Transaction property of the
command object to the above mentioned transaction object.
√ Execute the SQL commands using the command object. We may use one or more command
objects for this purpose, as long as the Transaction property of all the objects is set to a valid
transaction object.
√ Commit or roll back the transaction using the Commit or Rollback method of the transaction object.
√ Close the database connection.

(I)What’s difference between Dataset.clone and Dataset. copy ?


Clone: - It only copies structure, does not copy data.
Copy: - Copies both structure and data.

(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.

What is DataRelation object in ADO.NET? How to use a DataRelation


between two columns in ADO.NET?
In order to set the relationship between two or more than two columns, ADO.NET provides the
DataRelation class. When a DataRelation object is created, it assists to enforce some
constraints on the relationships between columns. The constraint may be like a Unique
constraint that ensures that a column will have no duplicate value in the table. A Foreign
Key constraint may be used to enforce Referential Integrity. The Unique property may be
set by setting the Unique property of a DataColumn to True. This may also be done by adding
an instance of the UniqueConstraint class to the DataRelation object. As a part of the foreign
key constraint, we may specify referential integrity rules that are applied at 3 places

1) When a parent record is updated


2) When a parent record is deleted
3) When a change is rejected or accepted.

A DataRelation object permits to establish a parent-child relationship between two or more


tables inside a DataSet object. The easiest way to create a DataRelation between two tables in
a DataSet is to setup a primary key - foreign key relationship between the columns of a table.

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

'Next, Let us create a Data Relationship


ds.Relations.Add("Employee_Salary", ds.Tables("Employees").Columns("EmployeeID"), _
ds.Tables("Salary").Columns("EmployeeID"))
'Display the Employee and Child Salary in the Form
'Say we have a Label in the form
For each RowParent in ds.Tables("Employees").Rows

lblRelation.Text &= RowParent("Emp_Name")


For each RowChild in RowParent.GetChildRows("Employee_Salary")
lblRelation.Text &= "<br/>" & RowChild("Sal_Amount")
Next
Next

Adding a Relationship Between Tables


In a DataSet with multiple DataTable objects, you can use DataRelation objects to relate one
table to another, to navigate through the tables, and to return child or parent rows from a
related table.
The arguments required to create a DataRelation are a name for the DataRelation being
created, and an array of one or more DataColumn references to the columns that serve as the
parent and child columns in the relationship. After you have created a DataRelation, you can
use it to navigate between tables and to retrieve values.
Adding a DataRelation to a DataSet adds, by default, a UniqueConstraint to the parent table
and a ForeignKeyConstraint to the child table. For more information about these default
constraints, see Adding Constraints to a Table.
The following code example creates a DataRelation using two DataTable objects in a
DataSet. Each DataTable contains a column named CustID, which serves as a link between
the two DataTable objects. The example adds a single DataRelation to the Relations
collection of the DataSet. The first argument in the example specifies the name of the
DataRelation being created. The second argument sets the parent DataColumn and the
third argument sets the child DataColumn.

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

Adding Constraints to DataSet


ADO.NET DataSet is can be thought of an in-memory representation of the database. It can
also contain various constraints namely Primary Key, Foreign Key and Unique Key. ADO.NET
allows you to put constraints on DataTables irrespective of the same are present in actual
database or not (However, most of the times you will mimic the database constraints in the
dataset). This article illustrates how to do just that.IntroductionADO.NET DataSet is can be
thought of an in-memory representation of the database. It can also contain various
constraints namely Primary Key, Foreign Key and Unique Key. ADO.NET allows you to put
constraints on DataTables irrespective of the same are present in actual database or not
(However, most of the times you will mimic the database constraints in the dataset). This
article illustrates how to do just that. Sample Database For our sample I will use an Access
database with following tables : Customers : CustID, CustName Orders : OrdId, CustId,
OrdAmt The tables contain only the fields that are relevant to our code. In reality you might
have many other fields. Namespaces Involved We will be using following namespaces :
System.Data System.Data.OleDbFilling up of the dataset Before starting any of our core
examples we need to fill the DataSet with desired DataTables. Following code does this work
Listing 1.1

{
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");

DataColumn[] pk = new DataColumn[2];

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);

Da.SelecteCommand.CommandText = "select * from orders";


da.Fill(ds, "orders");

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);

Data.UniqueConstraint uc = new Data.UniqueConstraint(ds.Tables(0).Columns(1));


ds.Tables(0).Constraints.Add(uc);
}

Dim connstr As String


connstr = "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=c:db.mdb;Mode=
ReadWrite"
Dim cnn As OleDbConnection
Dim da As OleDbDataAdapter
Dim ds As New DataSet()
cnn = New OleDbConnection(connstr)
da = New OleDbDataAdapter("select * from customers", cnn)
da.Fill(ds, "customers")

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.

Dim pk(1) As DataColumn

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"

Da.SelecteCommand.CommandText="select * from orders"


da.Fill(ds, "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.

Transaction Management in ADO.NET


A Database is a software system that defines a collection of predefined operations. Mainly it
includes following operations

• Efficient management of large amount of persistent data in a persistent storage


(database)
• Transaction Management which includes Concurrency Control, Atomicity and backup
recovery procedure
• A DataModel which gives a separate level of abstraction
In this article I am concentrating of transaction management that is Concurrency Control in
.NET environment.

A transaction is an abstract unit of concurrent computation that execute automatically. The


effect of transaction does not interfere with other transactions that access the same data. Also
a transaction happens with all of its effects (In this case you will commit the changes) or it
doesn't happen none of its effects (In this case you will rollback the changes).

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.

In .NET environment we can define transaction boundary by Transaction object.

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

string connectionString = ".........";


SqlConnection myConnection = new SqlConnection(connectionString);
myConnection.Open();
// Start transaction.
SqlTransaction myTransaction = myConnection.BeginTransaction();
// Assign command in the current transaction.
SqlCommand myCommand = new SqlCommand();
myCommand.Transaction = myTransaction;
try
{
.........................
Database operations
........................
myTransaction.Commit();
Console.WriteLine("Records are modified in the database.");
}
catch(Exception e)
{
myTransaction.Rollback();
Console.WriteLine(e.ToString());
Console.WriteLine("Neither record was written to database.");
}
finally
{
myConnection.Close();
}

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

string connectionString = ".......................";


SqlConnection myConnection = new SqlConnection(connectionString);
SqlDataAdapter myAdaptor = new SqlDataAdapter("SELECT Name, City FROM Employee
ORDER BY EmpID", myConnection);
// Add the RowUpdated event handler.
myAdaptor.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
DataSet supplierData = new DataSet();
myAdaptor.Fill(supplierData, "Supplier");
// Modify the DataSet contents.
..........................................
.........................................
myAdaptor.Update(supplierData, "Supplier");
foreach (DataRow myRow in supplierData.Tables["Supplier"].Rows)
{
if (myRow.HasErrors)
Console.WriteLine(myRow[0] + "\n" + myRow.RowError);
}
protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
{
if (args.RecordsAffected == 0)
{
args.Row.RowError = "Optimistic Concurrency Violation Encountered";
args.Status = UpdateStatus.SkipCurrentRow;
}
}

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.

A transaction is started by calling the OdbcConnection.BeginTransaction(isolationlevel) that


returns an instance of OdbcTransaction. The different isolation levels are available in
System.Data.IsolationLevel. For example, System.Data.IsolationLevel.Serializable can be
used.

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();

//Start the transaction


OdbcTransaction trans =
con.BeginTransaction(System.Data.IsolationLevel.Serializable);
OdbcCommand command = new OdbcCommand(sql, con, trans);

//An alternative but equivalent approach


OdbcCommand command2= new OdbcCommand(sql2, con);
command2.Transaction=trans;

//Execute and commit


command.ExecuteNonQuery();
command2.ExecuteNonQuery();
trans.Commit();
con.Close();
}
catch(OdbcException oe)
{
//Show errors
try
{
trans.Rollback();
}
catch(OdbcException oe2)
{
//Show errors
}
}

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.

What is Diffgram in ADO.NET? When do we use Diffgram?


A DiffGram is an XML format. It is used to identify current and original versions of data
elements. A DataSet may use a DiffGram format to load and persist the contents, and further
to serialize its contents for porting across a network connection. Whenever a DataSet is
written as a DiffGram, the DataSet populates the DiffGram with all the important information
to accurately recreate the contents. Note that schema of the DataSet is not recreated. This
includes column values from both the Current and the Original row versions, row error
information, and row order.

What is a Typed Dataset in ADO.NET? Why do we use a Typed DataSet?


What is the difference between a Typed and an UnTyped DataSet?
Typed DataSet - When a created DataSet derives from the DataSet class, that applies the
information contained in the XSD to create a Typed class, this DataSet is said to be a Typed
Dataset. Information from the schema whic comprises the tables, columns, and rows is
created and compiled to a new DataSet derived from the XSD. The Typed DataSet class
features all functionality of the DataSet class. This may be used with methods that take an
instance of the DataSet class as a parameter.
Note that an UnTyped DataSet does not have any schema. It is exposed simply as a mere
collection.
How to create a Typed DataSet? -
Write click your project in the Solution Explorer.
Click Add New Item.
Select DataSet.

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.