Documentos de Académico
Documentos de Profesional
Documentos de Cultura
NET
ADO.NET
Introduccin
ADO .NET responde a las siglas de Microsoft ActjveX Data Objects de la platafom1a .NET, y
es una mejora evolutiva de la tecnologa ADO. Realmente es una evolucin ms en las
tecnologas de acceso a la informacin.
En este captulo se comparan las tecnologas ADO y ADO.NET, se describen y detallan los
objetos ms importantes de la tecnologa, el objeto oataset y los proveedores de acceso a
datos. Se profundizar sobre el objeto oataset describiendo los objetos oataTable,
DataColumn, etc. En cuanto a los proveedores de acceso a datos se describir el proveedor
para SQL Server y el proveedor para OLE DB.
1/57
Durante un tiempo convivan ambas tecnologas: DAO para aplicaciones sencillas o locales y
RDO para aplicaciones distribuidas. Uno de los problemas que tena la tecnologa RDO es que
el lenguaje SQL con el que se accede a la informacin debe de ser el que entienda el sistema
de gestin de bases de datos correspondiente. Por ejemplo, si se desarrolla contra SQL Server,
se debe utilizar sentencias T-SQL -lenguaje SQL propio para SQL Server- y si se programa
contra Oracle se debe utilizar sentencias PLISQL -lenguaje SQL propio para Oracle-, y
aunque T-SQL y PL/SQL se basan en SQL estndar, tienen pequeas diferencias que pueden
hacer que una aplicacin cliente-servidor que utilice RDO no funcione en otro sistema de
gestin de bases de datos.
Con DAO no exista este problema y debido a este hecho, a otras circunstancias y sobre todo a
la aparicin de COM, el estndar ODBC evolucion a OLE DB. OLE DB es un conjunto de
interfaces basadas en COM que exponen los datos desde una gran variedad de orgenes de
datos. Posteriormente surgi la tecnologa ADO ( ActiveX Data Objects) que se apoya en OLE
DB y que es una interfaz que recoge lo mejor de las dos tecnologas anteriores, incorporando
adems otras mejoras.
Los objetos ms importantes de la tecnologa ADO son el objeto RecordSet, el objeto
Corrunand y el objeto Connection.
Connection
Error
Parameters
Parameter
Fields
Field
ADO
La tecnologa ADO es una capa COM sobre OLE DB de tal manera que las aplicaciones que
utilicen esta tecnologa de acceso a datos in vocan a los objetos de ADO sin tener que conocer
en absoluto el estndar OLE DB. Es una tecnologa que se utiliza de manera senci lla desde
Visual Basic o desde ASP, pero no est pensada para Visual C++ y otros lenguajes.
ClienteADO
(Visual Basic, ASP,etc.)
ADO
ADO.NET
La tecnologa ADO.NET -en la versin beta l se llamaba ADO+- es un modelo de proveedor
ms sencillo que el par OLEDB 1 ADO y se integra perfectamente con XML. ADO.NET es la
evolucin de ADO en La nueva plataforma .NET. Tiene la misma filosofia pero se ha
modificado el modelo.
Las principales caractersticas de ADO.NET son:
Trabaja desconectado del origen de datos que se utilice.
Tiene una fuerte integracin con XML y ASP .NET.
El uso de ADO.NET es independien te del lenguaje de programacin que se utilice.
Por otra parte se ha demostrado que Los niveles de trasferencia de informacin con ADO.NET
que utiliza XML, son tan buenos como los niveles que alcanza ADO utilizando COM.
Aplicacin .NET
1 YaAIIM 1
,..,_ 1
IWttJ*-*-1
ADO.NET
1.D-ataS_e_t
,, ,
OataReader
Managed Providers
ADO
Representad n
datos residente
memoria.
ADO.NET
Relaciones
varias tablas.
Recorrido
de
datos.
"Programabilidad"
Compartir
desconectados
capas
componentes.
mediante
no tiene
tipos de
requ1ere
porque
los Soportado,
frewalls
suelen estar DataSet
prevenir XML que puede pasar a
travs
peticiones a nivel de sistema, de un Firewall.
como por ejemplo COM
marshalling.
Namespaces
ADO .NET se basa en los siguientes espacios de nombres de accesos a datos:
Systern . Data . Cornrnon, que contiene las clases compartidas por los proveedores de datos.
systern. Data .OleDb, que almacena las clases del proveedor de datos OLE DB.
Systern . Data .SqlClient, que expone las clases del proveedor de datos para SQL Server.
.NET Framework
Aplicacin .NET
t
DataSe!
Proveedor .NET
IData Reader
1
1
IDataAdapter
IDBCommand
J
1
Origen de Datos
r
1
, .,
.. . .._
..t
..........
.-""
..,
Base de Datos
..........
IDataAdapter *
IDBDataAdapter Sumitstra .los mtodos de ejecucin tpicos para operar con bases de datos (insert,
El siguiente ejemplo trabaja utilizando el mismo cdigo con ambos proveedores: SQL Server
.NET Data Provider y OLE DB .NET Data Provider, es decir, funciona independientemente
de que el objeto Connection (objCnn) represente una conexin a un SQL Server .NET Data
Provider o a un OLE DB .NET Data Provider.
I DbCommand objCmd = objCnn .CreateCommand( ) ;
objCmd .CommandText = "SELECT * FROM Employees "
IDataReader objDR = ob jCmd . ExecuteReader( ) ;
while ob j DR .
Read()
Console .WriteLine( " (O}\t ( l} '', objDR . GetString ( O) , objDR .GetString(l} )
;
.NET Framework
.NET Framework
Aplicacin .NET
DataSe!
Proveedor .NET
1
1 SqiDataAdapter
'
SqiDataReader
SqiComrnand
..._
DataSe!
1 OleDbDataReader 1
+
1 OleDbDataAdapter 1
1 OleDbCommand 1
Origen de Datos
-........
Proveedor .NET
Origen de Datos
Aplicacin .NET
1 -...
,......_ 1
-....
,../
,../
..._
SOL Server
Base de Datos
Proveedor
SQLOLEDB
MSDAORA
El proveedor de datos OLE DB .NET no soporta OLE DB 2.5 con lo que no funcionarn los
proveedores siguientes: Microsoft OLE DB Provider para Exchange y el Microsoft OLE DB
Provider para Internet Publishing. Tampoco funciona con el proveedor de datos OLE DB para
ODBC (MSDASQL).
Se recomienda este proveedor para aplicaciones de varias capas que utilicen Oracle o SQL
Server 6.5 o inferior. Para aplicaciones cliente-servidor es ms conveniente la utilizacin de
Microsoft Access como origen de datos pero para aplicaciones de varias capas Microsoft no
recomienda utilizar Microsoft Access.
La clase Connection
Es la clase encargada de establecer la conexin con el origen de datos y tiene soporte
automtico para pooling de conexiones. Dependiendo del origen de datos que se utili ce se
deber utilizar oleDbConnection o SqlConnection. Se entiende por pool de conexiones el
conjunto de conexiones "cacheadas" en el servidor.
Esta clase implementa la interface IDbCon nection . La cadena de conexin al origen de
datos se obtiene por medio de la propiedad connectionst r i ng, el estado de la conexin
por medio de la propiedad state, para la base de datos se utiliza oatabase y para determinar
el tiempo mximo de conexin la propiedad Con nectionTimeou t.
Los mtodos ms importantes de esta clase son:
Open
Close
La siguiente tabla describe los estados en los que se puede encontrar la conexin.
Open
10/57
Broken
Closed
Est cerrada.
Connecting
Executing
Ejecutando un comando
Fetching
El proveedor slo puede cambiar la cadena de conexin cuando est cerrada (closed). Por
otro lado, los desarrolladores deberan utilizar el mtodo Close cuando hayan acabado de
utilizar la conexin, ya que este mtodo cierra la conexin y la devuelve al pool de
conexiones. Sin embargo el mtodo Dispose cierra la conexin y destruye la instancia del
objeto elimjnndola del pool de conexiones.
En funcin del proveedor de datos de la plataforma .NET que se utilice, se puede elegir entre
los clases Connection siguientes: OleDbConnection y SqlConnection .
Clase OleDbConnection
Esta clase representa una conexin al proveedor de datos OLE DB .NET. Las propiedades
ms importantes que utiU za son:
Si se desea que sea ilimitado ha de asignrsele el valor cero y slo podr cambiarse su
valor a travs de la propiedad ConnectionString.
Si el estado de la conexin cambia -propiedad State- entonces se produce el evento
StateChange.
Clase SqiConnection
Esta clase representa una conexwn a la base de datos SQL Server 7.0 o supenor. Las
propiedades ms importantes son las siguientes:
Si se produce una excepcin en SQL (sqlException) mientras se ejecuta un comando
concreto, la conexin permanece abierta en caso de que el nivel de severidad sea
menor que 19. Con un nivel de severidad mayor que 20, la conexin se cierra y es
necesario reabrirla para continuar.
La propiedad connectionstring especifica el origen de datos.
Un objeto sqlconnection lee la infonnacin de la conexin a travs de la base de
datos y del origen de datos. No necesita leer informacin del proveedor como en el
caso de OLE DB .NET.
l l/57
EHplorador de serYidores
Para el caso de una conexin a la base de datos Northwind en SQL Server se elige el
proveedor para SQL Server, el servidor, la base de datos y el usuario junto con la contrasea
(Figura 24.7).
12/57
1 Avanzadas 1 Todas 1
l(local)
Contrasea en _blanco
1N orthwind
::J
,_,r;
Cl
_j
1re;o&a'"ic'oneii
i .
:
Aceptar
Cancelar
Ayuda
EMplorador de serYidores
@]
El
Conexiones de datos
El JUPITER.Northwind.dbo
lill-l Employees
lilll EmployeeTerritories
lill-l Order Details
$ lilll Orders
$ lill-l Products
$ lilll Region
!l lil-ll Shippers
!l lill-l Suppliers
!l lill-l Territories
11
11
11
!l
!l
!l
tilll'll
tb Funciones
11 Servidores
Se selecciona el proveedor de acceso a datos Jet 4.0 OLE DB Provider y se el ige la base de
datos Neptuno de Access 2000.
1 Avanzadas 1 Todas 1
J C:\T emp\Neptuno.mdb
2. Escriba la informacinpara iniciar sesin en la base de
datos: Nombre de _ysuario:jAdmin
(:Jntr era
P'
Contrasea en.blanco
Aceptar
Cancelar
Ayuda
EMplorador de serYidores
-g
El
Conexiones de datos
ACCESS.C:\Temp\Neptuno.mdb.Admin
El
El QSJ Tablas
lB !TI] Categoras
ll !TI] Clientes
ll llij] Compaas de envos
$ lli)] Detalles de pedidos
ll llij] Empleados
!l llij] Pedidos
$ []] Productos
ll llij] Proveedores
ll ft Vistas
El Procedimientos almacenados
IJ
Clientes y proveedores por ciudad
!l
Filtro facturas
$
Pedidos trimestrales por producto
IJ
Ventas de empleado por pas
!l
Ventas por ao
[J JUPITER.Northwind.dbo
ll Servidores
a.;.
Transacciones en ADO.NET
Para empezar una transaccin en ADO .NET se llama al mtodo BeginTransaction que
acepta el parmetro IsolationLevel (nivel de aislamiento) y/o el nombre, y devuelve un
objetO transaccin de la clase OleDbTransaction O SqlTransaction dependiendo
del proveedor que se utilice.
El objeto SqlTransaction soporta savepoints o puntos de almacenamiento de la
transaccin que permiten deshacerla (RollBack)ms tarde. Para almacenar un savepoint
se utiliza el mtodo save. Esta funcionalidad es equivalente a la declaracin
"SAVE TRANSACTION" que se realiza en T-SQL.
Si se quiere deshacer una transaccin ya almacenada, ha de utilizarse el mtodo Rollback que
puede llevar como parmetro el nombre del punto de almacenamiento previamente guardado.
En caso de querer aceptar la transaccin se utilizar el mtodo Comrnit.
A continuacin se realiza un ejemplo con SQL Server:
String strConexion = "SERVER=(local); uid=sa; pwd=sa;
database=Northwind"; SqlConnection ObjCnn = new
SqlConnection(strConexion);
ObjCnn.Open()
;
11 Comienza la transaccin
SqlTransaction
ObjCnn.BeginTransaction();
ObjTran
try
(
11 Ejecucin de comandos
11 Se ejecuta el Commit de la Transaccin
ObjTran.commit();
11 La transaccin ha fallado
ObjTran.Rollback()
; ObjCnn.Close();
11 Ejecucin de comandos
11 Se ejecuta el Commit de la Transaccin
ObjTran.Commit();
catch (Exception ex)
11 La transaccin ha fallado
ObjTran.Rollback()
; ObjCnnOLE.Close();
La clase Command
Un objeto de la clase command al igual que un objeto de la clase Connection pertenece al
proveedor de acceso a datos de la plataforma .NET, as que a la hora de codificar se puede
utilizar la interfaz rcommand comn a todos los proveedores (todos ellos la implementan), o
las clases especficas de alguno de los proveedores que proporciona la platafonna .NET.
Un objeto command bsicamente formula una peticin y se la enva al origen de datos. Si esa
petici n devuelve datos, el objeto command se encarga de empaquetarlos y devolverlos como
un objeto DataReader, un valor escalar o como los parmetros de salida util izados en el
propio comando.
Por ejemplo
String strSQL = "SELECT * FROM Employees";
SqlCorrunand ObjCmd = new SqlCorrunand(strSQL,
ObjCnn);
11 La lnea siguiente no es necesaria porque Tex:t es el
11 valor por defecto
ObjCmd.CorrunandType = CorrunandType.Tex:t;
Cuando se est uti l izando un objeto Command se necesita que un objeto Connection haya
sido abierto. Siempre hay una transaccin asociada a la conexin. Si se "resetea" la
conexin entonces el objeto transaccin devuelve null. En principio, se puede cambiar la
conexin sin problema alguno para conectar con otro usuario o para conectar a otra fuente de
datos, pero hay que tener en cuenta que la transaccin que subyace sea compatible con la
conexin.
Los
parmetros
del
objeto
command pertenecen
a una coleccin llamada
SqlParameterCollection dependiendo del proveedor
colecciones estn compuestas por objetos OleDbParameter o
OleDbParameterCollection o
seleccionado.
Estas
Para crear un nuevo parmetro existen dos posi bilidades, o bien utilizar el operador New de la
clase Parameter, O bien trabajar COn el mtodo CreateParameter de la clase Command.
Para ejecutar un comando se necesita que haya una conexin vlida abierta y dependiendo del
comportamiento que se desee dar al objeto command se utilizar uno de l os siguientes
mtodos:
SingleRow. Se utiliza cuando se espera que la consulta devuelva una nica fila. Los
proveedores de datos estn optimizados con esta opcin para ejecutar este tipo de
consultas.
Como ya se ha descrito anteriormente la clase command pertenece al proveedor de acceso a
datos .NET, de tal forma que existen las clases OleDbCommand y SqlCommand para el
proveedor OLE DB .NET y SQL Server .NET respecti vamente.
Clase OleDbCommand
Esta clase representa una declaracin OLE DB para ejecutar contra un origen de datos OLE
DB. Esta declaracin puede ser un comando SQL, el nombre de un procedimiento almacenado
concreto, o bien cualquier texto que entienda el proveedor OLE DB.
Tiene diferentes constructores:
a) Command Text. Ejecuta una sentencia comprensible por el proveedor.
Por ejemplo:
String strSQL = "UPDATE Employees SET lastname='Isabel'
WHERE EmployeeiD=2";
OleDbCorrunand ObjCmd = new OleDbCorrunand(strSQL,
ObjCnnOLE); ObjCmd.ExecuteNonQuery();
Por ejemplo:
String strSQL = "SELECT COUNT(*) FROM Employees";
OleDbCorrunand ObjCmd = new OleDbCorrunand(strSQL,
ObjCnnOLE); Object ObjAux = ObjCmd.ExecuteScalar();
20/57
Clase SqiCommand
Representa una sentencia T-SQL o un procedimiento almacenado y tiene los siguientes
constructores:
a) Corrunand Text. Ejecuta una sentencia comprensible por SQL Server
b) Corrunand Text + SqlConnection. Ejecuta la sentencia bajo la conexin con SQL
Server subyacente.
e) Corrunand Text + SqlConnection + SqlTransaction. Ejecuta una sentencia en
una transaccin bajo una conexin SQL Server subyacente.
Al ejecutar el comando SqlCorrunand se pueden utilizar los siguientes mtodos
Por ejemplo:
String strSQL
"UPDATE Employees SET
WHERE EmployeeiD=2";
SqlCorrunand ObjCmd = new SqlCorrunand(strSQL,
ObjCnn); ObjCmd.ExecuteNonQuery();
lastname='Alvaro'
Por ejemplo:
String strSQL="SELECT COUNT(*) FROM Employees";
SqlCorrunand ObjCmd=new SqlCorrunand(strSQL, ObjCnn);
Object ObjAux = ObjCmd.ExecuteScalar();
Cuadro de herramientas
Data
Puntero
DataSet
'@, OleDbDataAdapter
OleDbConnection
OleDbCommand
SqiDataAdapter
SqiConnection
eyL SqiCommand
DataView
, ....
S::!mpo nt
Windows Forms
Anillo del Portapapeles
General
--
Explorador de servidores
*Cuadro de herramientas
----------------------------------------------
Propiedades
sqiCommand1 System.Data.SqiCiient.SqiCommand
1 [1
El
Connection
UpdatedRowSource
sqiConnectiont
El Existente
El
!l (DynamicProperties)
El
11$1011!1!lljlll.j1111T1!i;iI!I'glll@l!l'lll
Nuevo
(ninguno)
CommandText
CommandType
Parameters
(Collection)
sqiCommandt
Prvate
El
(Name)
Modifiers
"'
Connection
Connection used by the command.
Generador de consultas
0 0rderiD
OPnxb:t:ID
0
unitPrice
! Quantity
Ailas
Orders
[Order Det.:
[Order Detc
V
V
V
Aceptar
Cancelar
:d
Se parte de que existe una conexin a la base de datos Access llamada Neptuno.
Posteriormente se arrastra un objeto OleDbComrnand del cuadro de herramientas al formulario,
y se asigna la conexin al comando mediante la propiedad connection. Si se accede a la
propiedad comrnandText se establ ece la expresin del comando por medio del generador de
consultas, como se indica en la figura 24.13.
(Rl
Propiedades
oleDbCommand1 System.Data.OieDb.OleDbCommand
El
11 Connection
oleDbConnectionl
UpdatedRowSource Both
El
ll (DynamicProperties)
El
CommandText
CommandType
Parameters
El
El
..
Text
(Collection)
(Name)
oleDbCommandl
f\' odifiers
Private
CommandTimeout 30
CommandTewt
Command text to execute.
AS
de llamada
al procedimiento almacenado
Por ejemplo: Supnga que existe una conexin abierta a la base de datos Northwi nd en SQL
Server llamada ObjCnn.
11 Nota : Debe estar declarado el namespace System .Data . SqlClient
;
SqlCommand objCmd = new SqlCommand( "CustOrdersDetail", ObjCnn) ;
objCmd .CommandT ype = CommandType .StoredProcedure;
SqlParameter objPar =new SqlParameter( "@OrderiD", SqlDbType .I nt) ;
objPa r.Direction = Paramete r Direction . Input
;
objPar .Value = 14 ;
objCmd . Pa rameters . Add (objPa r )
;
SqlDataReader dr = ob jCmd . ExecuteReader(CommandBehavior . CloseConnection)
;
Nota: El proveedor de datos SQL Server .NET no soporta el carcter inten-ogacin para
obtener la informacin de los parmetros, pero s lo hace el proveedor OLE DB .NET.
La clase DataReader
Un objeto de la clase DataReader es muy similar a un Recordset de ADO pero que
nicamente soporta las siguientes caractersticas:
Readonly. Solo lectura.
Forward Only. Solo lee hacia delante.
Estas dos caractersticas hacen que un objeto de la clase DataReader sea muy rpido ya que
no tiene implementadas las caractersticas de edicin, eliminacin, i nsercin, navegacin de
registros hacia atrs, etc. que redundan en un peor rendimiento del objeto. Es una eficiente
alternativa para orgenes de datos desconectados, pero es menos escal able que la clase
oataset, ya que no permite ser heredado por otra clase.
La clase DataReader no tiene constructor y es necesario llamar al mtodo Execu teReader del
objeto command correspondiente para crear un objeto DataReader . Debe ser cerrado
explcitamente.
El mtodo Read se utiliza para leer los registros. Cuando se crea un objeto DataReader
siempre se abre y se posiciona en el primer registro, con lo que no hay que hacer una llamada
explicita a ningn mtodo del tipo MoveFirst. El mtodo Read lee siempre la siguiente tila.
DataReader Ob j DR
; ObjDR .Read() ;
Ob jCMD . ExecuteReader()
Para acceder a los valores de las columnas del objeto DataReader se puede acceder tanto por
nmero como por nombre.
Por ejemplo:
DataReader ObjDR = ObjCMD . ExecuteReader()
; ObjDR . Read() ;
Console . Write(ObjDR .Getint32(0) .ToString()) ;
11 o Console . virite(ObjDR[ "EmployeeiD"] . ToString())
;
Otras propiedades interesantes de la clase DataReader son:
La propiedad RecordsAffected toma un valor determinado cuando se realizan
acciones como inserciones, actualizaciones o eliminaciones de registros. En caso de
realizar consultas de seleccin, esta propiedad no recoge ningn valor hasta que no se
han ledo todos los registros, y se haya cerrado el objeto DataReader correspondiente.
La propiedad NextResult sirve para acceder al si&ruiente conjunto de resultados.
FieldCount devuelve el nmero de columnas o campos del conjunto de registros pero
no aporta informacin acerca del nmero de filas devueltas.
Existen multitud de mtodos especficos de lectura como GetString, GetBoolean, Getint32,
etc. Otros mtodos interesantes del objeto DataReader son GetFieldType y GetValues que
devuelven una matriz de objetos describiendo los valores de las filas.
En la versin actual del framework .NET se describen dos clases que implementan la interface
IDataReader, una para el estndar OLE DB y otra para SQL Server llamadas
OleDbDataReader y SqlDataReader respectivamente.
OleDbDataReader
Es la clase que se utiliza en caso de un acceso de datos estndar y es vlida para cualquier
base de datos, incluido SQL Server. Aunque lgicamente para SQL Server se utilizar la clase
SqlDa taReader.
Cuando se leen datos y la conex10n que subyace est ocupada no se puede hacer otras
operaciones sobre el objeto oleDbDataReader excepto cerrarlo. Y una vez que el objeto
OleDbDataReader est cerrado slo se pueden utilizar dos de sus propiedades: IsClosed() y
RecordsAffected
SqiDataReader
La clase sqlDataReader debe ser
Server. Esta clase es muy similar
caractersticas. Existen multi tud de
que devuelven datos de distintos
GetSqlString, etc.
En este ejemplo se representa, en una lista de un formulario, los empleados de la base de datos
de Northwind en SQL Server. Se crea un proyecto con un formulario, posteriormente se
agrega una etiqueta (labell) y un cuadro de lista (listBoxl) desde el
cuadro de herramientas. Finalmente se escribe en el evento Load del formulario el siguiente
cdigo, cuya finali dad es mostrar cmo trabaja un objeto oataReader para rellenar una lista
con datos de una base de datos.
String strConn = "SERVER=localhost; UID=sa; DATABASE=Northwind;";
string strCmd = "SELECT EmployeeiD, LastName, FirstName FROM Employees";
string strLista;
11 Rellena el DataReader
SqlDataReader ObjDR;
SqlConnection ObjCnn = new SqlConnection(strConn);
SqlCommand ObjCmd = new SqlCommand(strCmd,
ObjCnn); ObjCnn.Open();
ObjDR = ObjCmd.ExecuteReader();
labell.Text = "Lista de Empleados";
strLista =
ObjDR.Getint32(0).ToString(); strLista
+= "- " + ObjDR.GetString(l);
strLista += " "+ ObjDR.GetString(2);
listBoxl.Items.Add(strLista);
ObjCnn.Close();
E!J Form1
GJ(g](g]
Lsi ta de Empleados
1 Davolio Nancy
o
2 Fuller Andrew
3 Leverling Janet
4 Peacock Margaret
5o Buchanan Steven
6 Suyama Michael
7 King Robert
8 Callahan Laura
9 DodsworthAnne
o
La clase DataAdapter
La clase DataAdapter se encarga de las operaciones entre la capa de datos y la capa
intermedia, donde los datos son transferidos. Se puede decir que sirve como puente entre un
objeto Dataset y un origen de datos asociado para recuperar y guardar datos.
Bsicamente permite rellenar (Fill) el objeto Dataset para que sus datos coincidan con los
del origen de datos y permite actualizar (update) el origen de datos para que sus datos
coincidan con los del Dataset.
DataAdapter
SelectCommand
lnsertCommand
UpdateCommand
DeleteCommand
DataSet
TableMappings
DataAdapter (Comrnand
selectComrnand) .
DataAdapter (String
selectconnectionstring) .
selectComma ndText ,
String
Propiedades
sqiDataAdapter1 System.Data.SqiCiient.SqiDataAdapter
1[] (DynamicProperties)
El
(Name)
rvlodifiers
El
El
sqiDataAdapter1
Private
AcceptChangesDuringFill True
sql5electCommand1
11 (DynamicProperties)
(Name)
CommandText
CommandTimeou
t CommandType
11 Connection
Modifiers
Parameters
UpdatedRowSource
sqiSelectCommand1
CustOrdersDetail
30
StoredProcedure
sqiConnectionl
Private
(Collection)
Both
11
El
DeleteCommand
InsertCommand
UpdateCommand
(none)
(none)
(none)
....
30/57
...:J
)1111111
elect:
!nser :
!J..pdate:
.Q.elete:
Cancelar
Establecer parmetros de
Columna de datos
Discount
E xtendedPrice
ProductName
Quantity
UnitPrice
< atrs
iguiente
Einalizar
2) Asistente para generar el COI?junto de datos. Es el asistente que permite generar un objeto
DataSet.
(8]
r. .E,xisten
JWindowsApplication7.DataSet1
.fiuevo
P' 8gregar
Cancelar
Ayuda
3) Asistente para visualizar los datos, que se utiliza para disponer de una vista previa de los
datos que recupera el objeto DataAdapter del origen de datos.
.. Vista previa del adaptador de datos
daptador de datos:
1sqlDataAdapter 1
uen.ar conunto
de datos
.iJ
!:armetros:
1 Tipo de datos
1 Nombre
Int32
sqiDataAdapter1 @OrderiD
1 Valor
10850
labias de datos:
8,5
CustOrdersDetail
30
.errar resultados
15
238
15
382,5
Cerrar
Ayuda
Propiedades
oleDbDataAdapter1 System.Data.OleDb.OieDbDataAdapter
Jf l
(Name)
:'1
rvtodifiers
...
oleDbDataAdapter1
---i
Prvate
AcceptChangesDuringFill
B SelectCommand
11 (DynamicProperties)
(Name)
CommandText
CommandTimeout
CommandType
11 Connection
Modifiers
Parameters
UpdatedRowSource
True
oleDbSelectCommand1
oleDbSelectCommand1
SELECT Apellidos, IdEmpleado, Nombre FROMEmpleados
30
Text
oleDbConnectionl
Private
(Collection)
Both
11
11
DeleteCommand
11 InsertCommand
11 UpdateCommand
oleDbDeleteCommandl
oleDblnsertCommand1
oleDbUpdateCommandl
-...
Update
Qpciones avanzadas...
(lenerador de consultas...
Cancelar
< 8trs
iguiente
1 1
Einalizar
isten
r. Nuevo
JDataSet1
CustOrdersDetail (sqiDataAdapter1)
Empleados (oleDbDataAdapter1)
Cancelar
Ayuda
3) Asistente para visualizar los datos, que se utiliza para disponer de una vista previa de los
datos que recupera el objeto DataAdapter del origen de datos.
.. Vista previa del adaptador de datos
daptador de datos:
!:armetros:
iJ Adaptador
1oleDbDataAdapter1
Nombre
1 Tipo de datos
1 Valor
uen.ar conunto
de datos
iJ
IJI!ll
labias de datos:
Em leados
Andrew
Dodsworth
Janet
Margaret
Steven
6
7
Robert
Laura
Anne
Michael
.orrar resultados
Cerrar
Ayuda
La clase DataSet
La clase Dataset es la clase principal de la arquitectura ADO.NET. Un objeto de esta clase es
una representacin en memoria de los datos en forma relacional. Es un cach de datos
extraidos de un contenedor de datos genrico. El objeto Dataset se rellena con
DataAdapters, con datos locales, o bien con XML.
Relations
DataSet
DataViewManager
DataVIewSettlngs
Tables
DataTable
PrimaryKeys
DefaultView
DataVIew
Constraints
Rows
OataRow
ChildRelations
Columns
DataColum
ParentRelations
ExtendedProperties
Ixisten
r. Jiuevo
joataSet1
Cancelar
Ayuda
El
Empleados
:. ITl Apellidos
,IdEmpleado
L..
Nombre
r:J Constraint1
Ca;eSensrtrve
' ' '1.
Spanish (Spain)
http://www.tempuri.or
11
Locale
Namespace
Prefix
Relatrons
Tables
(Collectlon)
(Collectron)
El
EnforceConstrarnts True
r OataSetName
The name of this cache.
Aceptar
DataSet
1
DataTable
Constraints
DataColumn
DataRow
Relations
1 XML Schema 1
clase
El siguiente cdigo muestra cmo utilizar los objetos Dataset, DataTable, Datacolum y
DataRow.
DataSet objDS = new DataSet() ;
DataTable objTabla = new DataTable( "TablaLocal") ;
11 Preparando las columnas
JI Se vincula al DataGrid
dataGridl.DataMember
" TablaLocal ";
dataGridl.DataSource = objDS ;
Restricciones de datos
Para establecer reglas o restricciones con los objetos en memoria, ADO.NET presenta las
siguientes restricciones, que pueden ser de varios tipos:
ForeignKeyConstraint. Fuerza un vinculo entre dos DataTables del DataSet
Se asegura que la columna que tenga esta restriccin no pueda tener filas
con el mismo dato en esa columna.
Uniqueconstraint.
ADO .NET proporciona adems la propiedad PrimaryKey del objeto Data Table que obtiene
o establece un nmero de columnas como claves primarias de la tabla en memoria, pero este
conjunto de columnas que forman la clave primaria en el objeto DataTable no tiene por que
coincidir con las columnas que forman la clave primaria en la base de datos. El uso de esta
clave ayuda a prevenir errores comunes cuando se actualiza la tabla en memoria y a veces el
uso de esta clave primaria en memoria ahorra la reconciliacin de datos posterior con la base
de datos.
Ejemplo de una aplicacin Maestro-Detalle con Visual Studio .NET
Se pretende realizar una aplicacin .NET que conste de un formulario donde aparezcan los
pedidos en un DataGrid y sus lneas de pedido en otro, y que cada vez que se seleccione un
pedido concreto, aparezcan sus correspondientes lneas en el otro oataGrid. Adems no se
utilizarn los controles de conexin, adaptacin y contenedor de datos incluidos en Visual
Studio .NET.
A) Para una base de datos en SQL
Server
Para realizar este ejemplo se utilizan las tablas Orders y Order Details de la base de datos
Northwind en SQL Server.
40/57
@(g)
1\'thlvo
yer
oyecto
enerar
purr
DatQ.s
t err mlentM
Ve[ltana
Ayyda
l Formi cs'
Solucin 'Window;Applicatio
Data
E'
Components
Windows Forms
ill AsserrblyJnfo.cs
@ li\lllml
lt Puntero
@! WindowsApplicaton
r: 21 Referencias
Label
ll:liUbei
Button
[!bi TextBox
l:ii MalnMenu
P'
Ched<llox
r.
Radiol!utton
LJ GrolJilllox
;:j Pictl.l'e80X
Ptopiedades
O Panel
DatoGrid
1Form l.cs
IJ,..,
l!lil
UstBox
CheckecllistBox
ComboBox
>
111
-1
q. )(
Pr<Jpiedades del-:o:J
t UstView
:r::
Accin de ge Compilacin
TreeVJew
Espacio den
..:::1 Tabcontrol
Herramienta
General
Ex... * cu..
f '---------------------------1
Nombre de d Form!.es
Resul:ados
Generar
1:1 Resultados
1 Resojtlldos
dol fndlce
Una vez definido el objeto Dataset donde va a residir la informacin de los pedidos y de las
lneas de pedido, se procede a cargar el objeto Dataset en el evento Load del formulario
Forml.
prvate void Forml_Load(object
sender, System.EventArgs e)
string
sConexion="database=northwind;uid=sa;pwd=sa;server=localhost;"
;
DataSet odsPedidos = new DataSet();
/1 Se rellena el DataSet con la tabla Pedidos (Orders)
string sSQLPedidos = "SELECT * FROM Orders";
SqlDataAdapter ObjDA = new
SqlDataAdapter(sSQLPedidos,sConexion);
ObjDA.Fill(odsPedidos,"Orders");
//Se rellena el DataSet con las lineas del Pedido (Order
Details) string sSQLLineas = "SELECT * FROM [Order Details]";
ObjDA.SelectCommand.CommandText = sSQLLineas;
ObjDA.Fill(odsPedidos,"OrderDetails");
//Se establece la relacin entre las entidades en el
DataSet DataColumn ObjColPedidos =
odsPedidos.Tables["Orders"].Columns["OrderiD"];
DataColumn ObjColLineas =
odsPedidos.Tables["OrderDetails"].Columns["OrderiD"];
DataRelation ObjRelacion = new
DataRelation("relPedidos",ObjColPedidos,ObjColLineas)
;
odsPedidos.Relations.Add(ObjRelacion);
//Se vincula a los DataGrids la informacin
dataGridl.DataSource odsPedidos;
dataGridl.DataMember "Orders";
dataGrid2.DataSource
odsPedidos;
dataGrid2.DataMembe
"Orders.relPedidos";
r
LJ
Form1
6
4
TOMSP
HANAR
817/1996
81711996
9/7/1996
101711996
111711996
VICTE
SUPRO
4
3
HANAA
CHOPS
10
9.8
72
34.8
5/8/1 996
5/8/1 996
6/8/1 996
2417/1 996
8/8/1 996
10/711
121711
151711
11/711
una
base
de
datos
Se elige uno cualquiera de los dos DataAdapter y se genera el conjunto de datos o Dataset
desde las propiedades del mismo. En la ventana del asistente de la generacin del oataset se
elige tambin el otro DataAdapter.
fxisten
r. Nuevo
joataSet1
Cancelar
Ayuda
Figura 24.32 Asistente para generar un Dataset a partir de dos objetos DataAdapter .
Una vez que el Dataset ha sido generado, se procede a crear la relacin entre las tablas
generadas en el Dataset -Productos y Proveedores- que posteriormente rellenarn los
DataGrid del formulario. Para crear la relacin se selecciona el campo IDProveedor de la
tabla Proveedores y se accede al men contextua! mediante el botn derecho para crear una
relacin que relaciona un proveedor con varios productos.
Forml .cs [Diseo]*
Oata5et1.Msd"'
l>
E
E
E CdPostal
E Direccin
string
string
string
E Fax
string
'i']E IdProveedor
int
E NombreCompa string
E
E
E
E
E
1 CJ
NombreContac string
PginaPrincipa string
Pas
string
Regin
string
Telfono
string
DataSet 1 El XML
E fds
..
'
.
'.
'
-o-
'
'
E IdCategora
'i']E IdProducto
E IdProveedor
E NiveiNuevoPe
'
int
int
int
int
E
NombreProduc string
Suspendido
boolean
E PrecioUnidad
decimal
E
E UnidadesEnExi short
E UnidadesEnPe short
Se accede a la propiedad DataSource del DataGridl que es donde se quiere exponer los
proveedores, y se sel ecciona el datasetll como valor y en la propiedad DataMember se
selecciona Proveedores.
Propiedades
dataGrid1 System.Windows.Forms.DataGrid
El
ll (DataBindings)
DataMember
DataSource
TableStyles
Tag
(none)
(Name)
data5et11.Proveedores
dataSet11.Productos
data5et11
(nene)
Locked
rv'lodifiers
Prvate
El
ase
F1
Auto Format
Forml_Load(object sender ,
oleDbDataAdapterl .Fill(dataSetll) ;
oleDbDataAdapter2 . Fill(dataSetll) ;
System . EventArgs
GJJ[Rl
Form1
"C:\XML\ejemplo.xml"
El objeto DataSet tiene las propiedades Namespace que establece u obtiene el namespace
usado cuando se lee o escribe el documento XNIL, y Prefix que recoge o establece el prefijo
XML que sirve de alias del namespace del Dataset.
Para crear un Dataset adems de hacerlo con el mtodo Fill del DataAdapter, se puede
partir de cdigo XML+XSD. Tambin existen otros objetos aparte del oataset leer
informacin en XML como son XmlReader, TextReader o StreamReader.
System.Xml .XmlReader ;
System. IO . StreamReader
; System.IO . TextReader
En Visual Studio .NET se puede ver el esquema del objeto Dataset, utilizando la opcin
correspondiente.
<! X
Pgina deinicio 1 Forml.cs[Diseo] odsPedidos. esd* 1
<xsd:schema id="odsPedidos" tar:getNB!llespace="http:1/www .tempur:i.
<xsd:element nB!lle="odsPedidos" msdata:IsDataSet="tr:ue" msdatc<xsd:complexType>
<xsd:choice maxOccur:s="unbouncted">
<xsct:element nB!lle="Or:cter: x0020 Details">
<xsd:complexType>
<xsd:sequence>
<xsd:element nB!lle="Or:der:ID" type="xsc
<xsd:element nB!lle="Pr:oductiD" type=">
<xsd:element nB!lle="UnitPr:ice" type=">
<xsd:element nB!lle="Quantity" type="x
<xsd:element nB!lle="Discount" type="x
</xsd:sequence>
</xsd:complexType>
</xsd:element>
....
e-:
DataSet
..
..
1 El XML
_.r , _
Se aaden 10 filas.
DataRow ObjFila;
for(i = O;i < 10 ;i++l
ObjFila = ObjTabla.NewRow();
ObjFila["Columna"] = "tem " +
i; ObjTabla.Rows.Add(ObjFila);
ObjTabla.AcceptChanges();
11
ObjVista.RowStateFilter =
DataViewRowState.Added 1 DataViewRowState.ModifiedCurrent;
1/
11
ObjTabla.Rows[l].Delete()
;
ObjTabla.Rows[2).Delete()
;
ObjTabla.Rows[3).Delete()
;
11
11
11
dv,string
Adems el objeto Dataview soporta las operaciones generales de edicin por medio de las
propiedades AllowNew, AllowDelete y AllowEdit para establecer las operaciones bsicas y
los mtodos AddNew y Delete para agregar una fila y eliminarla respecti vamente.
Las operaciones de bsqueda del objeto oataview vienen reflejadas por el mtodo Find que
devuelve el ndice de la fila encontrada por los criterios de filtrado.
Por ejemplo:
DataView ObjDV;
Integer i;
Object vals[l];
DataTable ObjTabla;
ObjDV = New DataView(ObjTabla);
ObjDV.Sort = "Customers";
Para crear un control DataView basta con arrastrarlo al formulario. Una vez asignado al
formulario se establece la propiedad Table donde se selecciona la tabla del Dataset deseada.
Propiedades
data't'iewl System.Data.DataView
11a
------------------------------
11 (DynamicProperties)
AllowDelete
AllowEdit
Allowrllew
ApplyDefaultSort
RowFilter
RowStateFilter
True
True
True
False
CurrentRows
Sort
Table
odsPedidosl .Orders
l;l odsPedidosl
(Name)
Modifiers
. Order Details
; &DI
(ninguno)
Table
Indicates the table this DataView use
L----------------------w
La clase DataRelation
Una relacin es un vinculo dinmico establecido entre una o ms columnas del mismo tipo de
dos tablas y el objeto oataRelation representa una relacin maestro-detalle entre dos tablas.
Una vez que se ha establecido la relacin entre dos tablas cualquier cambio que infrinja la
relacin provocar una excepcin . Las relaciones admiten cambios en cascada desde la tabla
maestro a la tabla detalle aiiadiendo un objeto ForeignKeyConstraint a la coleccin de
restricciones del objeto oataTable. A continuacin se muestra un ejemplo en el que se define
una relacin de actualizacin en cascada.
11 Supnga que se tiene un DataSet llamado ObjDS
11
con las tablas Orders y OrderDetails
DataColumn ObjColMaestro = objDS.Tables("Orders"}.Columns("OrderiD"};
DataColumn ObjColDetalle =
objDS.Tables("OrderDetails"}.Columns("OrderiD"}; ForeignKeyConstraint
ObjFK = new ForeignKeyConstraint("FK_OD_OrderiD", ObjColMaestro,
ObjColDetalle};
50/57
11 Se crea la actualizacin
ObjFK.UpdateRule
Rule.Cascade;
en cascada
=
/ 1
la
A partir de aqu , estando en una fila de la tabla maestro es posible acceder a las filas de la
tabla detalle directamente utilizando la el mtodo GetChildRows del objeto DataRow, que
devuelve un array de objetos DataRow.
Si se utilizan relaciones se debe tener en cuenta que no son transitivas, de tal forma que si la
tabla A est relacionada con la tabla B, y por otro lado la tabla B est relacionada con la tabla
e, no se puede decir que las tablas A y e estn relacionadas.
Creacin de una relacin con Visual Studio .NET.
Para crear una relacin en un Dataset desde el diseador de Visual Studio .NET basta con
acceder a un Dataset donde existan varias tablas y seleccionar la opcin de agegar relacin.
Una vez realizada esta accin se pueden configurar los el ementos tanto primario como
secundario, y las columnas que van a formar parte de la relacin. Adems se pueden
configurar las reglas para actualizar o eliminar en cascada.
(8]
Editar r elacin
jiiD!f:tM
fiambre:
Para definir una relacin (keyref), seleccione el elemento y la clave primarios, seleccione el
elemento secundario y, a continuacin, seleccione el campo secundario correspondiente a
cada campo primario.
emento primario:
Elemento ecundario:
o,. J r_de-rs----- -
- -
Qave:
jorders_Constraintl
Nuevo"-..
CamQ.os:
Eliminar regla:
Jcascade
Aceptar
c_an_c_e_l
a_r -J
iJ
Ay_u_d_a_...J
string int
dateTime
E RequiredDat
dateTime
dateTime
odsPedidos.Hsd*
<1 1> X
Order Details)
---<0--.
int
int
UnitPrice
Quantity
E Discount
O DataSet
.....
decimal
short
float
El XML
Figura 24.39. Representacin grfica del esquema del Dataset con Visual Studio
Una vez que la relacin ha sido establecida se puede observar en el ejemplo maestro-detalle
anterior, que al actualizar el valor de la columna order i D 10251 por el valor 21,
automticamente las fi las relacionas de l a tabla order oetails cambian a 21, debido a
la configuracin en cascada, para la actualizacin, establecida en la relacin.
CJ[QJ
Form1
HANAR
VICTE
SUPRD
HANAR
CHOPS
4
3
4
3
8/7/1996
817/1996
917/1996
10/7/1996
11/7/1996
16/8/1996
5/8/1996
5/8/1996
6/8/1 996
2417/1 996
8/8/1996
121711
15/7/1
1117/1
Descripcin
Unchanged
No
se han producido
cambios
desde
la ultima
llamada
AcceptChanges
Modified
Deleted
Detached
Una de las formas de aadir nuevas filas a un objeto oataTable es crear un objeto DataRow,
rellenarlo y luego agregarlo al objeto DataTable.
Por ejemplo:
DataRow ObjFila = ObjTabla . NewRow()
ObjFila[ "DNI "] = "9999999";
ObjFila[ "Nombre") = "Alvaro";
ObjFila[ "Apellidos " ) = "Garcia Lopez ";
ObjFila [ "Email "1 = "agarcia@empresa.es 11
; ObjTabla . Rows .Add(ObjFila) ;
Para borrar filas de un objeto DataTable basta seleccionar una serie de filas y luego llamar al
mtodo Delete O Remove.
Delete marca la fila como borrada pero mantiene el registro original y permite deshacer la
eliminacin.
Las acciones de borrado de fi l as se real izan en el objeto oataTable que est en memoria. A la
hora de actualizar con el origen de datos se debe tener en cuenta que una fila borrada con
Remove no es percibida como borrada y por lo tanto no es borrada del origen de datos. Sin
embargo la fila que es borrada con el mtodo Delete es borrada en el origen de datos.
El hecho de marcar una fila como borrada (oelete) ind ica que l a fi l a ser eliminada de
la tabla despus de llamar a AcceptChanges. Cuando se realiza esta operacin la
propiedad RowState cambia al estado Deleted. Si se invoca el mtodo RejectChanges
entonces la propiedad Rowstate volver a su estado inicial.
En el caso de que se borre una fila que justo se haba aadido a la tabla y que haba sido
marcada como New utilizando Delete, Delete funciona como Remove.
Cuando se desea reconciliar las tablas en memoria con las tablas en el origen de datos se
utiliza el mtodo GetChanges para crear un segundo Dataset en local que contiene slo los
cambios que se van a hacer (filas marcadas). Posteriormente se examina la propiedad
HasErrors del Dataset para ver si existen errores en alguna de las filas de las tablas del
propio oataset. Si se producen errores, se deber reconciliar antes de actualizar los datos del
Dataset (memoria) con el origen de datos. Para recoger los errores se util iza el mtodo
GetErrors que devuelve los objetos DataRow que tienen errores. Si se posible reconciliar los
errores entonces se llama al mtodo Merge para volver a incorporar los cambios del segundo
Dataset al primero.
Para actualizar el origen de datos y refrescar la tabla se llama al mtodo Accept Changes y en
caso de que se desee deshacer la actual izaci n se llamar al mtodo Re j ectchanges.
El mtodo Accept Changes se puede aplicar al objeto Da t aSet, al objeto DataTable o al
objeto DataRow, y funciona en cascada, es decir, que si se aplica sobre el Dataset, se est
aplicando sobre todas las tablas del oataset, y si se aplica sobre el objeto oa t aTable, se est
apl i cando sobre todas las filas de esa tabla.
Cuando se llama al mtodo AcceptChanges
Los objetos DataRow que estn todava en edicin se almacenan
La propiedad RowState de cada fila cambia adecuadamente.
Las filas nuevas y modificadas pasan a ser filas normales y las borradas (oeleted)
pasan a eliminadas definitivamente.
Cuando se llama al mtodo Rej ectchanges se cancelan las filas que estaban en edicin, se
eliminan los nuevos registros y las filas modificadas o borradas (oelet ed) pasan a su estado
original.
En cuanto a la actualizacin del origen de datos, se recomienda utilizar como primera opcin
comandos SQL y como segunda opcin l a actualizacin tipo Batch o masiva que consiste en
un proceso que extrae datos del lado cliente y los actualiza en la base de datos. Este tipo de
actualizacin ( Batch ) se puede realizar con un conjunto de objetos DataRow, con un objeto
Dataset o con un objeto DataTable. Para realizar la actualizacin tipo Batch se ha de utilizar
el mtodo update del objeto DataAdapter que realiza una llamada a los comandos I NSERT,
UPDATE y DEL ETE para cada fila agregada, actualizada o borrada. Es conveniente utilizar el
mtodo Get changes para enviar al origen de datos un Dataset ms pequeo.
sender, System.EventArgs
e)
sqlDataAdapterPedidos.Fill(dataSetPedidos,"Orders");
GJ(g]
form1
Actualizar
e)
if (dataSetPedidos.HasChanges())
try
{
catch (DBConcurrencyException
dbError)
/1 Resolver el conflicto
MessageBox.Show("Error:" + dbError.ToString());