You are on page 1of 30

ADO.

NET Architecture
ADO.NET is a data access technology from Microsoft .Net Framework , which provides
commnication !etween relational and non"relational systems throgh a common set of
components . ADO.NET consist of a set of O!#ects that e$pose data access services to the
.NET environment. ADO.NET is !ilt for disconnected architectre , so it ena!les trly
disconnected Data Access and Data Maniplation throgh its Dataset O!#ect, which is
completely independent from the Data %orce.
The two key components of ADO.NET are Data
&roviders and Data%et . The .Net Framework
incldes mainly three Data &roviders for
ADO.NET. They are the Microsoft %'( %erver
Data &rovider, O(ED) Data &rovider and OD)*
Data &rovider. %'( %erver ses the %+l*onnection
o!#ect , O(ED) ses the OleD!*onnection O!#ect
and OD)* ses Od!c*onnection O!#ect
respectively.
The for O!#ects from the .Net Framework provide the fnctionality of Data &roviders in the
ADO.NET. They are *onnection O!#ect, *ommand O!#ect , Data,eader O!#ect and
DataAdapter O!#ect. The *onnection O!#ect provides physical connection to the Data
%orce. The *ommand O!#ect ses to perform %'( statement or stored procedre to !e
e$ected at the Data %orce. The Data,eader O!#ect is a stream"!ased , forward"only, read"
only retrieval of +ery reslts from the Data %orce, which do not pdate the data. Finally the
DataAdapter O!#ect , which poplate a Dataset O!#ect with reslts from a Data %orce .
Data%et provides a disconnected representation of reslt sets from the Data %orce, and it is
completely independent from the Data %orce. Data%et provides mch greater fle$i!ility
when dealing with related ,eslt %ets. Data%et consists of a collection of DataTa!le o!#ects
that yo can relate to each other with Data,elation o!#ects. The DataTa!le contains a
collection of Data,ow and Data*olmn O!#ect which contains Data. The DataAdapter
O!#ect provides a !ridge !etween the Data%et and the Data %orce.
ADO.NET ConnectionString
*onnection %tring is a normal %tring representation which contains Data!ase connection
information to esta!lish the connection !etween Dat!ase and the Application. The
*onnection %tring incldes parameters sch as the name of the driver, %erver name and
Data!ase name , as well as secrity information sch as ser name and password. Data
providers se a connection string containing a collection of parameters to esta!lish the
connection with the data!ase.
The .NET Framework provides mainly three data providers- Microsoft %'( %erver, O(ED)
and OD)*. .ere yo can see how to make connection string to these ADO.NET Data
&roviders.
Microsoft SQL Server Connection String
connetionString ="Data Source = ServerName; Initial Catalog =
Databasename; User ID = UserName; Password=Password"
OLEDB Data Provider Connection String
connetionString = "Provider = Microsoft.et.!"#D$.%.&; Data Source =
'ourdatabasename.mdb;"
ODBC Connection String
connetionString = "Driver = (Microsoft )ccess Driver *+.mdb,-; D$. =
'ourdatabasename.mdb;"
Note - /o have to provide the necessary informations to the *onnection %tring attri!tes.
0n the following section yo can see how to these ADO.NET Data &roviders esta!lish
connection to the Data!se in detail.
%'( %erver *onnection
O(ED) *onnection
OD)* *onnection
Advantages of ADO.Net over ADO
ADO stands for Active1 Data O!#ects and it relies on *OM whereas ADO.NET relies on
managed providers defined !y the .NET *(, 2*ommon (angage ,ntime3. ADO.NET
provides consistent access to data sorces sch as %'( %erver, as well as data sorces
e$posed throgh O(E D) and 1M(. 4hile there are similarities !etween ADO and
ADO.NET, the way they operate and their fondations are +ite different. The following are
some Advantages of ADO.Net over ADO in !asic level.
A ma#or difference in creating connections with ADO and ADO.NET is that ADO fits all
connections to all types of data sorces into a single *onnection o!#ect. ADO.NET can have
separate O!#ects that represent connections to different data sorces. 0n ADO.NET yo can
create mltiple data provider namespaces to connect specifically with a particlar data
sorce, making access faster and more efficient and allowing each namespace to e$ploit the
featres of its targeted data provider.
Dim connection As SqlConnection
connection = New SqlConnection("connetionString")
Dim connection As OleDbConnection
connection = New OleDbConnection("connetionString")
ADO allows yo to create client side crsors only whereas ADO.NET gives yo the choice of
either sing client side or server side crsors.
ADO.NET introdces a new way of getting a single vale from a +ery5s reslts when yo
e$pect only one row and one colmn to retrn. The ADO.NET command o!#ect has an
E$ecte%calar method which retrns the first row and colmn5s vale from its associated
+ery.
ADO.Net dataset represents in memory representation of a data!ase. ADO recordsets is
merely a set of rows retrieved from a data sorce.
ADO recordsets can hold data from one data sorce at a time. ADO.Net datasets can hold
data from varios sorces and integrate the data and write it !ack to one or several data
sorces.
The ADO.NET Framework spports two models of Data Access Architectre, *onnection
Oriented Data Access Architectre and Disconnected Data Access Architectre.
0n the case of Data *ommnication , ADO o!#ects commnicate in !inary mode while
ADO.NET ses 1M( for passing the data.
ADO.NET Data Providers
The .Net Framework incldes mainly three Data &roviders for ADO.NET. They are the
Microsoft %'( %erver Data &rovider , O(ED) Data &rovider and OD)* Data provider. /o
can see from the following links how these Data &roviders making connection to the
specified data %orces.
%'( %erver *onnection
O(ED) *onnection
OD)* *onnection
The for O!#ects from the .Net Framework provide the fnctionality of Data &roviders in
ADO.NET. They are *onnection O!#ect, *ommand O!#ect , Data,eader O!#ect and
DataAdapter O!#ect. The following link shows in details a!ot these O!#ects.
*onnection
*ommand
Data,eader
DataAdapter
ADO.NET Command
The *ommand O!#ect in ADO.NET e$ectes %'( statements and %tored &rocedres against
the data sorce specified in the *onnection O!#ect. The *ommand O!#ect re+ired an
instance of a *onnection O!#ect for e$ecting the %'( statements. That is, for retrieving data
or e$ecte an %'( statement against a Data %orce , yo have to create a *onnection O!#ect
and open a connection to the Data %orce, and assign the open connection to the connection
property of the *ommand O!#ect. 4hen the *ommand O!#ect retrn reslt set , a Data
,eader is sed to retrieve the reslt set.
The *ommand O!#ect has a property called *ommandTe$t, which contains a %tring vale
that represents the command that will !e e$ected in the Data %orce. 4hen the
*ommandType property is set to %tored&rocedre, the *ommandTe$t property shold !e set
to the name of the stored procedre.
*lick the following links to see some important !ilt in methods ses in the *ommand O!#ect
to e$ecte the %'( statements.
E$ecteNon'ery
E$ecte,eader
E$ecte%calar
ADO.NET EecuteNonQuer! in S"#Command O$%ect
E$ecteNon'ery23 is one of the most fre+ently sed method in %+l*ommand O!#ect and is
sed for e$ecting statements that do not retrn reslt set. E$ecteNon'ery23 performs Data
Definition tasks as well as Data Maniplation tasks also. The Data Definition tasks like
creating %tored &rocedres and 6iews perform !y E$ecteNon'ery23 . Also Data
Maniplation tasks like 0nsert , 7pdate and Delete perform !y E$ecteNon'ery23.
ADO.NET Eecute&eader in S"#Command O$%ect
E$ecte,eader23 in %+l*ommand O!#ect send the %'( statements to *onnection O!#ect and
poplate a %+lData,eader O!#ect !ased on the %'( statement. 4hen the E$ecte,eader
method in %+l*ommand O!#ect e$ecte , it instantiate a %+l*lient.%+lData,eader O!#ect.
The %+lData,eader O!#ect is a stream"!ased , forward"only, read"only retrieval of +ery
reslts from the Data %orce, which do not pdate the data. The %+lData,eader cannot !e
created directly from code, they created only !y calling the E$ecte,eader method of a
*ommand O!#ect.
ADO.NET EecuteSca#ar in S"#Command O$%ect
E$ecte%calar23 in %+l*ommand O!#ect is sed for get a single vale from Data!ase after its
e$ection. 0t e$ectes %'( statements or %tored &rocedre and retrned a scalar vale on first
colmn of first row in the ,eslt %et. 0f the ,eslt %et contains more than one colmns or
rows , it takes only the first colmn of first row, all other vales will ignore. 0f the ,eslt %et
is empty it will retrn a Nll reference.
0t is very sefl to se with aggregate fnctions like *ont283 or %m23 etc. 4hen compare to
E$ecte,eader23 , E$ecte%calar23 ses fewer %ystem resorces.
'hat is DataAda(ter
DataAdapter is a part of the ADO.NET Data &rovider. DataAdapter provides the
commnication !etween the Dataset and the Datasorce. 4e can se the DataAdapter in
com!ination with the Data%et O!#ect. That is these two o!#ects com!ine to ena!le !oth data
access and data maniplation capa!ilities.
The DataAdapter can perform %elect , 0nsert , 7pdate and Delete %'( operations in the Data
%orce. The 0nsert , 7pdate and Delete %'( operations , we are sing the contination of the
%elect command perform !y the DataAdapter. That is the DataAdapter ses the %elect
statements to fill a Data%et and se the other three %'( commands 20nsert, 7pdate, delete3 to
transmit changes !ack to the Data!ase. From the following links descri!e how to se
%+lDataAdapter and OleD!DataAdapter in detail.
%+lDataAdapter
OleD!DataAdapter
ADO.NET O$%ects
ADO.NET includes many objects you can use to work with data. This section
introduces some of the primary objects you will use. Over the course of this
tutorial, youll be e!posed to many more ADO.NET objects from the perspective of
how they are used in a particular lesson. The objects below are the ones you must
know. "earnin# about them will #ive you an idea of the types of thin#s you can do
with data when usin# ADO.NET.
The SqlConnection Object
To interact with a database, you must have a
connection to it. The connection helps identify the
database server, the database name, user name,
password, and other parameters that are re$uired for
connectin# to the data base. A connection object is
used by command objects so they will know which
database to e!ecute the command on.
The SqlCommand Object
The process of interactin# with a database means that you
must specify the actions you want to occur. This is done with
a command object. %ou use a command object to send &'"
statements to the database. A command object uses a
connection object to fi#ure out which database to
communicate with. %ou can use a command object alone, to
e!ecute a command directly, or assi#n a reference to a
command object to an &$lDataAdapter, which holds a set of
commands that work on a #roup of data as described below.
The SqlDataReader Object
(any data operations re$uire that you only #et a stream of data for readin#. The
data reader object allows you to obtain the results of a &E"E)T statement from a
command object. *or performance reasons, the data returned from a data reader
is a fast forward+only stream of data. This means that you can only pull the data
from the stream in a se$uential manner. This is #ood for speed, but if you need to
manipulate data, then a Data&et is a better object to work with.
The DataSet Object
Data&et objects are in+memory representations of data. They contain multiple
Datatable objects, which contain columns and rows, just like normal database
tables. %ou can even define relations between tables to create parent+child
relationships. The Data&et is specifically desi#ned to help mana#e data in memory
and to support disconnected operations on data, when such a scenario make
sense. The Data&et is an object that is used by all of the Data ,roviders, which is
why it does not have a Data ,rovider specific prefi!.
The SqlDataAdapter Object
&ometimes the data you work with is primarily read+only and you rarely need to
make chan#es to the underlyin# data source. &ome situations also call for cachin#
data in memory to minimi-e the number of database calls for data that does not
chan#e. The data adapter makes it easy for you to accomplish these thin#s by
helpin# to mana#e data in a disconnected mode. The data adapter fills a Data&et
object when readin# the data and writes in a sin#le batch when persistin# chan#es
back to the database. A data adapter contains a reference to the connection
object and opens and closes the connection automatically when readin# from or
writin# to the database. Additionally, the data adapter contains command object
references for &E"E)T, .N&E/T, 0,DATE, and DE"ETE operations on the data. %ou
will have a data adapter defined for each table in a Data&et and it will take care
of all communication with the database for you. All you need to do is tell the data
adapter when to load from or write to the database.
Summar!
ADO.NET is the .NET technolo#y for interactin# with data sources. %ou have
several Data ,roviders, which allow communication with different data sources,
dependin# on the protocols they use or what the database is. /e#ardless, of which
Data ,rovider used, youll use a similar set of objects to interact with a data
source. The &$l)onnection object lets you mana#e a connection to a data source.
&$l)ommand objects allow you to talk to a data source and send commands to it.
To have fast forward+only read access to data, use the &$lData/eader. .f you want
to work with disconnected data, use a Data&et and implement readin# and writin#
to1from the data source with a &$lDataAdapter.
What is ADO.NET?
ADO.NET is the new data!ase technology of the .NET 2Dot Net3 platform, and it !ilds on
Microsoft Active) Data O$%ects 2ADO3.
ADO is a langage"netral o!#ect model that is the keystone of Microsoft5s 7niversal Data
Access strategy.
ADO.NET is an integral part of the .NET *ompact Framework, providing access to
relational data, 1M( docments, and application data. ADO.NET spports a variety of
development needs. /o can create data!ase"client applications and middle"tier !siness
o!#ects sed !y applications, tools, langages or 0nternet !rowsers.
ADO.NET defines DataSet and DataTable o!#ects which are optimi9ed for moving
disconnected sets of data across intranets and 0nternets, inclding throgh firewalls. 0t also
incldes the traditional Connection and Command o!#ects, as well as an o!#ect called a
DataReader that resem!les a forward"only, read"only ADO recordset. 0f yo create a new
application, yor application re+ires some form of data access most of the time.
ADO.NET provides data access services in the Microsoft .NET platform.
/o can se ADO.NET to access data !y sing the new .NET Framework data providers
which are-
Data Provider for SQL Server (System.Data.SqlClient).
Data Provider for OLEDB (System.Data.OleDb).
Data Provider for ODBC (System.Data.Odbc).
Data Provider for Oracle (System.Data.OracleClient).
ADO.NET is a set of classes that e$pose data access services to the .NET developer. The
ADO.NET classes are fond in System.Data.dll and are integrated with the 1M( classes in
System.Xml.dll.
There are two central components of ADO.NET classes- the DataSet, and the .NET
Framework Data Provider.
Data Provider is a set of components inclding-
the Connection object (SqlConnection, OleDbConnection, OdbcConnection,
OracleConnection)
the Command object (SqlCommand, OleDbCommand, OdbcCommand,
OracleCommand)
the DataReader object (SqlDataReader, OleDbDataReader, OdbcDataReader,
OracleDataReader)
and the DataAdapter object (SqlDataAdapter, OleDbDataAdapter,
OdbcDataAdapter, OracleDataAdapter).
DataSet o!#ect represents a disconnected cache of data which is made p of DataTables and
DataRelations that represent the reslt of the command.
The ADO.NET Object Model
top
2. Connection to an ADO.NET database
)efore working with a data!ase, yo have to add 2here3 the OleDb .NET Data &rovider
namespace, !y placing the following at the start of yor code modle-
Collapse | Copy Code
using System.Data.OleDb;
%imilarly for the SqlClient .NET Data &rovider namespace-
Collapse | Copy Code
using System.Data.SqlClient;
The using statement shold !e positioned first in yor code.
Now, we have to declare a connection string pointing to a M% Access data!ase
:PersonDatabase.mdb:.
Collapse | Copy Code
public string
conString=@"ro!ider="icroso#t.$et.O%&D'.(.);" *
@" DataSource=..++..++ersonDatabase.mdb";
The data!ase shold !e in the specified path, otherwise yo shold change the path
accordingly.
The ne$t step is to create an OleDbConnection o!#ect. 4e pass then the connection string to
this OleDbConnection o!#ect. /o can code now to create a new ADO.NET *onnection
o!#ect in order to connect to an O(E D) provider data!ase.
Collapse | Copy Code
OleDbConnection con = ne, OleDbConnection-conString.;
/o can also e$plicitly reference declared o!#ects if yo dont mind typing a lot.
Collapse | Copy Code
System.Data.OleDb.OleDbConnection con =
ne, System.Data.OleDb.OleDbConnection-conString.;
.ere is the code snippet for connection to a data!ase-
Collapse | Copy Code
//using declaration #or O%& D'
using System.Data.OleDb;
//speci#y t0e ConnectionString property
public string conString=
@"ro!ider="icroso#t.$et.O%&D'.(.);Data
Source=..++..++ersonDatabase.mdb";
//1nitiali2es a ne, instance o# t0e OleDbConnection
OleDbConnection con = ne, OleDbConnection-conString.;
// open t0e database connection ,it0 t0e property settings
// speci#ied by t0e ConnectionString "conString"
con.Open-.;
0n many earlier applications, the tendency was to open a connection when yo start the
application and not close the connection ntil the application terminates. 0t is an e$pensive
and time"consming operation to open and close a data!ase connection. Most data!ases have
a limit on the nm!er of concrrent connections that they allow.
For e$ample- each connection consmes a certain amont of resorces on the data!ase server
and these resorces are not infinite. Most modern O(E D) providers 2inclding %'( %erver
provider3 implement connection pooling. 0f yo create data!ase connections, they are held in
a pool. 4hen yo want a connection for an application, the O(E D) provider e$tracts the
ne$t availa!le connection from the pool. 4hen yor application closes the connection, it
retrns to the pool and makes itself availa!le for the ne$t application that wants a connection.
This means that opening and closing a data!ase connection is no longer an e$pensive
operation. 0f yo close a connection, it does not mean yo disconnect from the data!ase. 0t
#st retrns the connection to the pool. 0f yo open a connection, it means it5s simply a matter
of o!taining an already open connection from the pool. 0t5s recommended in many
ADO.NET !ooks not to keep the connections longer than yo need to. Therefore, yo
shold-
Open a connection !hen yo" need it, and
Close it as soon as yo" have #nished !ith it.
For e$ample- here is another way to get a connection to a data!ase-
Collapse | Copy Code
// setup t0e global SqlConnection ob3ect and constr in your class
pri!ate SqlConnection con = null;
pri!ate string constr ="1ntegrated Security=SS1;" *
"1nitial Catalog=4ort0,ind;" *
"Data Source=SO45++"5S6%S&R7&R;";

pri!ate !oid #n8etConnection-.
9
try
9
// setup t0e database connection
con = ne, SqlConnection-constr.;
con.Open-.;
:catc0 -&;ception e;. 9
"essage'o;.S0o,-"&rror in connection < "*e;."essage.;
:#inally 9
// dispose o# open ob3ects
i# -con == null.
con.Close-.;
: //#inally
:
For e$ample- yo want to open the connection, fill the DataSet, and close the connection. 0f
the connection fails, yo want to get the error message.
Collapse | Copy Code
try
9
con.Open-.;
dadapter.>ill-dataset?.;
con.Close-.;
: catc0 -&;ception e;. 9
"essage'o;.S0o,-"&rror in retrie!ing data< " * e;."essage.;
:
For e$ample- if yo want to save the data yo changed, then yo #st open the connection,
pdate the data, and close the connection and accept the changes. 0f it fails, display an error
message, re#ect the changes, and close the connection.
Collapse | Copy Code
try
9
DataSet c0anges = dataset.8etC0anges-.;
con.Open-.;
datapter.@pdate-c0anges.;
con.Close-.;
dataset?.AcceptC0anges-.;
:catc0 -&;ception e;. 9
"essage'o;.S0o,-"&rrorR< " * e;."essage.;
dataset?.Re3ectC0anges-.;
con.Close-.;
:
top
. Data!et
The DataSet is similar to an array of disconnected Recordset o!#ects. 0t spports
disconnected data access and operations, allowing greater scala!ility !ecase yo no longer
have to !e connected to the data!ase all the time. DataSet is a copy of an e$tracted data
!eing downloaded and cached in the client system.
The DataSet o!#ect is made p of two o!#ects-
DataTableCollection o$%ect containin& n"ll or '"ltiple DataTable o$%ects
(Col"'ns, (o!s, Constraints).
DataRelationCollection o$%ect containin& n"ll or '"ltiple DataRelation
o$%ects !hich esta$lish a parent)child relation $et!een t!o DataTable
o$%ects.
Collapse | Copy Code
//Create a DataSet
DataSet dset = ne, DataSet-.;
There are two types of DataSets-
*. T"ped Data!et
+. #nt"ped Data!et
*. T!(ed DataSet is derived from the !ase DataSet class and then ses information in an
1M( %chema file 2.xsd file3 in order to generate a new class. 0nformation from the schema
2ta!les, colmns, and so on3 is generated and compiled into this new DataSet class as a set of
first"class o!#ects and properties. T!(ed dataset is easier to read. 0t5s also spported !y
0ntelli%ense in the 6isal %tdio *ode Editor. At compile time, it has type checking so that
there are less errors in assigning vales to DataSet mem!ers. Therefore, sing T!(ed
DataSet has many advantages.
E$ample- the following code accesses the Customer1D colmn in the first row of the
Customers ta!le.
Collapse | Copy Code
string str;
str=dset.CustomersA)B.Customer1D;
Create a t!(ed DataSet +ithout designer , manua##!
Call the co''and pro'pt (cmd) at the location of the ,SD sche'a #le.
-se the XSD.EXE "tility to create the class for the typed DataSet.
Collapse | Copy Code
;sd.e;e /d /l<cs mydataset.;sd /n<mynamespace
/d < you create a DataSet.
/l<cs C set t0e language as CD.
/n<mynamespace C t0e class s0ould use t0e namespace "mynamespace".
The otpt of XSD.EXE with these argments will !e a .cs class file 2mydataset.cs3.
7se csc.exe to compile the class.
Collapse | Copy Code
csc.e;e /t<library mydataset.cs /r<System.dll /r<System.Data.dll
/r<System.E"%.dll /out<bin/mydataset.dll /t<library
*ompile as a li!rary component 2D((3.
)r. / speci#es asse'$lies yo" need to reference.
)o"t. / saves the co'piled asse'$ly in the bin s"$directory of the c"rrent
directory.
-. .nt!(ed DataSet is not defined !y a schema, instead, yo have to add ta!les, colmns and
other elements to it yorself, either !y setting properties at design time or !y adding them at
rn time. Typical scenario- if yo don5t know in advance what the strctre of yor program
is that is interacting with a component that retrns a DataSet.
The e+ivalent code a!ove for Untyped DataSet is-
Collapse | Copy Code
string str;

str=-string.dset.TablesA"Customers"B.Ro,A)B.A"Customer1D"B;
A DataSet is a container; therefore, yo have to fill it with data.
/ou can (o(u#ate a DataSet in a variet! of +a!s0
b" $sin% DataAdapter objects and &ill method.
For e$ample-
Collapse | Copy Code
string strCon = @"Data Source=SO45+"5S6%S&R7&R;" *
"1nitial Catalog=4ort0,ind;1ntegrated Security=SS1";
string strSql="select F #rom customers";
SqlConnection con=ne, SqlConnection-strCon.;
con.Open-.;

SqlDataAdapter dadapter=ne, SqlDataAdapter-.;
dadapter.SelectCommand=ne, SqlCommand-strSqlGcon.;
DataSet dset=ne, DataSet-.;
dadapter.>ill-dset.;
con.Close-.;

t0is.data8rid?.DataSource=dset;
b" creatin% DataTable' DataCol$mn and DataRo( objects
pro%rammaticall".
After yo create a DataTable and define its strctre sing colmns and constraints,
yo can add new rows of data to the ta!le.
For e$ample-
Collapse | Copy Code
DataSet dset;
DataTable dtbl;
DataRo, dro,;
//create a ne, ro,
dro,=dtbl.4e,Ro,-.;
//manipulate t0e ne,ly added ro, using an inde; or t0e column name
dro,A"%ast4ame"B="Altindag";
dro,A?B="Altindag";
//A#ter data is inserted into t0e ne, ro,G t0e A met0od is used
//to add t0e ro, to t0e Data!owCollection
dtbl.Ro,s.Add-dro,.;
//5ou can also call t0e A met0od to add a ne, ro, by passing in an
//array o# !aluesG typed as Ob"ect
dtbl.Ro,s.Add-ne, ob3ectAB 9?G "Altindag":.;
Read an )M* doc$ment or stream into the Data!et.
The following code creates a SqlConnection o!#ect that opens a connection to the
Pubs data!ase, creates a %'( +ery to get the data of the Authors ta!le as 1M(, and
it creates a new SqlCommand o!#ect. After creating a new DataSet, it ses the
&;ecuteEmlReader method to pass an EmlReader o!#ect to the DataSet5s ReadEml
method, which allows the DataSet to poplate itself from the EmlReader. Finally, the
code sets the DocumentContent property to the reslt of the 8etEml method of the
DataSet. 1M( ses the 1%( Transformation docment authors.xsl 2inclded in the
pro#ect3 to format the 1M( content displayed !y the 1M( control.
For e$ample-
Collapse | Copy Code
protected System.Heb.@1.HebControls.Eml EmlDisplay;

string strCon = @"Data Source=SO45+"5S6%S&R7&R;" *
"1nitial Catalog=pubs;1ntegrated Security=SS1";
SqlConnection con=ne, SqlConnection-strCon.;

con.Open-.;
try
9
string strSql="select F #rom >RO" aut0ors >OR E"% A@TOG E"%DATA";
SqlCommand cmd=ne, SqlCommand-strSqlG con.;
DataSet dset=ne, DataSet-.;
dset.ReadEml-cmd.&;ecuteEmlReader-.GEmlRead"ode.>ragment.;
EmlDisplay.DocumentContent = dset.8etEml-.;
:#inally 9
con.Close-.;
:
Mer%e +cop", the contents o- another Data!et' (ith the Mer%e
method.
/o can merge two DataSet o!#ects that have largely similar schemas. /o can se a
merge typically on a client application to incorporate the latest changes from a data
sorce into an e$isting DataSet. This allows the client application to have a refreshed
DataSet with the latest data from the data sorce.
For e$ample-
Collapse | Copy Code
dataset?."erge-datasetI.;
top
.. DataAdapter
DataAdapter o!#ect is like a !ridge that links the data!ase and a *onnection o!#ect with the
ADO.NET"managed DataSet o!#ect throgh its S&%&CT and action +ery *ommands. 0t
specifies what data to move into and ot of the DataSet. Often, this takes the form of
references to %'( statements or stored procedres that are invoked to read or write to a
data!ase.
The DataAdapter provides for properties that allow s to control how pdates are made to
the server-
SelectCommand
@pdateCommand
1nsertCommand
DeleteCommand
The for properties are set to *ommand o!#ects that are sed when data is maniplated.
The DataAdapter incldes three main methods-
>ill (pop"lates a DataSet !ith data).
>illSc0ema (0"eries the data$ase for sche'a infor'ation that is necessary
to "pdate).
@pdate (to chan&e the data$ase, DataAdapter calls the DeleteCommand, the
1nsertCommand and the @pdateCommand properties).
For e$ample-
4hen we call the DataAdapter5s >ill method to retrieve data from a data sorce and por it
into a DataSet, the *ommand o!#ect in the SelectCommand property is sed. The
DataAdapter is the gatekeeper that sits !etween or DataSet and the data sorce.
Collapse | Copy Code
//Create an instance o# a OleDbDataAdapter
//by passing OleDbConnection ob3ect and select.. query
OleDbDataAdapter Aapter = ne,
OleDbDataAdapter -"select F #rom ersonTable"G con .;
//#ill t0e DataSet ,it0 records #rom t0e table "ersonTable"
Aapter.>ill-dSetG"ersonTable".;
.ere is the method sed in this pro#ect to get a data connection, DataSet and DataAdapter.
/o can find this method in the file :DataAccessTierClass.cs:.
Collapse | Copy Code
public bool #n8etDataConnection-.
9
try 9
con =ne, OleDbConnection-conString.;
dAdapter=ne, OleDbDataAdapter-"select F #rom ersonTable"G con.;
dSet=ne, DataSet-.;
//re#res0es ro,s in t0e DataSet
dAdapter.>ill-dSetG"ersonTable".;
:catc0-&;ception e;. 9
"essage'o;.S0o,-"&rror < "*e;."essage.;
//connectection #ailed
return #alse;
://tryCcatc0
//connection oJ=
return true;
:
top
/. Displa" data in a Data0rid 1 data relationship bet(een t(o
tables
The 4indows Forms Data8rid control displays data in a series of rows and colmns. The
4indows Forms Data8rid control provides a ser interface to ADO.NET DataSets. 0t
displays ta!lar data and allows for pdates to the data sorce. 4hen yo set a Data8rid
control to a valid data sorce, the control will !e atomatically poplated, creating colmns
and rows !ased on the shape of the data.
/o can se the Data8rid control for displaying either a single ta!le or the hierarchical
relationships !etween a set of ta!les. 0f yo want to work with the Data8rid control,
Data8rid shold !e !ond to a data sorce !y sing-
the DataSource and Data"ember properties at desi&n ti'e or
the SetData'inding 'ethod at r"n ti'e.
.ere is the !inding to the Data8rid control with DataSet 0 sed in this pro#ect-
Collapse | Copy Code
t0is.data8rid? DataSource = datc.dSet.TablesA"ersonTable"B;
/o can only show one ta!le in the Data8rid at a time.
0f yo define a (arent,chi#d re#ationshi( !etween ta!les, yo can navigate !etween the
related ta!les to select the ta!le yo want to display in the Data8rid control.
For e$ample-
Collapse | Copy Code
dset.Relations.Add-"CustomerOrders"G
dset.TablesA"customers"B.ColumnsA"Customer1D"BG
dset.TablesA"orders"B.ColumnsA"Customer1D"B.;
//no, 0ere you can use one o# t0e #ollo,ing
t0is.data8rid?.DataSource=dset.TablesA"customers"B;
O,
Collapse | Copy Code
t0is.data8rid?.SetData'inding-dsetG"customers".;
customers. Parent ta$le
orders. Child ta$le
Customer1D in Orders is a forei&n 1ey referrin& to Customer1D pri'ary 1ey in
Customers ta$le.
.ere is a typical e$ample of how to se the parent"child relationship !etween the ta!les
:*stomers: and :Orders: on a Data8rid control.
The DataRelation in this e$ample allows yo to navigate from one DataTable
2:*stomers:3 to another DataTable 2:Orders:3 within a DataSet. The DataSet class can
contain nll or many DataTable o!#ects. :*stomers: and :Orders: DataTables contain a
colmn named :Cust1D:, which is a link !etween these two DataTable o!#ects.
To rn and test this e$ample, create a new pro#ect, drag<drop a 'utton 2here- button?3 and a
Data8rid 2here- data8rid?3 on the >orm and copy the following code snippets
2#n8etConnectionString-., button?KClicJ3 and yo additionally need %'( %erver =>>>
rnning or M%"Access.
Collapse | Copy Code
public string #n8etConnectionString-.
9
//it gi!es bacJ t0e connection string <
// c0ange #or you t0e Data Source=.... accordingly
//#or "SCAccess
//return "ro!ider="icroso#t.$et.O%&D'.(.);
// Data Source=..++..++4ort0,ind.mdb";
//#or S6%S&R7&RI)))
return "data source=SO45++"5S6%S&R7&R;initial" *
" catalog=4ort0,ind;integrated security=SS1;";
:
Collapse | Copy Code
pri!ate !oid button?KClicJ-ob3ect senderG System.&!entArgs e.
9
// #or S6%Ser!erI)))
DataSet dset=ne, DataSet-.;
string strCustomers="select F #rom customers";
string strOrders="select F #rom orders";
SqlConnection sqlcon=ne, SqlConnection-#n8etConnectionString-..;
SqlDataAdapter dadapter=ne, SqlDataAdapter-strCustomersGsqlcon.;
dadapter.>ill-dsetG"Customers".;
dadapter=ne, SqlDataAdapter-strOrdersGsqlcon.;
dadapter.>ill-dsetG"Orders".;
// Add t0e relation to t0e DataSet.
dset.Relations.Add-"Customer Orders"G
dset.TablesA"Customers"B.ColumnsA"Customer1D"BG
dset.TablesA"Orders"B.ColumnsA"Customer1D"B.;
//Display data in t0e Data8rid
//bot0 ,orJs #ine
t0is.data8rid?.DataSource=dset.TablesA"Customers"B;
//t0is.data8rid?.SetData'inding-dsG"Customers".;
//#or "SCAccess
/F
//create a DataSet ob3ect ,0ic0 ,ill contain t0e #ollo,ing I DataTables
DataSet dset=ne, DataSet-.;
string strCustomers="select F #rom customers";
string strOrders="select F #rom orders";
OleDbConnection con=ne, OleDbConnection-#n8etConnection-..;
OleDbDataAdapter dadapter=ne, OleDbDataAdapter-strCustomersGcon.;
//#ill t0e DataSet ,it0 t0e records #rom t0e Customers table
dadapter.>ill-dsetG"Customers".;
dadapter=ne, OleDbDataAdapter-strOrdersGcon.;
//#ill t0e DataSet ,it0 t0e records #rom t0e Orders table
dadapter.>ill-dsetG"Orders".;
//establis0 t0e relation bet,een t0e I DataTable ob3ects
dset.Relations.Add-"Customer Orders"G
dset.TablesA"Customers"B.ColumnsA"Customer1D"BG
dset.TablesA"Orders"B.ColumnsA"Customer1D"B.;
//bot0 ,orJs #ine
t0is.data8rid?.DataSource=dset.TablesA"Customers"B; //s0o, t0e data in
Data8rid
//t0is.data8rid?.SetData'inding-dsG"Customers".;
F/
:
Now if yo u(date the data in the !ond DataSet throgh any mechanism, the Data8rid
control reflects the changes. /o can pdate the data in the DataSet throgh the Data8rid
control, if the Data8rid and its ta!le styles and colmn styles have the ReadOnly property set
to #alse. There are for most typical valid data sorces for the Data8rid-
DataTable class
Data7ie, class
DataSet class
Data7ie,"anager class
The first time this application was p!lished, 0 got e"mails from sers asking me how to get
the contents of a Data8rid cell yo clicked, or how to get the Data8rid row contents yo
clicked. %o now, 05ve one method to do that and didn5t want to withhold it from yo.
Collapse | Copy Code
// you clicJ in t0e cell or t0e ro,s
// o# t0e Data8rid and get t0e content o# it
pri!ate !oid data8rid?KCurrentCellC0anged-ob3ect senderG System.&!entArgs
e.
9
/F be ,arned< i# you clicJ t0e last cell on t0e Datagrid you get
an un0andled e;ception o# type LSystem.ArgumentOutO#Range&;ception.
because t0ere is no #urt0er columns a#ter t0e last column-Country.
to a!oid t0is 1 tried a di##erent ,ay< in a tryCcatc0 get t0e rig0t
cell content. i# t0e last column cell clicJedG display t0e e;ception
and t0e cell content one be#ore. 'ut you can comment
t0e "essage'o;.S0o, line i# not ,is0ed F/
//get t0e ro, number on t0e Data8rid
int iRo,nr=t0is.data8rid?.CurrentCell.Ro,4umber;
//get t0e column number on t0e Data8rid
int iColnr=t0is.data8rid?.CurrentCell.Column4umber;
//get t0e content o# t0e cell in t0e clicJed cell on t0e Datagrid
ob3ect cell!alue?=t0is.data8rid?AiRo,nrG iColnrB;
ob3ect cell!alueI=null;
//get t0e ne;t cell content in t0e same ro,
try 9
cell!alueI=t0is.data8rid?AiRo,nrG iColnr*?B;
//display -cell!alue?*cell!alueI. in Te;t'o; "te;t'o;?"
t0is.te;t'o;?.Te;t=cell!alue?.ToString-.*" "*cell!alueI.ToString-.;
: catc0-&;ception e;. 9
//t0e e;ception occurs 0ere because ,e increment iColnr*?
"essage'o;.S0o,-"4o #urt0er columns a#ter t0e last " *
"column-Country. CCMM "*e;."essageG"STO".;
cell!alueI=t0is.data8rid?AiRo,nrG iColnrC?B;
//display t0is time -cell!alueI*cell!alue?. in Te;t'o; "te;t'o;?"
t0is.te;t'o;?.Te;t=cell!alueI.ToString-.*" "*cell!alue?.ToString-.;
://catc0
:
top
2. Data3indin%s -or Te4t3o4es
DataBinding is the a!ility to !ind some elements of a data sorce with some graphical
elements of an application.
The data in 4indows Forms is !ond !y calling Data'indings. 4indows Forms allows yo
to !ind easily to almost any strctre that contains data.
4indows Forms *ontrols spport two types of data !inding-
Simple Data Binding
Complex Data Binding
*. Sim(#e Data Binding allows yo to display a single data element, sch as a colmn vale
from a DataSet ta!le, in a control. /o can simple"!ind any property of a control to a data
vale. Simple Data Binding can !e performed either at design time sing Data'indings
property of a control or dynamically at rn time. This is the type of !inding typical for
controls sch as a Te;t'o; control or %abel control that displays typically only a single
vale.
For e$ample-
Collapse | Copy Code
// Simple Data'inding #or Te;t'o; "te;t'o;?"
te;t'o;?.Data'indings.Add-"Te;t"G datasetG "studentTable.student1D".;
The control :te;t'o;?: a!ove is !ond to the :student1D: colmn of a ta!le :studentTable:
on the DataSet 2dataset3 throgh the 'indingConte;t o!#ect.
-. Com(#e data $inding is the a!ility of a control to !ind to more than one data element,
typically more than one record in a data!ase, or to more than one of any other type of
!inda!le data element. Data8rid, %ist'o; and &rrorro!ider controls spport com(#e
data $inding.
Typical scenario-
/o want to display the names of prodcts in a list !o$ and then retrieve in a Te;t'o; the
roduct1D of a prodct which yo selected.
For e$ample-
/o cold add complex data binding !y sing the DataSource and Data"ember properties.
Collapse | Copy Code
datagrid?.DataSource = dSet;
// @se t0e Data"ember property to speci#y t0e DataTable.
datagrid?.Data"ember = "ersonTable";
.ere is the method sed in this pro#ect to !ind all Te;t'o;es-
Collapse | Copy Code
pri!ate !oid #n8etData'inding>orTe;t'o;es-.
9
t0is.te;tbo;>irstname.Data#inings.Add-"Te;t"G
datc.dSet.TablesA"ersonTable"BG">irst4ame".;
t0is.te;tbo;%astname.Data#inings.Add-"Te;t"G
datc.dSet.TablesA"ersonTable"BG"%ast4ame".;
t0is.te;tbo;Title.Data#inings.Add-"Te;t"G
datc.dSet.TablesA"ersonTable"BG"Title".;
t0is.te;tbo;City.Data#inings.Add-"Te;t"G
datc.dSet.TablesA"ersonTable"BG"City".;
t0is.te;tbo;Country.Data#inings.Add-"Te;t"G
datc.dSet.TablesA"ersonTable"BG"Country".;
:
top
5. #sin% the C$rrenc"Mana%er
/o se the Currency"anager o!#ect if yo want to keep data"!ond controls synchroni9ed
with each other which means showing data from the same record. For e$ample- if yo want
to add a Te;t'o; control to a form and !ind it to a colmn of a ta!le 2e.g.,
Customers.>irst4ame3 in a DataSet 2e.g., dSet3, the control is going to commnicate with
the 'indingConte;t o!#ect for this form. 0n trn, the 'indingConte;t o!#ect is going to talk
to the specific Currency"anager o!#ect for the data the Te;t'o; control is !inding.
Every 4indows Form has a 'indingConte;t o!#ect keeping track of all the
Currency"anager o!#ects on the 4indows Form. Currency"anager keeps track of the
position in the data sorce. 4hen yo !ind a data o!#ect to a control 2i.e., Te;t'o;3, a
Currency"anager o!#ect is atomatically assigned. 0f yo !ind several controls to the same
data sorce, they share the same Currency"anager.
0n a normal case where yo are sing an ADO.NET data!ase 2connecting and closing
data!ase3 and displaying the records, e.g., in a Data8rid, yo never need the
Currency"anager o!#ect. But if yo want to know the e$act position within a data strctre
2e.g., ta!le in yor data!ase3 as 0 did, yo have to se the Currency"anager o!#ect !ecase
the Currency"anager has the osition property for this prpose. /o can, for e$ample,
maniplate the osition property in a Ne$t or &revios or First or (ast !tton which 0 did in
my program as well.
For e$ample-
0f yo want to know how many records are in a DataTable, yo simply +ery the
'indingConte;t o!#ect5s Count property.
Collapse | Copy Code
t0is.'indingConte;tAdataset?G"ersonTable"B.Count C ? ;
0f yo want to get the crrent position from the 'indingConte;t o!#ect-
Collapse | Copy Code
t0is.'indingConte;tAdataset?G "ersonTable"B.osition * ?;
After data !inding, yo call and initiali9e Currency"anager for yor ta!le. .ere is the
method 0 sed to initiali9e the Currency"anager for the ta!le PersonTable-
Collapse | Copy Code
public !oid #nSetCurrency"anager-.
9
curr"anager = -Currency"anager.t0is.
'indingConte;t A datc.dSet.TablesA"ersonTable"BB ;
:
top
6. Na7i%ation thro$%h records (ith Ne4t' 8re7io$s' *ast'
&irst b$ttons
As soon as yo get the data poplated in the Data8rid, yo can navigate throgh records !y
sing Ne$t, &revios, (ast, First !ttons, or !y clicking the rows of the Data8rid, or !y
sing the arrow keys 27p arrow and Down arrow3.
0f the Data8rid is crrently displaying data, none of the standard key!oard events are raised
for the navigation keys. /o can still se 7p and Down arrow keys to navigate in the
Data8rid !t, !ecase 0 haven5t implemented it, yo don!t get the record position in the
Status'ar.
0n order to captre keystrokes on the Data8rid, yo have to override the rocessCmdNey
method that processes a command key. /o can find this method in section ?.
0 also inclded two new methods in order to highlight the records in the Data8rid !y sing
Ne$t, &revios, (ast or First !ttons !ecase yo don5t normally get the row highlighted in
the Data8rid if yo click sch a !tton. )y defalt, if yo click the Data8rid row, the row
will !e highlighted with 'acJColor and >oreColor.
*
st
method0
Collapse | Copy Code
#nSelect@nselect%ast>irstRo,-int posi.
0f yo click First or (ast !tton, the first or last record will !e selected and highlighted in the
Data8rid. /o invoke for that the #nSelect@nselect%ast>irstRo,-. method and pass as
parameter > 29ero3 for the first record 2#nSelect@nselect%ast>irstRo,-).;3, and
-t0is.curr"anager.CountC?. for the last record.
Collapse | Copy Code
#nSelect@nselect%ast>irstRo,-t0is.curr"anager.CountC?.;
.ere is the @
st
method 0 sed for this prpose-
Collapse | Copy Code
pri!ate !oid #nSelect@nselect%ast>irstRo, -int posi.
9
//unselect t0e last selected/0ig0lig0ted ro,
t0is.data8rid?.@nSelect-t0is.data8rid?.CurrentRo,1nde;.;
//select t0e last or #irst ro,
t0is.data8rid?.Select-posi.;
:
-
nd
method-
Collapse | Copy Code
#nSelect@nselectCurrentRo,-int num?G int numI.
0f yo click Ne$t or &revios !tton, the ne$t or previos record will !e selected and
highlighted in the Data8rid. /o call for that the method
#nSelect@nselectCurrentRo,-.; and pass as parameter 2@,"@3 for the ne$t record
2#nSelect@nselectCurrentRo,-?GC?.;3, or 2"@,@3 for the previos record
2#nSelect@nselectCurrentRo,-C?G?.;3.
.ere is the =
nd
method sed for it-
Collapse | Copy Code
pri!ate !oid #nSelect@nselectCurrentRo,-int num?G int numI.
9
//get t0e current ro, inde;
t0is.iRo,1nde;=t0is.data8rid?.CurrentRo,1nde;;
//increment or decrement t0e inde; by -num?GbumI.?GC? or C?G? depending
on
//4e;t or re!ious button because ,e ,ant to select ne;t or pre!ious ro,
//i# num? is *? you clicJed 4e;t so select ne;t ro,
//i# num? C? you clicJed re!ious so select pre!ious ro,
//1 use in bot0 select and unselect plus-*.
// its liJe in mat0< e.g.O*-C?.=OC?= P orO*-*?.=O*?=Q
t0is.iRo,1nde;=t0is.iRo,1nde;*num?;
//select t0e current ro,
t0is.data8rid?.Select-t0is.iRo,1nde;.;
//increment or decrement t0e inde; by C? or ?
//so t0at ,e can unselect t0e pre!ious ro,
t0is.iRo,1nde;=t0is.iRo,1nde;*numI;
//unselect t0e pre!ious ro,
t0is.data8rid?.@nSelect-t0is.iRo,1nde;.;
:
No+ $ac1 to ena$#ing and disa$#ing the $uttons0
4hen yo click 2irst !tton, position will !e set to > 29ero3 !ecase the first row starts !y
9ero.
Collapse | Copy Code
curr"anager.osition=);
and
Disa$le &irst and 8re7io$s $"ttons $eca"se there is no previo"s record in
the data so"rce.
Ena$le Ne4t and *ast $"ttons $eca"se there are records for!ards.
4hen yo click Net !tton, position in the data is increased !y @ and moved to the ne$t row.
Collapse | Copy Code
curr"anager.osition *=?;
and
Ena$le &irst and 8re7io$s $"ttons as lon& as there are for!ard records.
Other!ise, disa$le Ne4t and *ast $"ttons !hich 'eans yo" reached the
end of the records.
4hen yo click Previous !tton, position in the data is decreased !y "@ and moved to the
previos row.
Collapse | Copy Code
curr"anager.osition C=?;
and
Ena$le Ne4t and *ast $"ttons as lon& as there are records $ac1!ards.
Other!ise, disa$le &irst and 8re7io$s $"ttons !hich 'eans yo" reached
the $e&innin& of the records.
4hen yo click Last !tton, position in the data is set to the last record 2row3.
Collapse | Copy Code
t0is.curr"anager.osition=t0is.curr"anager.CountC?;
and
Disa$le Ne4t and *ast $"ttons $eca"se there are no records for!ards any
'ore.
Other!ise, ena$le &irst and 8re7io$s $"ttons so that yo" can navi&ate
$ac1!ards.
To ena!le and disa!le the !ttons, 0 se the fnction<method #n&nableDisable'uttons with
for parameters 2two 'uttons, string for Status'ar, bool for trueAena!ling,
#alseAdisa!ling3.
Collapse | Copy Code
pri!ate !oid #n&nableDisable'uttons-'utton bt?G 'utton btIG string strG
bool b.
9
bt1.Enabled=b;
bt2.Enabled=b;
this.statusBar1.Text=str;
:
top
9. :o( to trap ;e"stro;es +#p' Do(n' Esc' N$m*oc;..., in the
Data0rid
Every time yo press the keys 7p, Down, Nm(ock and Esc in the Data8rid, 0 display te$t
in the status'aranel? and status'aranelI, !t yo don5t get record nm!ers displayed
!ecase 0 thoght it wold !e a !it confsing and too mch coding.
(ike many sers, 0 also looked for a method to catch the keystrokes in a Data8rid, and
encontered it first in M%DN (i!rary. %o 0 decided to inclde it in the code so that sers can
make se of it. For most prposes, the standard Ney@p, NeyDo,n, and Neyress events can
captre and handle keystrokes. .owever, not all controls raise the standard Ney@p, NeyDo,n
events for all keystrokes nder all conditions. The Data8rid control is one of them.
0f no data was assigned to the grid, the arrow keys 2(EFT, ,0B.T, 7&, and DO4N3 raise
only the Ney@p event. 0f the Data8rid displays data, none of the standard key!oard events
are raised for the navigation keys. The Data8rid is the control for which this featre is most
fre+ently re+ested. /o also can intercept key com!inations, inclding *T,( and A(T.
This techni+e does not captre the &rint %creen key. 0n order to trap keystrokes in a
4indows Forms control, yo can override the rocessCmdNey method in which 0 changed
only Status'aranel Te;t.
Collapse | Copy Code
protected o!erride bool rocessCmdNey-re# "essage msgG Neys JeyData.
9
const int H"KN&5DOH4 = );?));
const int H"KS5SN&5DOH4 = );?)(;
i# --msg."sg == H"KN&5DOH4. RR -msg."sg == H"KS5SN&5DOH4..
9
s,itc0-JeyData.
9
case Neys.Do,n<
t0is.status'aranelI.Te;t="Do,n";
t0is.status'aranel?.Te;t = "Trapped JeystroJes on Data8rid...";
breaJ;
case Neys.@p<
t0is.status'aranelI.Te;t="@p";
t0is.status'aranel?.Te;t ="Trapped JeystroJes on Data8rid...";
breaJ;
case Neys.4um%ocJ<
t0is.status'aranelI.Te;t="4um%ocJ";
t0is.status'aranel?.Te;t ="Trapped JeystroJes on Data8rid...";
breaJ;
case Neys.&scape<
t0is.status'aranelI.Te;t="&scape";
t0is.status'aranel?.Te;t ="Trapped JeystroJes on Data8rid...";
//in!oJe t0e met0od "#n&;it@ni!ersal" #rom t0e class "&;itClass"
&;itClass ec=ne, &;itClass-.;
ec.#n&;it@ni!ersal-.;
breaJ;
/F
case Neys.Tab<
t0is.status'aranel?.Te;t="Tab Ney Captured";
breaJ;
case Neys.Control R Neys."<
t0is.status'aranel?.Te;t="SCTR%M* " Captured";
breaJ;
case Neys.Alt R Neys.T<
t0is.status'aranel?.Te;t="SA%TM * T Captured";
breaJ;
F/
: //s,itc0
: //i#
return base.rocessCmdNey-re# msgGJeyData.;
:

You might also like