Professional Documents
Culture Documents
com
Agradecimientos ..................................................................................................................... 6
..
Introduccion
.......................................................................................................
...................................................................................
1. Terminologia y conceptos .............................................................................
18
20
20
21
21
22
24
25
26
27
29
29
30
32
33
33
34
fndice de contenidos
.......................................................................................
iQu6 es SQL?..........................................................................................................................
Partes de SQL ...................................................................................................................
Derivados de SQL ...........................................................................................................
Ejecuci6n de sentencias SQL ........................................................................................
DDL ..........................................................................................................................................
Creaci6n de una base de datos .....................................................................................
Creaci6n de tablas ...........................................................................................................
Modificaci6n y borrado de tablas ...............................................................................
Otras operaciones de definici6n de datos .................................................................
DML ..........................................................................................................................................
Inserci6n de datos ...........................................................................................................
Recuperaci6n de datos ...................................................................................................
Alias de tablas ............................................................................................................
Selecci6n de filas ........................................................................................................
Condicionales complejos ..........................................................................................
Orden de las filas .......................................................................................................
Expresiones y funciones de resumen ....................................................................
Agrupamiento .............................................................................................................
Enlaces entre tablas ...................................................................................................
Consultas dentro de consultas ...............................................................................
Actualizacibn de datos ...................................................................................................
Eliminaci6n de datos ......................................................................................................
DCL ...........................................................................................................................................
Derivados de SQL .................................................................................................................
Transact-SQL ....................................................................................................................
Variables y tipos de datos .......................................................................................
Evaluaci6n de expresiones ......................................................................................
Condicionales y bucles .............................................................................................
Codificaci6n de procedimientos almacenados ...................................................
PL / SQL ..............................................................................................................................
www.detodoprogramacion.com
36
36
37
37
38
39
40
40
41
41
43
43
44
46
46
47
47
48
51
51
54
54
56
57
58
58
59
59
61
61
62
62
63
64
65
65
66
66
67
68
68
69
69
3 Origenes de datos
..........................................................................................
70
70
71
71
72
74
75
76
77
79
79
81
83
84
85
87
89
90
91
93
95
96
97
98
104
105
106
110
111
113
115
116
117
118
120
120
121
121
123
125
125
128
133
.........................................................................................
..
4 . Introduccion a ADO.NET ..........................................................................
Objetivos del modelo ADO.NET .....................................................................................
Representach interna en XML ......................................................................................
Ausencia de cursores de datos ........................................................................................
Cursores de lectura .......................................................................................................
Soluci6n multiprop6sito ....................................................................................................
Configuraci6n de 10s clientes ...........................................................................................
Resumen ................................................................................................................................
5 Modelo de objetos
.......................................................................................
. . al origen de datos
6 Conexion
........................................................................
133
134
137
138
139
141
143
144
144
148
150
152
153
154
155
156
156
159
160
161
162
163
164
165
166
167
168
168
169
170
172
173
174
174
176
176
177
178
178
..........................................
. . de datos
8 Recuperacion
................................................................................
178
181
181
181
183
183
183
185
186
188
189
193
194
194
196
197
199
200
201
202
203
204
206
206
209
210
212
214
215
216
217
217
219
220
222
223
226
228
228
229
230
fndice de contenidos
9. Conjuntos de datos
.....................................................................................
10 Relaciones y vistas
.....................................................................................
11. XML
............................................................................................................
231
233
234
235
236
237
237
238
239
241
243
244
246
250
253
253
255
256
258
260
261
264
267
270
272
274
276
277
278
278
279
281
284
286
289
290
........................................................................
12. Capacidades de datos en Visual Studio .NET ......................................
...............................................................
296
297
297
298
298
301
305
307
309
310
311
312
314
317
318
319
321
322
322
324
325
326
328
328
331
332
333
334
336
336
340
341
343
343
346
347
350
351
352
354
fndice de contenidos
...................................................
15 Formularios de datos
................................................................................
355
356
358
358
362
362
363
365
366
368
369
370
374
376
377
378
379
379
380
380
381
385
386
388
389
390
391
391
392
393
395
396
397
401
402
404
404
405
406
408
410
......................................................
. . genCrica .....................................................................................
16. Conexion
.............................................
..........................................................................
............................................
411
412
413
414
415
418
420
421
423
429
429
430
431
431
434
435
436
437
438
438
442
443
444
445
447
450
.............................................................
451
453
453
454
458
......................................
459
460
462
464
465
fndice de contenidos
......................................................
.......................................................
........................................................................................................
B. Contenido del CD-ROM ............................................................................
A . Glosario
Indice alfabCtico
...............................................................................................
www.detodoprogramacion.com
468
470
471
474
479
485
487
488
488
489
492
493
495
496
496
497
498
500
506
507
509
51 1
www.detodoprogramacion.com
Las soluciones o mecanismos de acceso a datos han sido y, por ahora, seguirfin
siendo muchos y diversos. Tenemos lenguajes que gestionan directamente sus
formatos de archivo, C O ~ Oes el caso de 10s conocidos como archivos indexados de
COBOL; motores de acceso a datos que pueden usarse desde distintos lenguajes,
como DAO, ADO o BDE; bases de datos que cuentan con su propio lenguaje de
programaci6n, desde dBase y Access hasta cualquier RDBMS actual, y plataformas que cuentan con sus propios servicios de datos, como JDBC y ADO.NET.
Normalmente cada una de esas soluciones est6 asociada a una determinada herramienta de desarrollo o lenguaje, o bien a un modelo de objetos, sistema o plataforma. DAO y ADO, por poner un ejemplo, s610 existen en Windows y, adem&,
s610 pueden ser usados desde lenguajes que contemplan el trabajo con objetos
COM, mientras que JDBC es Litil s610 en caso de que se trabaje con el lenguaje de
programaci6n Java.
Cada una de estas soluciones tiene sus particularidades, problemas, ventajas y
requerimientos. La elecci6n de una de ellas suele limitar 10s origenes de datos a 10s
que puede accederse, determinar el rendimiento y la escalabilidad de las aplicaciones. No es el objetivo de este libro entrar en 10s detalles especificos de cada una
de ellas sino, como puede imaginar, centrarnos en el estudio de ADO.NET.
de datos; aplicaciones en varias capas o n-tier y, por supuesto, aplicaciones distribuidas basadas en Internet.
Con ADO.NET es posible acceder a practicamente cualquier origen de datos,
ya sea local o remoto, estructurado o jerArquico, basado en DBMS o no. El rendimiento obtenido es, en la mayoria de 10s casos, superior a la de otras soluciones
existentes en la actualidad. En ADO.NET se ha optado por un nuevo esquema de
trabajo con 10s datos, un esquema en el que se prescinde de elementos como la
conexi6n continua con el servidor u origen de datos, la ejecuci6n de un cursor de
acceso a la informacion o la representaci6n binaria de forma interna. El resultado
es un increment0 en rendimiento, escalabilidad, compatibilidad y transportabilidad,
asi como un menor us0 de recursos en 10s servidores.
Como tendr6 ocasi6n de ver en este libro, podemos usar ADO.NET para trabajar con documentos XML, bases de datos Microsoft Access, SQL Server, Oracle y,
en general, cualquier origen para el que exista un controlador OLE DB u ODBC lo
que, en la prgctica, significa pricticamente todos 10s origenes posibles.
Aunque es posible utilizar todos 10s servicios de ADO.NET sin m6s ayuda que
un editor de textos simple y el compilador de Visual Basic .NET, ejecutable desde
la linea de comandos, el entorno de Visual Studio .NET puede, en ocasiones, facilitar de forma notable nuestro trabajo. Dicho entorno cuenta con elementos que,
como el Explorador de servidores, nos permiten establecer conexiones con origenes de datos, seleccionar conjuntos de informacibn, definirlos, crear autom6ticamente 10s objetos necesarios para acceder a ellos desde programa, etc.
Independientemente de que est4 utilizando VisuaZ Basic . N E T Standard o alguna
de las ediciones de Visual Studio .NET, Professional, Enterprise Developer o Enterprise
Architect, hay ciertas operaciones b6sicas que siempre tendremos a1 alcance. Otras,
por el contrario, s610 est6n disponibles en las ediciones superiores.
Una vez que nos hayamos familiarizado con ADO.NET, y sepamos c6mo usar
sus clases para efectuar todas las operaciones habituales, veremos cdmo aprovechar las posibilidades del entorno de Visual Studio .NET.
El libro que tiene en sus manos no est6 pensado para aprender a programar con
Visual Basic .NET, familiarizarse con el entorno de Visual Studio .NET o bien conocer 10s servicios bdsicos de la plataforma .NET para la creaci6n de aplicaciones
Windows, aplicaciones y servicios Web. Todos esos conocimientos se asume que el
lector ya 10s tiene, lo cual nos permite centrarnos especificamente en un tema: el
acceso a datos con ADO.NET desde Visual Basic .NET. No es &te, por tanto, un
www.detodoprogramacion.com
In troduccidn
libro adecuado para aquellos que desconocen el lenguaje o el entorno, a 10s cuales
recomendamos titulos como Programacidn con Visual Basic .NET o Guia pra'ctica para
usuarios de Visual Studio .NET, de la misma editorial y de tip0 mas gen6rico.
A diferencia de otros titulos, en 6ste no se parte de que el lector conoce ADO, el
mecanismo de acceso a datos empleado en Visual Basic 6.0 y otras herramientas
previas a la aparici6n de Visual Studio .NET, ni DAO ni ninguna otra soluci6n previa. No encontrari, por tanto, comparativas entre 10s objetos de ADO y ADO.NET
o descripcih de procesos tomando como base 10s de ADO. Con este libro podra
usar ADO.NET sin necesidad de conocer previamente ningh-i otro mecanismo de
acceso a datos, tan s610 necesita saber c6mo utilizar Visual Basic .NET para construir aplicaciones Windows y Web.
Para alcanzar estos objetivos es indispensable que su configuraci6n, la del equiPO donde va a probar 10s ejemplos propuestos, cuente con estos elementos:
0
Tener instalado Visual Basic .NET Standard o algunas de las ediciones de Visual Studio .NET. El autor ha empleado la edici6n Enterprise Architect de Visual Studio .NET, si bien la mayor parte del contenido es aplicable a cualquier
edicih, incluida la citada Visual Basic .NET Standard.
Contar con una unidad de CD-ROM desde la cual recuperar 10s ejemplos del
disco que acompaiia a1 libro, copiindolos en su sistema.
Disponer del software cliente y servidor de datos usado en 10s ejemplos, entre otros Microsoft Access, Microsoft SQL Server 7/2000, Oracle 8i e InterBase.
En 10s capitulos respectivos se tratarin las bases de estas aplicaciones y, en
algunos casos, se indicara c6mo obtenerlas, instalarlas y configurarlas en su
sistema.
A1 redactar este libro se ha tenido como primer punto de mira el contenido didictico, por ello 10s fundamentos y conocimientos se van abordando de manera
escalonada, capitulo a capitulo, asumiendo que 6sa sera la secuencia inicial de lectura. No obstante, muchos capitulos tambien pueden usarse a mod0 de consulta o
referencia, una vez que haya adquirido la visi6n global de 10s temas que se tratan.
El libro esti dividido en cuatro partes: Sentar las bases, ADO.NET, Visual Studio
.NET y Resolucidn de cusos concretos. La primera de ellas, compuesta de tres capitulos, nos servirii para conocer la terminologia que va a utilizarse a lo largo del libro,
asi como unos fundamentos del lenguaje SQL y ciertas aplicaciones que pueden
actuar como origenes de datos.
La segunda parte se centra en el estudio de ADO.NET, sus clases y la forma de
usarlas para conectar con un origen de datos, recuperar informacih, manipularla
y devolverla. Aprender6 a acceder a distintos origenes de datos, establecer relaciones y restricciones, trabajar con conjuntos de datos o usar XML con ,ADO.NET.
www.detodoprogramacion.com
B, Internet
www.detodoprogramacion.com
lntroduccidn
En caso de encontrar algun problema con este libro o el CD-ROM que le acompaiia, el lector puede recurrir tanto a la editorial como directamente a1 autor.
Desde la Web de la editorial, en http: //www.AnayaMultimedia.com,puede acceder a la secci6n Atencion al cliente para acceder a1 soporte tbcnico, asi como
a las secciones de Complementos y Fe de erratas.
Si desea ponerse en contact0 con el autor para plantear exclusivamente alguna
cuesti6n relativa a este libro, puede hacerlo a traves de la Web Torre de Babe2, en
http://www.fcharte.com.
www.detodoprogramacion.com
www.detodoprogramacion.com
Este libro estA dirigido a desarrolladores que necesitan utilizar 10s servicios de
ADO.NET para trabajar con bases de datos, documentos XML y, en general, cualquier origen de datos. Como programadores, el autor asume que ya se conocen 10s
terminos habituales en cualquier lenguaje de programach: variable, bucle, sentencia, expresi6n condicional, compilaci6n, etc. No se asume, por el contrario, ningiin conocimiento relativo a1 trabajo con datos, campo que tambien cuenta con sus
propios conceptos y terminologia especifica.
A pesar de no ser dste un titulo dedicado a 10s fundamentos de tratamiento de
datos, tema sobre el que encontrard libros monogrdficos, en este capitulo se abordan 10s elementos que podrian considerarse bisicos: ique es un DBMS o el lenguaje SQL?, jcdmo se estructuran 10s datos en filas y columnas? o iqu6 es XML? son
algunos de 10s contenidos de este capitulo.
El objetivo no es otro que facilitarle 10s conocimientos indispensables, conceptos y tdrminos, para que pueda leer c6modamente 10s demis capitulos de este libro.
Posteriormente, dependiendo de su inter& y necesidades, puede recurrir a textos
que traten con mayor profundidad la teoria del tratamiento de bases de datos.
Origenes de datos
Los servicios de acceso a datos .NET, conocidos como ADO.NET, pueden ser
usados para operar sobre origenes de datos diversos, no exclusivamente sobre lo
www.detodoprogramacion.com
1. Terminologia y conceptos
que se conoce como bases de datos. Un origen de datos puede ser una base de dat
SQL Server, un documento XML, una hoja de cdculo Microsoft Excel, el Direct
rio Activo de Windows 0, en general, cualquier recurso para el que exista un pr
veedor de datos .NET.
El origen d e datos, por tanto, es el recurso, ya sea local o remoto, del que va a e
traerse o en el que se va a introducir informacibn, teniendo un sentido mucho m
amplio que el de base de datos. En el texto encontrar6 ambas expresiones, la prim
ra cuando se quiera dar un sentido general y la segunda a1 hacer referencia concr
ta a un DBMS.
Utilizando el paradigma del origen de datos, sin asumir su localizacibn, estruct
ra ni naturaleza, ADO.NET es realmente un mecanismo de acceso a datos unive
sal. Esto tiene como ventaja fundamental el ahorro de trabajo para el desarrollado
a1 no tener que recurrir a sistemas diferentes dependiendo de 10s datos que se pr
tendan manipular o recuperar.
l-----l
Figura 1.1. ALlO.NET actua como intermediario entre las aplicaciones y 10s posibles
origenes de datos, utilizando para ello diversos proveedores de acceso
www.detodoprogramacion.com
Los servicios de ADO.NET pueden utilizarse desde una aplicacion con interfaz
de usuario, un componente que se ejecuta en un servidor, un servicio Windows
o Web. En general, es posible recurrir a ADO.NET desde cualquier punto de
una aplicacion que se ejecute en un sistema donde este disponible la plataforma .NET.
S
El origen de datos por excelencia es la base d e datos. Una base de datos puede
definirse como uno o mds archivos en 10s que se almacenan 10s datos y toda la informaci6n que describe su estructura, fundamental para poder operar sobre ellos.
Las bases de datos pueden ser de distintas categorias, siendo el tip0 mds habitual
el de las bases de datos relacionales. Por otra parte, las bases de datos tambikn se
dividen en dos clases: bases de datos de escritorio y servidores de bases de datos.
Las primeras estiin dirigidas principalmente a usuarios con ciertos conocimientos
que le permiten crear y mantener sus estructuras de informacibn, raz6n por la cual
estas bases de datos cuentan con una interfaz de usuario bastante completa y amigable. Es el caso de Microsoft Access, dBase o Paradox. Tambien se caracterizan
por no contar con un middleware que permita tener el software en una msquina y
10s datos en otra distinta, es decir, son bases de datos locales.
Se llama servidor de datos a una aplicaci6n que se encarga de manipular fisicamente 10s datos, ocupdndose de su almacenamiento y recuperaci6n de 10s archivos
en que se encuentran. De esta forma las aplicaciones no tienen que conocer la estructura de dichos archivos, limitiindose a solicitar a1 servidor las operaciones que
quiere efectuar. Tambikn suele conocerse como servidor d e datos a1 ordenador en el
que se ejecuta dicha aplicaci6n.
Aunque una base de datos de escritorio o local puede colocarse en una unidad
compartida de red, facilitando el acceso a ella desde diferentes puestos, no es la
configuraci6n miis adecuada para construir un acceso multiusuario. En este caso
resultan mucho miis eficientes y seguros 10s servidores de bases de datos.
MS y RDBMS
Los servidores de bases de datos son sistemas de administraci6n de informaci6n o DBMS, aplicaciones cuyo objetivo no es s610 almacenar y recuperar datos,
www.detodoprogramacion.com
1. Terrninologia y conceptos
Tambien se conoce a 10s DBMS por sus siglas en nuestro idioma, SGBD, aunque su us0 es menos habitual.
Durante aiios, las bases de datos se han utilizado en sistemas que se ajustaban
una arquitectura conocida como clientelservidor. En ella 10s datos residen en u
ordenador que actua como servidor, ejecutando el software que denomin6bamo
antes servidor de datos. Los usuarios, desde ordenadores remotos, se sirven de u
software cliente para comunicarse con el servidor de datos. Ese software cliente e
especifico para cada servidor de datos existente.
Supongamos que estd utilizando SQL Server como servidor de datos, estand
instalado dicho software en una mAquina que reside en un centro de proceso d
datos. Desde su ordenador, ubicado en otra planta del mismo edificio, se comun
caria con ese servidor mediante el software cliente de SQL Server que, 16gicame
te, deberia estar instalado en su m6quina. Dicho software cliente no serviria par
comunicar con un servidor Oracle o DB2, por poner un caso, teniendo que dispo
ner del software cliente que corresponda en cada caso.
Las bases de datos de escritorio, como 10s citados Access, dBase y Paradox,
no son servidores de datos y, por tanto, no pueden utilizarse en una arquitectura clientelservidor real, a pesar de la posibilidad indicada antes de colocar 10s
archivos de datos en una unidad compartida de red. La diferencia estA en que
cada maquina accederia a sus datos directamente, como si 10s archivos se encontrasen en ella, mientras que en una arquitectura cliente/servidor real el
www.detodoprogramacion.com
cliente nunca accede directamente a 10s datos, sin0 que delega ese trabajo en
el servidor.
~
En la figura 1.2 puede ver representada una tipica configuracibn cliente / servidor. Concretamente aparece un servidor de datos, en la parte inferior, y varios
clientes, en la superior. Aunque en dicha imagen no se ha representado, se supone
que tanto clientes como servidor tienen sus respectivos paquetes de software instalados.
Cliente 1
Cliente 3
Cliente 2
Router
Servidor
de datos
1 . Terrninologi'a y conceptos
Cliente I
Cliente 2
aplicaciones
Cliente 3
Servidor
de datos
En este modelo 10s clientes no tienen acceso direct0 a 10s datos, trabajo que que
da en manos de 10s componentes que se ejecutan en el servidor de aplicaciones
www.detodoprogramacion.com
Nosotros contamos con 10s servicios de ADO.NET para acceder a 10s origenes
de datos, utilizando para ello un modelo de objetos y componentes que tendra
ocasi6n de conocer en un capitulo posterior. ADO.NET, a su vez, precisa de otros
www.detodoprogramacion.com
1 . Terminologi'a y conceptos
elementos para poder efectuar su trabajo, entre ellos 10s proveedores y 10s controladores.
Un proveedor ADO.NET es una implementacibn especifica de una serie de com
ponentes que facilitan el acceso a un determinado origen de datos. Visual Basic
.NET incorpora por defect0 dos proveedores de datos .NET: uno para SQL Serve
y otro capaz de emplear cualquier controlador OLE DB. Hay disponibles dos m6s
que instalar6 posteriormente, uno para Oracle y otro dirigido a1 us0 de un contro
lador ODBC.
Los proveedores .NET aparecen, desde el punto de vista del desarrollador, como
una serie de definiciones de clases alojadas en un Ambit0 con nombre o namespace
clases que pueden usarse para acceder a un determinado origen de datos. El pro
veedor de datos para SQL Server y el de Oracle son especificos, comunicindose
directamente con el software cliente de esas dos bases de datos sin intermediario
alguno. Los proveedores OLE DB y ODBC, por el contrario, son de tip0 genkrico
diseiiados para aprovechar todos 10s controladores que ya hay disponibles de eso
dos tipos.
Suponga que quiere, desde una aplicaci6n propia, recuperar datos de una hoja
de cilculo Excel o comunicarse con una base de datos IBM DB2 o InterBase. No
hay proveedores .NET especificos para estos tipos de datos, a1 menos no por el mo
mento, y por ello hay que recurrir a las soluciones genericas. Mediante un contro
lador OLE DB se puede acceder a Excel, y mediante ODBC a IBM DB2 o InterBase
En estos casos empleariamos un m6dulo o componente de software adicional a
proveedor OLE DB u ODBC: el controlador especifico del origen a1 que va a acce
derse.
En la figura 1.4 puede ver representados dos supuestos en 10s que un cliente
necesita acceder a dos origenes de datos diferentes: una base de datos SQL Serve
y una base de datos IBM DB2. En el primer caso, puesto que existe un proveedo
.NET especifico, el cliente tan s610 precisa el software cliente de SQL Server y ya
puede comunicarse, mediante una infraestructura de red, con el servidor. En e
segundo, por el contrario, no existe ese proveedor especifico, per0 si un controla
dor ODBC que sabe c6mo hablar con el software cliente de DB2. Utilizamos, po
tanto, el proveedor genkrico ODBC de .NET que, a su vez, empleari el controlado
ODBC adecuado.
Ni que decir tiene que el acceso mediante proveedores genkricos implica m6
carga de proceso y, por tanto, un menor rendimiento en la aplicaci6n. En alguna
ocasiones, sin embargo, puede ser la h i c a via para poder llegar a una cierta in
formaci6n.
Mediante XPath, por ejemplo, podria efectuarse una seleccidn de datos en un documento XML.
Aplicacion cliente
0,
IBMDB2
El lenguaje de consulta de datos por excelencia entre 10s RDBMS es SQL, creado hace algo m6s de veinte afios y conocido originalmente como SEQUEL. Realmente SQL se compone de varios sub-lenguajes, principalmente DDL y DML. El primer0
de ellos se utiliza para definir las estructuras de 10s datos que se manipulan con el
www.detodoprogramacion.com
1. Terrninologia y conceptos
segundo. Conocer el lenguaje SQL es fundamental para poder trabajar con bases
de datos, por ello en el siguiente capitulo podrd encontrar una introduccih a DDL
y DML.
Ademiis de para manipular la informacih, la mayoria de 10s RDBMS tambien
emplean SQL para otros fines como la implementacion de procedimientos almacenados. En realidad, cada fabricante de un product0 RDBMS cuenta con su propio
derivado de SQL para efectuar esas tareas. SQL Server, por ejemplo, cuentan con
el lenguaje T-SQL, mientras que Oracle utiliza PL/SQL. Tambibn encontrarii en el
capitulo siguiente una breve introduccih a dichos lenguajes.
Ciriiendonos ya a las bases de datos relacionales, posteriormente en otros capitulos nos ocuparemos del resto de origenes de datos, encontramos una serie de
terminos y conceptos que tambien es precis0 conocer. Los RDBMS introducen la
informaci6n en tablas, que pueden ser consideradas como conjuntos de entidades
cada una de las cuales tiene una serie de atributos. Los atributos almacenan datos
en un cierto dominio y, en algunas ocasiones, sirven para establecer relaciones con
otras entidades.
Los puntos siguientes son un recorrido rdpido por 10s conceptos mds importantes relativos a la estructura de la informaci6n en un RDBMS, independiente de
cud1 sea este.
Atributo
Titulo
Atributo
Editorial
Atributo
ISBN
Atributo
Pdginas
Conjunto
de entidades
Figura 1.5. Conjunto de tres entidades con cuatro atributos cada una
DO
10s
A1 conjunto de valores que puede tomar un atributo es a lo que se llama dominio. El atributo ISBN del ejemplo mostrado en la figura 1.5, por poner un ejemplo,
tendr6 un dominio que limite la introducci6n a 13 caracteres ajustados a un cierto
formato. De manera aniloga, el atributo P a g i n a s contaria con un dominio que
tan s610 permitiese la introducci6n de valores numericos comprendidos entre 100
y 2000, por ejemplo.
Los dominios, cuando se definen asociados a columnas en un RDBMS, impiden
la introducci6n de valores incorrectos en la base de datos, asegurando asi la integridad de la informaci6n. A1 tiempo, se evita que la aplicaci6n tenga que estar comprobando continuamente la validez de 10s valores introducidos por 10s usuarios.
Una restriccidn se define como el conjunto de reglas de validaci6n de un cierto
atributo, reglas que pueden ser mucho m i s complejas que un dominio. Mediante
una restricci6n es posible, por ejemplo, evitar que se introduzca en una tabla informaci6n relativa a un elemento que no existe en otra. En realidad, 10s dominios son
un tip0 de restricci6n.
ldentidad de una
Por norma, las entidades suelen contar con un atributo a1 que se aplica una restricci6n que le obliga a contener un valor unico entre el conjunto de entidades, utilizindose como atributo de identidad de cada una de las entidades. Es el clisico
cddigo que se asocia a las filas, normalmente un numero consecutivo generado por
la propia base de datos, y que permite identificarlas de manera unica.
Que las entidades tengan un atributo de identidad es algo indispensable en 10s
RDBMS, ya que facilita el establecimiento de relaciones entre distintos conjuntos
de entidades y hace posible la integridad referencial mediante restricciones de claves externas. Ademis, las reglas de normalizacion comentadas brevemente m i s
adelante exigen la existencia de ese atributo de identidad.
www.detodoprogramacion.com
ILf
1. Terrninologia y conceptos
conjuntos de enti
Los conjuntos de entidades que conforman una base de datos, en forma de tablas,
generalmente guardan ciertas relaciones entre ellos. Las reglas de normalizaci6n
de las bases de datos relacionales, que conocer6 b6sicamente en un punto posterior, persiguen evitar la repetici6n de datos en las tablas a fin de ahorrar espacio.
No tiene sentido, por ejemplo, que en el conjunto de entidades de la figura 1.5 se
repita el nombre de la editorial en cada entidad.
En la figura 1.6 se pueden ver dos conjuntos de entidades: uno relativos a libros
y otro a editoriales. Observe que el segundo atributo de cada libro ahora no es el
nombre de la editorial, sin0 un numero que la identifica. Ese numero es el atributo
identidad de las entidades del segundo conjunto.
vlsuai B ~ S ~. NCE T
V i s u a l CB .NET
Visual S t u d i o .NET
1
1
1
e4-115-1351-1
84-415-1392-9
84-415-1376-7
672
656
65h
El atributo Editorial de la primera entidad que hay en el primer conjunto indica que la editorial es la numero 1, estableciendo asi una relaci6n con la primera
entidad del segundo conjunto. El numero 1 es el atributo identidad o clave primaria
de cada entidad editorial, mientras que actua como clave externa en la entidad correspondiente a cada libro. Estas claves tambi6n suelen conocerse como PK y FK.
Mediante una restricci6n de integridad referencial se evitaria que el usuario pudiese introducir en una entidad de la tabla de libros un c6digo de editorial que no
existiese en la segunda tabla.
De manera anAloga, otra restricci6n podria impedir la eliminaci6n de una editorial del segundo conjunto mientras existiesen en el primer0 entidades que hicieran referencia a ella.
Las relaciones entre tablas pueden ser de diversos tipos, siendo las mAs habituales las conocidas como uno-a-uno y uno-a-muchos. En el primer caso a cada entidad
del primer conjunto le corresponde s610 una entidad del segundo. Es lo que ocurre
en el caso de la figura 1.6, en el que cada fila de la tabla de libros apunta a una sola
fila de la tabla de editoriales. Si invirti6semos la relaci6n (v6ase figura 1.7), por el
www.detodoprogramacion.com
contrario, nos encontrariamos con el segundo caso, por cada fila de la editorial de
tablas tendriamos multiples filas de la tabla de libros que le corresponden, en este
ejemplo concreto tres.
Anaya M u l t i m e d i a
O'ReiLly
V i s u a l 5ds1c .NET
V i s u a l C # .NET
V i s u a l S t u d i o .NET
1
1
84-415-1351-1
84-415-1392-9
84-415-1376-7
672
656
656
Al hablar de relaciones suele usarse con cierta frecuencia el termino maestrodetalle. Hace referencia a un tip0 de relacion en la que una tabla actua como
maestra o primaria y otra como tabla de detalle o secundaria, dando lugar a una
relacion uno-a-muchos.
A1 trabajar con tablas de tamafio considerable, con muchos miles 0, incluso, millones de filas, el proceso de recuperaci6n de datos puede verse afectado de manera considerable. Es 16gico si tenemos en cuenta que para, por ejemplo, encontrar
todos 10s libros de una editorial, seria precis0 recorrer la tabla de libros completa,
de principio a fin.
Un mecanismo comun para acelerar esa operaci6n son 10s indices. Un indice es
una lista de claves con una estructura tal que el servidor puede realizar busquedas
de forma muy ripida en ella.
Las claves pueden estar formadas por el contenido de una o varias columnas de
una tabla. Ademis de acelerar la busqueda de informacih, un indice tambi6n puede ser utilizado para establecer el orden en el que se almacenarin las filas en una
tabla.
Cada vez que se inserta, modifica o elimina una tabla de la cual depende uno o
varios indices, el servidor tiene que actualizar no s610 la tabla de datos sin0 tambi6n todos 10s indices que existan a fin de que Sean consistentes con la informaci6n
actual. Es ficil deducir que cuintos m i s indices existan m i s tiempo seri necesario
para efectuar cualquiera de esas operaciones.
www.detodoprogramacion.com
---- -
--- --
I_
I_
___I
-~
-___-
- -
_I
_ _ ~ _ _ _ _ _ _ _ _______-__-.-----_
~ -~
- ___I____
_ _ _ _ I _
___-
^____l___l_ll
_______I__
A1 operar sobre un RDBMS del tipo Oracle, SQL Server, DB2, Sybase o InterBase,
10s que podriamos considerar servtdores de datos, todas las actuaciones que impliquen manipulacih de la informacih, no solo recuperaci6n de datos, tienen lugar
en el Qmbito de una transacctdn. Esto es especialmente cierto en aquellos casos en
10s que la informaci6n manipulada se aloja en dos o mas tablas y, por tanto, podria
generarse una inconsistencia entre 10s datos.
www.detodoprogramacion.com
1. Terrninologia y conceptos
Suponga que crea una aplicaci6n para una entidad bancaria en la que el usuario,
por ejemplo el cajero de una oficina, introducir6 datos sobre operaciones bancarias. Atendiendo a un cliente que quiere efectuar una transferencia desde su cuenta a la de un proveedor, el cajero introduce 10s dos c6digos de cuenta y el importe
a transferir, entre otros datos. A1 pulsar un bot6n su aplicaci6n deduce el importe
de la cuenta del cliente y, cuando va a sumarlo a la cuenta del proveedor, se produce un fallo en el sistema. iQu6 ha ocurrido con la operacibn? En ese momento ya
no est5 el dinero en la cuenta del cliente, per0 tampoco en la del proveedor. Simplemente ha desaparecido o quiz5 est6 en el limbo.
Obviamente, esa situaci6n no deberia darse nunca. A1 iniciar las operaciones
sobre la base de datos la aplicaci6n deberia iniciar una transacci6n. h a asegura
que 10s datos que se manipulen no son escritos de manera inmediata en la base de
datos, sino en un espacio temporal. S610 cuando se han finalizado 10s cambios en
todas las tablas afectadas se termina la transacci6n, momento en el que dichos cambios se confirman.
Para que este sistema sea realmente util es necesario que el sistema de transacciones del RDBMS cumpla con las propiedades conocidas como ACID:
0
La atornicidnd de la transacci6n hace que todas las operaciones que comprende Sean vistas por el RDBMS como una sola, de tal manera que o se efectcia o
se rechaza completa, no existiendo la posibilidad de que el trabajo quede a
medias.
Mediante la consistencia se garantiza el cumplimiento de las reglas que lleven asociadas las operaciones introducidas en la transaccibn, tales como restricciones, ejecuci6n de desencadenadores, etc.
Que una transacci6n tenga entre sus propiedades el aislamiento implica que
las operaciones intermedias que se efectuen, antes de finalizar la transacci6n,
no son visibles para nosotros y, an5logamente, las realizadas en esta transaccion no Sean visibles en otras hasta que se confirme. Asi se consigue una independencia total en el trabajo de multiples transacciones concurrentes.
Por ciltimo tenemos la durabilidad o persistencia, la propiedad que da la garantia de que la transaccibn, una vez concluida, no se perder5 a pesar de 10s
problemas posteriores que pudiesen encontrarse.
XML
Seguramente ya sepa qu6 es XML y c u d es su finalidad, ya que se trata de un
lenguaje que en 10s ultimos afios ha encontrado aplicaci6n en prscticamente todos
10s campos de la informAtica. A1 trabajar con ADO.NET no s610 podremos operar
sobre documentos XML sin0 que, ademds, 10s conjuntos de datos en ADO.NET se
almacenan internamente en dicho formato.
XML es un lenguaje que se centra en la definici6n de la estructura de 10s datos,
en contraposici6n a otros, como es el caso de HTML, que se ocupa no de 10s datos en
si sin0 de su representaci6n visual. En XML es posible definir marcas propias segun se precise, facilitando asi la creaci6n de estructuras de informaci6n a medida.
El beneficio es que XML se almacena y transfiere a trav6s de redes no en un formato binario, como venia siendo habitual en cualquier medio para el almacenamiento
de datos, sin0 como texto simple, facilitando asi la comunicaci6n entre aplicaciones y sistemas sin importar el tip0 de procesador, sistema operativo o lenguaje de
programaci6n empleados.
A pesar de su naturaleza, XML es un formato para el almacenamiento de datos
con definici6n implicita, no para la presentaci6n de esos datos. Es muy fdcil, no
obstante, definir una hoja de estilo XSL y aplicarla a un documento XML para obtener una representach visual de la informaci6n. De la misma forma, tambi6n se
pueden definir esquemas XSD para asegurar que la estructura de 10s documentos
es correcta.
En la plataforma .NET existen servicios especificos para trabajar con documentos XML. Como veremos posteriormente, tambien podemos actuar sobre ellos mediante ADO.NET, como si fuesen origenes de datos locales.
www.detodoprogramacion.com
x_l.
....I.,
.,...
.... '.
....
'
....
,.-.
www.detodoprogramacion.com
:7?.
A pesar de que nuestro papel en la empresa este m6s cerca, o sea puramente,
del desarrollador que del administrador de bases de datos, lo cierto es que conocer el lenguaje SQL resultar6 totalmente imprescindible.
ADO.NET, como veri en su momento, cuenta con componentes capaces de generar las sentencias SQL necesarias para actuar sobre las bases de datos, per0 ser6n muchos 10s casos en que dichas sentencias deban facilitarse desde la aplicacion
que estemos creando.
Actualmente todos 10s DBMS, incluidos aquellos que no son servidores como es
el caso de Access o dBase, contemplan el us0 del lenguaje SQL para efectuar cualquier tarea sobre la informacion, desde la definition de su estructura hasta la manipulaci6n de 10s datos propiamente dichos.
Algunos RDBMS, realmente todos aquellos que contemplan la definici6n de
procedirnientos alrnacenados, utilizan tambien SQL como base para un lenguaje propi0 de tip0 procedimental.
El objetivo de este capitulo es acercarle a1 lenguaje SQL, facilitando una explicaci6n de sus estructuras b6sicas que le permitan, por ejemplo, crear una tabla, seleccionar un conjunto de datos o modificar informaci6n ya existente en la base de
datos.
Tambien se facilita, a1 final del capitulo, una breve introduccih a dos derivados de SQL: Transact-SQL y PL/SQL. Obviamente no se intenta abordar la sintaxis completa de SQL y todas sus posibilidades. Si necesita conocer a fondo este
lenguaje siempre tiene la posibilidad de recurrir a un texto especifico o la referencia del lenguaje de su RDBMS en particular.
www.detodoprogramacion.com
2. S Q L y sus dialectos
DML: Es la parte m6s conocida del lenguaje SQL, a1 formar parte de 41 todas
las sentencias de manipulaci6n de datos: extracci6n de informacibn, actualizaci6n y eliminacih. Tebricamente, y asumiendo que existe un DBA que se
ocupa del RDBMS, 10s programadores tan s61o tendrian que conocer DML
para efectuar su trabajo.
DDL: Con las sentencias DDL no se manipulan 10s datos propiamente dichos, sino la informacih de su estructura. Con las sentencias DDL pueden
definirse las columnas de una tabla y sus atributos, eliminar o crear un indice, etc.
DCL: Mucho menos conocido que 10s dos anteriores, este lenguaje se compone de sentencias especificas para garantizar la seguridad de acceso a 10s datos, facilitando la gestion de usuarios y el otorgamiento o denegaci6n de 10s
permisos necesarios para operar sobre cada elemento de la base de datos.
r
Programacidn de bases de datos con Visual Basic .NET
caciones. En 10s puntos siguientes, no obstante, tambien encontrari una r6pida introducci6n a algunas de las sentencias de DDL y DCL.
Si bien, en un principio, la finalidad de 10s RDBMS era bisicamente la de almacenar, recuperar y manipular la informacidn, segun las sentencias SQL facilitadas
desde algun tip0 de aplicaci6n o por el usuario, con el paso del tiempo se han ido
confiando a estos sistemas de tratamiento de datos otras tareas adicionales. Una
de ellas es la ejecuci6n de una cierta 16gica de proceso que asegure la integridad de
10s datos 0,simplemente, haga m i s f6cil su tratamiento por parte de las aplicaciones. Estas operaciones se implementan en forma de desencadenadores y procedimientos almacenados, siendo precis0 un lenguaje de programaci6n para efectuar
dicha implementacibn. SQL, como se ha dicho antes, no es un lenguaje procedimental y, por tanto, no puede ser utilizado para dar soluci6n a estas necesidades. Por
esa raz6n, cada fabricante de RDBMS incorpora en su product0 un lenguaje propio
para desempefiar esas tareas. Por regla general, estos lenguajes tienen una sintaxis
basada en la de SQL, aportando 10s elementos necesarios para definir procedimientos, evaluar expresiones condicionales o definir una ejecucidn reiterada.
Dos de 10s lenguajes derivados de SQL m i s conocidos son PL/SQL, propio de
las bases de datos Oracle, y T-SQL (tambien conocido como Transact-SQL), que
podemos encontrar en SQL Server o Sybase. Lbgicamente, necesitaremos aprender
uno u otro dependiendo del RDBMS que utilice nuestra empresa.
Las bases de escritorio, como dBase, Access y Paradox, no disponen de un lenguaje similar a PL/SQL o T-SQL para la implernentacion de procedimientos almacenados, pues dichos elementos no existen en esos productos. Si cuentan,
sin embargo, con un completo lenguaje de programacion que permite crear
verdaderas aplicaciones, en contraposicion a la Iogica discreta, siempre dirigida al tratamiento de datos, para la que estan pensados PL/SQL y T-SQL.
2.S Q L y
sus dialectos
Puede usar una base de datos de escritorio, por ejemplo Microsoft Access (v6ase figura 2.1), ya que permiten la ejecucion de un subconjunto del lenguaje SQL, o
bien la utilidad de SQL interactivo del RDBMS con que cuente. Esta puede ser el
Analizador de consultas SQL de SQL Server (v6ase figura 2.2), el Interactive SQL
de InterBase (v6ase figura 2.3) o bien el SQL*Plus Worksheet de Oracle 8i (v6ase
figura 2.4). En cualquier caso, no entraremos en este momento en detalles sobre
c6mo usar una herramienta u otra, en el pr6ximo capitulo conocera algunas de ellas,
sino que nos centraremos en la sintaxis de SQL, sin mbs.
Figura 2.1. Desde Microsoft Access es posible definir consultas mediante asistentes,
per0 tambien pueden escribirse de forma manual
Antes de poder manipular datos mediante DML, es necesario que dichos datos
existan ya en la base de datos y, para ello, es precis0 definir las estructuras que 10s
www.detodoprogramacion.com
Conexmes 1
Figura 2.3. Aunque con un nombre diferente y sobre otro RDBMS, el Interactive SQL
de InterBase es una herramienta similar a la de SQL Server
www.detodoprogramacion.com
2. S Q L y sus dialectos
Mediante DDL es posible crear una base de datos, crear las tablas definiendo
las columnas que t e n d r h , crear indices y vistas y, por supuesto, modificar y eliminar todos esos elementos. Los comandos DDL son tres:
CREATE: Se utiliza para crear bases de datos, tablas, indices, desencadenadores, procedimientos almacenados y vistas, segun la palabra clave que se
indique a continuacih. Dependiendo del caso aceptar6 m6s o menos par&metros adicionales.
DROP: Acepta las mismas palabras clave que el comando CREATE, si bien la
finalidad es eliminar el elemento indicado en lugar de crearlo.
una base de datos. No acepta todas las palabras clave de 10s dos comandos
anteriores, solo parte de ellas. Las vistas, por ejemplo, pueden crearse y eliminarse, per0 no modificarse.
VIEW: Vista.
TRIGGER: Desencadenador.
INDEX: indice.
S
La creaci6n de una nueva base de datos es un proceso relativamente complejo,
a1 ser precis0 definir su contenido y estructura, espacio de almacenamiento, permisos de acceso, usuarios con que cuenta y otra serie de reglas adicionales. Por ello
pr6cticamente todos 10s RDBMS incorporan un asistente para efectuar este trabajo,
asistente que va dirigido a1 DBA. Como desarrolladores, tan s610 necesitariamos
emplear la sintaxis siguiente en caso de que fuese imprescindible crear la base de
datos desde nuestra propia aplicacih.
La sintaxis bdsica para crear una nueva base de datos seria &a:
CREATE DATABASE n o r n b r e _ b a s e _ d e - d a t o s
El nombre de la base de datos puede ser un nombre 16gic0, caso en el cual existir6n opciones adicionales para indicar la localizacih y nombre fisico de 10s archivos donde ser6 alojada, o bien ser una especificacion de nombre de archivo en si
mismo, segun el RDBMS con que trabajemos.
Una vez que ya tenemos la base de datos creada, y estamos conectados a ella, el
siguiente paso 16gico es crear las tablas que alojar6n 10s datos, definiendo 10s atributos de cada una de dichas columnas. A1 tiempo, tambi4n es posible establecer
las restricciones para cada una de las columnas, asi como la creaci6n de claves primarias.
La sintaxis general para la definici6n de una nueva tabla en una base de datos
es la siguiente:
www.detodoprogramacion.com
2. S Q L y sus dialectos
...
I
DATE:Una fecha.
NOT NULL:Indica que la columna no puede quedar sin valor. Hay que tener
en cuenta que una cadena de caracteres vacia o un cero no es igual a NULL,
por lo que una columna que tenga esta restriccih podria tomar perfectamente uno de esos valores.
0
PRIMARY KEY: Establece la columna a la que acompafia como clave primaria o principal de la tabla, es decir, como atributo de identidad de cada fila.
www.detodoprogramacion.com
Esto suele conllevar el hecho de que 10s valores de dicha columna deban ser
unicos.
0
FOREIGN KEY:Define una colurnna como clave externa, que hace referencia
a una clave primaria de otra tabla.
Las opciones PRIMARY KEY y FOREIGN KEY pueden tanto seguir a una columna como disponerse a1 final de la lista de columnas, caso en el cual se indicaria entre parhtesis, detras de KEY, el nombre de la columna o columnas que actuarian
como clave primaria o clave externa. En este ultimo caso, hay que aiiadir el apartado REFERENCES ( col), donde col seria la referencia a la tabla y columna externa.
A continuacibn tiene un ejemplo de creaci6n de una tabla simple:
CREATE TABLE Libros
( IDLibro INTEGER PRIMARY KEY,
ISBN CHHR(13I UNIQUE,
Titulo VARCHAR(30) NOT NULL,
Autor VARCHAR(501,
FOREIGN KEY (Editorial1
REFERENCES Editoriales ( IDEditorial)
)
Tenemos una columna que actua como clave principal, identificando a cada una
de las filas que pudieran existir en la tabla. Se ha utilizado una colurnna INTEGER
como clave unica en lugar de la columna 1S BN que, como puede verse, alberga valores unicos. Para 10s RDBMS, sin embargo, resulta mucho mas fdcil gestionar una
clave que es un numero que una cadena de 13 caracteres. Aunque parezca redundante aiiadir una columna como identidad de cada fila, en realidad estd ahorrdndose espacio y se mejora el rendimiento.
Las columnas T i t ul o y Auto r tienen una longitud variable, aunque con un
mdximo, en contraposici6n a ISBN que siempre tendra 13 caracteres. El us0 de
VARCHAR tambien ahorra espacio en la base de datos, a1 ocupar tan s610 el espacio
necesario para almacenar cada valor en lugar de asignar el mdximo posible.
Por ultimo, encontramos la definici6n de una clave externa, llamada Editorial en esta tabla, que hace referencia a la columna IDEditorial de la tabla
Editoriales. Lbgicamente, dicha tabla deberd existir y la columna IDEditorial
seria su clave primaria.
Debe tener en cuenta que, dependiendo del DBMS que emplee, para crear una
tabla puede necesitar ciertos permisos o privilegios. De no contar con ellos, la
ejecucion de una sentencia como la anterior provocaria un error. En algunos
DBMS, ademas, debera preceder el nombre de la nueva tabla con el esquema
donde quiera crearla si es que dicho esquema no es el asumido por defecto.
www.detodoprogramacion.com
2 . S Q L y sus dialectos
Otra posibilidad, a la hora de crear una tabla en una base de datos, consiste
en hacerlo a partir de 10s datos que ya existen en otra tabla. En este caso el
comando CREATE TABLE nombre iria seguido no de una lista de columnas,
tipos y opciones, corno en el ejemplo anterior, sino de una consulta SQL que
recuperaria de otra tabla o tablas 10s datos con 10s que se generaria la nueva
tabla.
Las modificaciones a una tabla pueden ser de distintos tipos, desde aiiadir o
eliminar una columna o una restriccibn hasta modificar la definicih original de la
columna para cambiar el tipo. En cualquier caso, la sentencia la iniciaremos con
ALTER TABLE N o m b r e T a b l a , tras la cual dispondremos la palabra ADD, para
aiiadir un nuevo elemento; ALTER, para modificarlo, o DROP si queremos eliminarlo. Por ejemplo:
ALTER TABLE Libros DROP COLUMN ISBN
ALTER TABLE ADD ISBN VARCHAR(13)
ALTER TABLE Libros ALTER COLIJMN Titulo VARCHAR(35)
Hay que tener en cuenta que la modificacion del tip0 de una columna puede
irnplicar una perdida de datos, algo que es obvio si la columna se elimina.
Si deseamos eliminar una tabla completa, no tenemos m& que usar la sintaxis
mostrada en el ejemplo siguiente:
DROP TABLE Libros
Aunque las tablas son el centro de cualquier base de datos, a1 ser fisicamente
las que alojan la informacih, t a m b i h existen otros elementos de us0 comun, entre ellos 10s indices y las vistas.
Para crear un indice utilizaria la siguiente sintaxis:
CREATE INDEX NombreIndice ON NombreTabla(Co1umna)
www.detodoprogramacion.com
www.detodoprogramacion.com
2. S Q L y sus dialectos
El resultado, a1 ejecutar esta vista, seria una tabla temporal con dos columnas,
una con el nombre de la editorial y otra con el titulo del libro, y tantas filas como
combinaciones de editoriales y libros existan en las tablas.
La consulta asociada a una vista puede modificarse con la sentencia ALTER
VIEW, por ejemplo:
ALTER VIEW L i b r o s E , J i t o r i a l A S
S E L E r T E d i t , - > r i a l . N s r n l n r e , L i b r o s . ISBN
FROM E d i t o r i a l , L i b r c - I S
W H E R E E d i t o r 1a 1 .1DEd I t~c
r i a 1=Lib r o s EIJ i t~o r i a 1
Aqui hemos modificado la vista anterior para que, en lugar del titulo de 10s libros, se incluya el ISBN.
Asimismo, la eliminaci6n de una vista es tan simple como ejecutar la sentencia
DROP VIEW NombreVista.
Nota
Segun se indicaba al inicio de este punto, dedicado a DDL, 10s mismos comandos CREATE, ALTER y DROP pueden utilizarse tambien para crear desencadenadores, procedimientos almacenados y otros elementos. Las posibilidades
y sintaxis, en estos casos, varian en mayor medida de un DBMS a otro. Para
crear un desencadenador o procedimiento almacenado, por ejemplo, suele hacerse us0 del lenguaje especifico del RDBMS para efectuar la implernentacion
de una cierta Iogica.
Si con DDL definimos las estructuras para el almacenamiento de 10s datos, con
DML podremos manipular 10s datos propiamente dichos, efectuando consultas
para recuperar datos, modificaciones, borrados, etc.
Las operaciones fundamentales de manipulacih de datos son cuatro y, consecuentemente, cuatro 10s comandos DML que necesitaremos para poder llevarlas a
cabo:
0
SELECT:
La sentencia DML por excelencia. Se utiliza para ejecutar consultas
de recuperacih de datos.
I N S E R T : Su finalidad es insertar nuevas filas en una tabla.
UPDATE: Con este comando es posible cambiar la informacih alojada en
una o m i s filas.
m6s filas.
www.detodoprogramacion.com
A diferencia de lo que ocurre con las sentencias de un lenguaje de programaci6n tipico, como puede ser Visual Basic, estas sentencias DML no actuan sobre un
solo elemento, sin0 sobre conjuntos de filas y columnas. Es importante tenerlo en
cuenta a la hora, por ejemplo, de utilizar una sentencia DELETE para eliminar una
fila, puesto que, inadvertidamente, podemos afectar a varias 0, incluso, la tabla
completa.
En 10s puntos siguientes va a conocer la sintaxis b6sica de cada una de las cuatro sentencias indicadas, asi como a ver algunos ejemplos de su uso.
__
__
___
I
_
--
Si creamos una aplicaci6n para que 10s usuarios puedan trabajar sobre una base
de datos, una operaci6n biisica es la inserci6n de nuevos datos. De hecho, en principio ser6 la unica opci6n disponible a menos que las tablas de datos sobre las que
se trabaje tengan ya informaci6n previamente. La sintaxis de la sentencia I N S E R T
es la siguiente:
INSERT INTO NornbreTabla
VALlJES
( v a l o r , valor
...)
En caso de que desee introducir datos en menos columnas de las que existen en
la tabla, deberia especificar las columnas de destino detr6s del nombre de la tabla,
entre parhtesis. Por ejemplo:
I N T O Libros ( I D L i b r c , ,
( 1 , '84-415-1351-1')
INSERT
ISBN) V A L l J E S
El resto de las columnas de esa fila quedarian con el valor NULL, siempre, por
supuesto, que sus restricciones no lo impidan.
En el caso de que se viole alguna restriccibn, como que un valor no sea unico en
una columna que debe serlo o que se entregue como una clave externa un valor
que no se encuentre en la tabla de destino, la inserci6n no se efectuari y generari
un error.
www.detodoprogramacion.com
2. S Q L y sus dialectos
Colurnrla2,
...
FROM T a b l a
A u t o r FROM L i b r o s
Esta consulta retornaria el titulo y autor de todas las filas existentes en la tabla
L i b r o s . Si queremos obtener todas las columnas de la tabla, sin necesidad de especificar el nombre de cada una, podemos sustituir la lista que sigue a la palabra
S E L E C T por un asterisco:
SELECT
FROM L i b r o s
En este caso se obtendria la totalidad de la tabla L i b r o s , es decir, todas las filas con todas las columnas. Usualmente esto no es necesario, por ello se seleccionan s610 las columnas que se precisan en cada caso y, ademis, se limitan las filas
mediante condiciones. Tambikn es posible establecer el orden en que se facilitan las
filas recuperadas, agruparlas, efectuar consultas sobre consultas, etc.
CI
_ I ~ I ~ _ _ _ _ I _ . _ _ .~
_ _ ~ _ I _ _ I _ _ _ _
I__-_-
__
L.Editoria1
www.detodoprogramacion.com
En este caso concreto no tiene mucho sentido ya que, a1 participar una sola
tabla en la consulta, no tenemos porqu6 usar la notaci6n L . I S BN para seleccionar
la columna ISBN, hubiera bastado con facilitar directamente el nombre de la columna. Encontrard una mayor aplicaci6n al us0 de 10s alias de tablas en 10s puntos
siguientes.
Seleccicin de Eilas
Indicar en la consulta qu6 columnas deseamos incluir en el conjunto de resultados es bastante sencillo, ya que el numero de columnas con que cuenta una tabla
suele ser pequeiio y, por tanto, podemos indicar 10s nombres de cada una de ellas
tras la palabra SELECT.
Para seleccionar un determinado conjunto de filas no es posible utilizar una tkcnica similar, primer0 porque las filas no tienen nombres, sin0 que contienen valores, y segundo porque, a diferencia de columna, una tabla puede alojar miles o
incluso millones de filas. Por ello la soluci6n tiene que ser totalmente diferente pero, como programadores, nos debe resultar relativamente fdcil comprenderla ya
que est6 basada en la evaluaci6n de expresiones condicionales.
Aparte de la cl6usula FROM,unica obligatoria y con la cual se indican las tablas
de las que va a recuperarse la informacibn, la sentencia SELECT puede contar,
opcionalmente, con varias mds. Una de ellas es la cldusula WHERE, encargada de
aplicar uno o m6s condicionales basdndose en 10s cuales se filtrardn las filas a devolver. La sintaxis de la consulta seria la siguiente:
SELECT C o l u r n n a s FROM Tablas WHERE C o n d i c i j i - j
La condici6n se asemejard bastante a 10s condicionales que estamos acostumbrados a utilizar en Visual Basic, con operadores relacionales como =, < y > y operadores 16gicos como AND, OR y NOT. Esto permite una gran flexibilidad a la hora
de seleccionar conjuntos de datos. Por ejemplo:
SELECT I S B N , Titulo
FROM Libros
WHERE Autor='Bill Gates'
...
SELECT I S B N , Titulo
FROM LIBROS
WHERE Editorial=S AND Precio<bO
Condicionalcs complcjos
Ademds de condicionales relativamente simples, en 10s que se compara si el valor de una columna es igual, mayor o menor que otro valor dado, en la cldusula
www.detodoprogramacion.com
2. S Q L y
sus dialectos
WHERE pueden emplearse elementos adicionales que nos permiten crear condicio-
nales realmente complejas. A 10s operadores relacionales cldsicos hay que aiiadir
otros, como I N , LIKE y BETWEEN, mucho m6s flexibles.
Mediante el operador IN es posible crear una expresion que serd cierta en caso
de que el valor de la columna indicada a la izquierda contenga uno de 10s valores
delimitados entre parhtesis, a la derecha del operador. Por ejemplo:
SELECT ISBN, T i t u l o
FROM L i b r o s
WHERE A u t o r
I N ( ' B i l l Gdtes',
' P a u l Allen',
'Steven J o b s ' )
En esta consulta se seleccionan todos 10s titulos escritos por 10s tres autores indicados entre parhtesis, evit6ndonos asi la construccion de tres condicionales con
el operador = unidos mediante AND.
Con el operador LIKE podemos efectuar comparaciones no absolutas entre 10s
valores de una columna y un valor dado 0, dicho de otra forma, facilita la busqueda de un cierto patron entre 10s valores de una columna.
Tras el operador L I K E debemos facilitar, entre comillas simples, el patron a
buscar. Por ejemplo:
SELECT ISBN, T i t u l o
FROM L i b r o s
WHERE T i t u l o LIKE ' V i s u a l % '
En este caso obtendriamos la lista de todos aquellos libros cuyo titulo comience
con Visual, sin necesidad de especificar el titulo completo.
Por ultimo tenemos BETWEEN, mediante el cual es posible especificar un rango
de valores en el cual deberd encontrarse una cierta columna para ser incluida en el
conjunto de resultados. Por ejemplo, si queremos obtener todos aquellos libros cuyo precio se encuentre entre 30 y 50 euros podemos utilizar una consulta como la
siguiente:
SELECT ISBN, T i t u l o
FROM L i b r o s
WHERE P r e c i o BE,TWEEN 3 0
AND 5 0
'Steven Jobs')
www.detodoprogramacion.com
El conjunto de datos obtenido estaria formado por todos aquellos libros que,
escritos por Bill Gates, Paul Allen o Steven Jobs, costasen entre 30 y 50 euros y,
adem&, su titulo comenzase con la palabra V i s u a l .
S
Con esta consulta obtendriamos una lista completa de todas las filas que hay en
la tabla Libros ordenadas alfabeticamente por el contenido de la columna Titul o . El orden seria de menor a mayor, es decir, de la A a la Z . Podemos alterar el
orden mediante las palabras DESC y ASC, segun deseemos un orden descendente o
ascendente.
Hasta ahora, en las consultas mostradas como ejemplo en 10s puntos anteriores,
siempre hemos seleccionado como resultados una serie de columnas existentes en
las tablas. Tambien existe la posibilidad de introducir expresiones, usando como
operando el valor de una o varias columnas, y funciones de resumen o agregacidn.
Para obtener, aparte de las columnas que nos interesen, datos obtenidos a partir de algun ciilculo u operacih, tan s610 tenemos que incluir la expresih apropiada como si de una columna m6s se tratase. Por ejemplo:
SELECT Titulo, Precio * 1,04
FROM L i b r o s
Con esta consulta se obtendria una lista de titulos de libros y una segunda columna que tendria el precio m6s un 4 por ciento. Dicho valor se obtendria como
resultado de la consulta, per0 no afectaria en absoluto a1 contenido de la tabla
Libros.
Si lo que necesitamos no es operar sobre una cierta columna de una fila, como
en este caso, sin0 sobre todas las columnas recuperadas a partir de la consulta, podemos utilizar las funciones de agregaci6n. Las de us0 m6s corriente son:
0
0
SUM ( ) : Suma 10s valores de la columna indicada de todas las filas del conjunto.
www.detodoprogramacion.com
2. S Q L y sus dialectos
AVG ( ) : Efectua una media sobre 10s valores de la columna indicada de todas
del conjunto.
M I N ( ) : Halla el valor minimo de la columna indicada entre todas las filas
del conjunto.
Cuando en una sentencia SELECT aparece una o m6s funciones de agregacibn,
las unicas columnas adicionales que pueden incluirse son las utilizadas para efectuar agrupamientos, segun se Vera en el punto siguiente. El siguiente es un ejemplo de us0 de estas funciones:
SELECT COUNTiPrecio), MINiPrecio), MAXiPrecio)
FROM L i b r o s
El resultado obtenido seria una sola fila conteniendo el numero total de filas de
la tabla Libros, puesto que no se ha aiiadido una cliusula WHERE, asi como el
precio del libro mas barato y el del m6s caro.
MINiPrecio), MAXiPrecio)
FROM Libros
G R O U P BY Editorial
En este caso no se obtendria una sola fila de resultados, como en el punto previo, sin0 una fila por editorial. Ademas, cada fila contendria el numero de titulos
de esa editorial, asi como 10s precios minimo y mdximo de 10s titulos de esa editorial. Un resultado asi, que es ejecutado en el RDBMS y devuelto a la aplicacih,
puede ahorrarnos muchas sentencias de programa Visual Basic.
Enlnc
En todos 10s ejemplos previos se ha operado exclusivamente sobre una tabla de
la base de datos. No es extrafio, sin embargo, que sea precis0 recuperar columnas
de dos o m6s tablas, por ejemplo una lista de editoriales y 10s libros correspondientes a cada una, la informacih de un pedido y las lineas asociadas, etc.
Tras la cl6usula FROM puede aparecer cualquier numero de tablas, y tras SELECT
todas las columnas que se necesiten de esas tablas. Para poder asociar 10s datos de
las distintas tablas, y componer adecuadamente cada fila del conjunto de datos rewww.detodoprogramacion.com
sultante, es preciso crear un vinculo entre las distintas tablas. Con este fin se utilizan las claves primarias y externas que se definieron previamente, enlaz6ndolas
mediante un condicional en el apartado WHERE.
Suponga que desea obtener una lista con el nombre de cada editorial y 10s titu10s que le corresponden. La consulta podria ser la siguiente:
SELECT E.Nombre, L.Titulo
FROM Editorial E, Libros L
WHERE E.IDEditorial=L.Editorial
co
- _ _ _ ~
_ _ I _ _ I _~
_
_
I
I
_
~~
--
Las sentencias SELECT pueden anidarse, dando lugar a lo que se conoce como
subconsultas. Primero se ejecuta la consulta que est6 en el nivel m6s interior (aparece despues en la sentencia completa), obteniendose un conjunto de resultados que,
en lugar de devolverse directamente, se entrega a la consulta del nivel exterior para que efectue el proceso apropiado. Este proceso se repite las veces que sea preciso
hasta llegar a1 SELECT m6s exterior, el que aparece en primer lugar en la sentencia, momento en que se devuelven 10s resultados.
SELECT C o l u m n a s FROM Tabla
WHERE Cond i c i on
(SELECT Columnas FROM Tabla)
Suponga que desea obtener una lista de todos aquellos libros cuyo precio es superior a la media. iC6mo se expresaria esa consulta? Primero es necesario obtener
la media del precio y, a continuacih, utilizarla como resultado para ejecutar otra
consulta. En lugar de utilizar una variable intermedia y ejecutar dos consultas,
resulta mucho m i s efectivo utilizar una sentencia como la siguiente:
SELECT Titulo, Precio FROM Libros
WHERE Precio >
(SELECT AVGiPrecio) FROM Libros)
El resultado de la subconsulta no tiene que aplicarse necesariamente a un condicional, pudiendo utilizarse directamente como origen de datos para la consulta
superior.
www.detodoprogramacion.com
2. S Q L y sus dialectos
Por ejemplo:
S E L E C T T i t u l o , P r - e c i o * l . 0 4 FROM
(SELECT T i t u l o , P r e c h , E d i t o r i a l
FROM L i b r o s
WHERE E d i t r ) r i a l =
( S E L E C T I d E d i t o r i a l FROM E d i t o r i a l e E
WHERE, N o m h r e = ' A n d y a M i i l t i r n e d i a ' )
..
Una vez insertados en una tabla, 10s datos pueden consultarse tantas veces como se precise e, igualmente, es posible modificarlos si es necesario. En este caso la
sentencia a utilizar ser6 UPDATE, con la sintaxis siguiente:
1J
P DATE N o r r i h r e T a b 1a
S E T Columna=Valor, C o l u m n a = V a l o r
...
Hay que tener en cuenta que, de no facilitar una cliusula WHERE con un condicional, la sentencia de actualizacih afectari a la tabla completa. La ejecuci6n de la
sentencia siguiente, por ejemplo, asignaria el valor 30 a1 precio de todos 10s libros
existentes en la tabla L i b r o s :
U P D A T E Libros
SET P r e c i o = 3 0
www.detodoprogramacion.com
Como se indicaba a1 inicio del capitulo, DCL resulta mucho menos conocido
para 10s desarrolladores que DML y DDL, especialmente porque las tareas para
las que se utiliza recaen siempre en un DBA, encargado de gestionar 10s usuarios
que pueden acceder a la base de datos y otorgarles o denegarles la operacidn sobre
sus tablas.
Las dos sentencias m6s conocidas de este grupo son GRANT y REVOKE. Con la
primera se otorga un cierto permiso, mientras que con la segunda se deniega. Los
permisos pueden ser globales o muy concretos, por ejemplo la insercidn o borrado
de una tabla o la modificacidn de ciertas columnas. El destinatario del otorgamiento
o la denegacidn es un perfil o una cuenta de usuario, segun 10s casos. Estos perfiles
y cuentas tambien pueden crearse mediante DCL, con sentencias del tipo CREATE
U S E R y CREATE ROLE, si bien la sintaxis suele diferir entre distintos DBMS.
Suponiendo que estuvi4semos trabajando con SQL Server y dese6semos permitir la seleccidn e insercidn, per0 no la modificacidn ni el borrado, sobre la tabla
Libros a un usuario llamado Operador, podriamos usar las siguientes sentencias DCL:
GRANT SELECT, INSERT
ON L i h r o s T O Operador
www.detodoprogramacion.com
2. S Q L y sus dialectos
REVOKE U P D A T E , DELETE
ON L i b r o s FROM O p e r a d o r
El lenguaje SQL, como ha podido ver desde el inicio de este capitulo, est6 orientad0 a1 trabajo con conjuntos de datos, facilitando la selecci6n y modificaci6n de
manera flexible y potente. Efectuar un trabajo similar desde Visual Basic, procesando 10s datos de manera individual, conllevaria una carga mucho mayor para
nuestras aplicaciones.
A pesar de todo, SQL tiene sus limitaciones 0, simplemente, no estaba pensado
originalmente para las necesidades que han surgido con posterioridad. Una de
esas necesidades es la incorporaci6n en el propio DBMS de parte de la 16gica de
proceso de 10s datos, en forma de desencadenadores y procedimientos almacenados, con el fin de aliviar la carga de trabajo de 10s clientes y, a1 tiempo, centralizar
las reglas de negocio en un servidor, facilitando su mantenimiento.
Por esta raz6n, cada fabricante de DBMS ha creado su propio lenguaje que,
partiendo de la sintaxis y naturaleza de SQL, aiiade posibilidades como el trabajo
con variables, evaluacidn de expresiones condicionales y repetici6n de sentencias.
Dos de esos lenguajes, quiz2 10s m6s representativos, son Transact-SQL, conocido
originalmente como T-SQL y utilizado por Sybase y SQL Server, y PL / SQL, empleado en Oracle.
Tanto Transact-SQL como PL / SQL son lenguajes lo suficientemente complejos
como para escribir varios libros especificos sobre ellos, puede encontrarlos en su
libreria habitual, por lo que en 10s puntos siguientes lo unico que se pretende es facilitar un acercamiento muy superficial a ellos.
Provenientes de una misma raiz, Sybase y SQL Server cuentan con un lenguaje
llamado Transact-SQL que, con el tiempo, ha evolucionado de manera distinta en
www.detodoprogramacion.com
Para poder procesar 10s datos, evaluando expresiones y efectuando operaciones, es precis0 contar con un medio de almacenamiento temporal con el que no
cuenta SQL, ya que &te opera siempre sobre datos almacenados en una tabla de la
base de datos. En Transact-SQL podemos definir variables de distintos tipos, como hariamos en Visual Basic.
La sintaxis para declarar una variable es la siguiente:
DECLARE @ I d e n t if icador T i p o
Observe que el identificador va precedido del simbolo @, que utilizaremos tambikn a1 efectuar una asignaci6n a la variable o recuperar su valor. En cuanto a1 tiPO, tenemos a nuestra disposici6n tipos numericos enteros y con parte decimal de
distintas precisiones (int, smallint, bigint, decimal, money y float, entre
otros), fechas (datetime y smalldatetime), cadenas de caracteres ASCII (char,
varchar y text), cadenas de caracteres Unicode (nchar,nvarchar y ntext) y
secuencias de datos binarios (binary,varbinary e image). Dos tipos especialmente interesantes son table y curs or, permitiendo el almacenamiento de un
conjunto de resultados, en el primer caso, o el recorrido secuencial, fila a fila, de
un conjunto de datos, en el segundo.
Declarada la variable, la asignaci6n de un valor se efectua mediante la sentencia SELECT. Dicho valor puede ser un valor constante, otra variable, el resultado
de una expresi6n 0,incluso, el resultado de la ejecuci6n de una consulta. A continuaci6n tiene un par de ejemplos:
DECLARE P N u r n L i b r o s i n t
SELECT @ N u r n L i b r o s = 5
...
SELECT @ N u r n L i b r o s = COUNT(1SBN)
FROM L i b r o s
Las variables tambien pueden ser de 10s tipos VARCHAR, INTEGER y demhs
tipos indicados anteriormente como estandar en SQL.
Para componer expresiones, Transact-SQL cuenta prficticamente con 10s mismos operadores aritmeticos y relacionales que encontramos en Visual Basic. Tenemos 10s cuatro operadores aritmeticos bfisicos, +, -, * y /, ademfis del operador 8
para obtener el resto de divisi6n entera. Los relacionales son 10s mostrados en la
tabla 2.1.
Tabla 2.1. Operadores relacionales de Transact-SQL
lgualdad
<
Menor que
<=
!<
No menor que
>
Mayor que
>=
!>
No mayor que
<>
Desigualdad
El resultado de la expresi6n puede almacenarse en una variable, asignarse como contenido de una colurnna de una tabla o ser utilizado en otra expresi6n o sentencia condicional.
CS
Las expresiones condicionales pueden utilizarse para ejecutar o no una sentencia, dependiendo del resultado, o bien controlar 10s ciclos de un bucle.
Las sentencias para codificar este tip0 de 16gica son I F , E L S E , W H I L E , C O N T I NUE y BREAK. La forma de utilizarlas no difiere, en esencia, de las hornhimas en
Visual Basic.
I F , E L S E y W H I L E afectan, por defecto, s610 a la sentencia que les siga. En caso
de que nos interese que no sea una, sin0 m~ltipleslas sentencias que se vean afectadas, delimitaremos entonces el bloque mediante las palabras B E G I N , a1 inicio, y
END, a1 final.
www.detodoprogramacion.com
2 . S Q L y sus dialectos
mismo esquema del punto dedicado a Transact-SQL, prdcticamente con 10s mismos ejemplos, per0 con la sintaxis de PL/SQL.
...
SELECT COUNT(1SBN) I N T O N u m L i b r o s
FROM L i b r o s ;
...
END:
Primer0 declaramos la variable NumLibros, de tip0 INTEGER, y, a continuaci6n, efectuamos dos asignaciones. La primera asigna una constante y, por ello, se
utiliza el operador :=. En la segunda el valor se recupera mediante una consulta.
Evaluacicin de exmesiones
En lugar de un valor constante, como en el ejemplo anterior, una variable puede recibir el resultado de la evaluacih de una expresih. 6sta se compondria de
operandos, constantes y / o variables, y operadores aritmeticos y / o relacionales.
www.detodoprogramacion.com
Los operadores aritmkticos son 10s habituales +, -, * y /, a 10s que habria que
afiadir el operador * * que efectua la potenciaci6n. Los aritmkticos =, <, <=, >, => y
! =. Los primeros son equivalentes a 10s indicados en la secci6n de Transact-SQL,
mientras que el ultimo comprueba la desigualdad entre dos operandos. Los operadores 16gicos son AND, OR y NOT.
Utilizando estos operadores, la composici6n de expresiones se efectua de la
manera habitual y puede almacenarse el resultado, para un us0 posterior, o bien
emplearse directamente en un condicional o sentencia similar.
Si deseamos ejecutar una o varias sentencias dependiendo de que una cierta expresi6n sea cierta o no, utilizaremos la sentencia I F/THEN/ELSE, prhcticamente
idkntica a la que existe en Visual Basic. La expresi6n a evaluar o condicional ir6
tras la palabra IF, mientras que las sentencias a ejecutar si dicha expresi6n es
cierta se pondrian tras la palabra THEN. Puede ser s610 una o multiples sentencias,
sin delimitar el bloque en forma alguna puesto que el final vendr6 marcado por un
E N D I F, un E L S E o bien un E L S I F en caso de que necesitemos evaluar expresiones
adicionales:
I F C o r l d i c i h n THEN
s e n tencia s ;
ELSIF C o n d i c i 6 n THEN
s e n t encia s ;
ELSE
sentencias;
END IF;
. . M LOOP
END LOOP;
WHILE C o n d i c i h n LOOP
S e n t e n cia s ;
END LOOP;
La N y M del primer bucle se sustituirian por 10s valores extremos del bucle, por
ejemplo 1y 10, valores que irA tomando Contador mientras se ejecutan las sentencias que hay en el interior del bucle. En el segundo caso tan s610 tendria que sustituir Condicion por la expresi6n condicional a evaluar en cada ciclo del bucle.
2. S Q L y sus dialectos
de c6digo que podemos ejecutar a demanda desde las herramientas de administraci6n o bien desde aplicaciones externas.
La creacion de un procedimiento almacenado se inicia con CREATE PROCEDURE
seguido del nombre del procedimiento y, opcionalmente y entre parhtesis, la lista
de pardmetros que recibird el procedimiento. Estos pueden tener un valor por defecto, especificado mediante la palabra clave DEFAULT. A continuaci6n se dispone
la palabra Is, el bloque de declaraciones de variables (sin el apartado DECLARE ya
que AS actua como punto de partida de dicho bloque) y el c6digo entre 10s habituales B E G I N y END.
En caso de que necesitemos devolver un resultado tenemos dos opciones: definir un pardmetro de salida en la lista de argumentos del procedimiento 0, en su
lugar, implementarlo como funcidn, cambiando PROCEDURE por F U N C T I O N e indicando a1 final de la cabecera, antes de la palabra 1s, el tip0 a devolver mediante
RETURN .
El funcionamiento y resultado de la ejecuci6n de esta funci6n seria como el descrito antes para el procedimiento almacenado Transact-SQL. Si facilitamos un c6digo de editorial se obtiene el n ~ m e r ode titulos con que cuenta, de lo contrario se
retorna el numero total de titulos.
Como ha podido ver en este capitulo, el lenguaje SQL, en general, y 10s derivados de cada RDBMS, en particular, suponen un extenso campo de estudio y aplicaci6n sobre el tratamiento de datos en sistemas como SQL Server u Oracle. Nuestro
objetivo era introducirle en ese campo, aunque apenas araiiando el mundo de posibilidades existentes en el. Ha aprendido, no obstante, a utilizar sentencias DDL
para definir estructuras de datos bdsicas, como las tablas; DML para manipular
esos datos y DCL para otorgar y denegar privilegios a 10s usuarios.
www.detodoprogramacion.com
Aunque muy brevemente, t a m b i h se han descrito algunas de las caracteristicas de Transact-SQL y PL/SQL, dos de 10s lenguajes mAs importantes para programaci6n de bases de datos a1 ser 10s productos asociados, SQL Server y Oracle
respectivamente, dos de 10s m i s extendidos en el mercado.
Parte de 10s conocimientos que ha adquirido en este capitulo le s e r h utiles en
el prbximo, donde 10s pondrii en prtictica a1 usar algunas herramientas de DBMS,
y, por supuesto, en 10s posteriores, a1 introducirnos en ADO.NET.
www.detodoprogramacion.com
'..,.,
www.detodoprogramacion.com
En el primer capitulo, dedicado a terminologia y conceptos generales, conocimos lo que era un origen de datos y, a mod0 de enumeracibn, se citaron algunos
de 10s origenes a 10s que puede accederse mediante ADO.NET, como las bases de
datos, de escritorio y RDBMS, documentos XML o bien hojas de cdlculo Microsoft
Excel. No entramos, entonces, en mayores detalles.
Para poder trabajar desde Visual Basic con ADO.NET, en 10s capitulos posteriores, es indispensable contar con 10s origenes de datos que van a utilizarse. Por
ello, en este capitulo va a conocer algunas de las herramientas y aplicaciones que
le permitirdn crear y configurar dichos origenes de datos, asi como introducir en
ellos algunos datos de partida.
Tras algunos conceptos adicionales, aprenderd a utilizar Microsoft Access, SQL
Server, Oracle, InterBase y Excel con el fin de preparar algunas bases de datos y
documentos. Las indicaciones dadas serdn las suficientes para cada necesidad.
Recurra a la documentaci6n de cada producto, o a bibliografia adicional, si le interesa profundizar en alguna de esas aplicaciones. Tambi6n conocer6 algunas bases
sobre XML y el Directorio activo.
3 . Origenes de datos
datos local cuando tanto la informaci6n como el middleware preciso para acceder a
41 se encuentran en el mismo ordenador, conjuntamente con la aplicacih. Es el caso tipico en configuraciones monousuario, en el que el ordenador aloja programas y
datos e, incluso, no esta conectado a otros equipos en red.
En ocasiones, el acceso a esa informacih local puede efectuarse directamente
desde ADO.NET, sin necesidad de intermediario alguno. Es lo que ocurre, por
ejemplo, a1 trabajar con documentos XML tratindolos como si fuesen conjuntos de
datos. En otras, por el contrario, que la informaci6n este en el mismo equipo donde se ejecuta ADO.NET no implica que pueda manipularse sin mds, precisdndose
ese intermediario en forma de controlador. Un caso asi se encuentra a1 operar
sobre una base de datos Microsoft Access o dBase que est6 en el mismo ordenador.
Cuando el origen de datos es remoto, por ejemplo una base de datos alojada en
un servidor y gestionada por un RDBMS, siempre es preciso contar en el ordenador donde se ejecuta la aplicacibn, el ordenador del usuario final, con un software
cliente dependiente del RDBMS que se emplee. ADO.NET, o el controlador que corresponda, se comunicara con ese software cliente que, a su vez, se comunicar6
con el servidor a trav6s de la infraestructura de red correspondiente. L6gicamente, es necesario tener instalado el software cliente del RDBMS y configurados 10s
parametros de comunicaci6n entre 61 y el servidor. Estos son aspectos que quedan
fuera del Bmbito de este capitulo, en el que se asume que utilizar6 las herramientas
indicadas desde el mismo ordenador en que esta instalado el servidor y se encuentran 10s datos aunque, en la practica, las operaciones indicadas pudieran efectuarse t a m b i h remotamente.
Este producto, que forma parte de la suite Microsoft Office, es uno de 10s gestores de bases de datos mas populares del mercado, especialmente en instalaciones en las que el propio usuario opera sobre la informacibn, utilizando la interfaz
de esta aplicacibn, o bien utiliza una aplicaci6n desarrollada con VBA que se ejecuta directamente dentro de Access.
Desde una aplicaci6n Visual Studio .NET podemos necesitar recuperar la informacion que el usuario gestiona habitualmente utilizando Access 0,incluso, crear
una aplicaci6n que se encargue de actuar como interfaz para ese usuario a fin de
que no tenga que aprender a usar Access. En cualquier caso, en este apartado vamos a conocer algunos elementos de esta aplicacibn, 10s necesarios para crear una
base de datos y editar su contenido.
Comience por iniciar Microsoft Access, en este caso suponemos que la versi6n
es la 2000, se encontrard con un cuadro de diilogo similar a1 de la figura 3.1. Seleccione la opci6n Base de datos de Access en blanco y pulse el b o t h Aceptar.
Introduzca el camino y nombre de la base de datos a crear. La que va a describirse a continuaci6n la encontrar6 en la carpeta Ejemplos del CD-ROM con el
nombre Libros .mdb.
www.detodoprogramacion.com
I
I
I
Y
I
I
. . . . - ~ - . ~ - . ~ . . - - " ~ ~ ~ - "
__
Dado el paso anterior, creando la base de datos, encontrarh una ventana similar
a la de la figura 3.2. En el margen izquierdo aparecen una serie de botones que dan
acceso a las distintas categorias de elementos que pueden existir en una base de
datos Access, mientras que a la derecha se enumeran las opciones que en ese momento hay disponibles en la categoria seleccionada.
www.detodoprogramacion.com
3 . Origenes de datos
Seleccione la opci6n Crear una tabla en vista DiseAo, la primera que aparece en
la lista de la secci6n Tablas, simplemente haciendo doble clic sobre ella. Apareceri
una nueva ventana, con una especie de cuadricula, en la que deber5 introducir el
nombre y tip0 de cada una de las columnas de la tabla que va a crearse. Comenzaremos con las columnas de la tabla Editoriales, como se aprecia en la figura 3.3.
Las columnas y sus atributos serin 10s siguientes:
0
IDEditorial: SerA el identificador de cada editorial. Seleccione el elemento Autonumerico de la lista de tipos de datos y pulse el b o t h Clave principal
que hay en la parte superior. De esta forma la columna obtendri automiticamente un valor numeric0 incrementado para cada fila y que, ademis, actuari como clave primaria, generindose para ella un indice en el que no se
permitirin duplicados.
Nombre y Direccion: Dejaremos estas columnas con su tipo y atributos
por defecto, sirviendo para introducir el nombre y direcci6n de la editorial,
respectivamente.
A1 cerrar la ventana apareceri un pequeiio cuadro de diilogo en el que debe introducirse el nombre de la tabla, tras lo cual volveri a la ventana de la figura 3.2.
Seleccione de nuevo la opcion Crear una tabla en vista DiseAo a fin de definir las
columnas de la tabla Libros, que seran &stas:
www.detodoprogramacion.com
Titulo: Queda con 10s atributos por defect0 ofrecidos por Access.
0
Autor: Lo dejamos con el tip0 Texto per0 ajustando el Tamaiio del campo a
30 caracteres.
Editorial: Seleccionamos el tip0 Numeric0 de la lista desplegable y, en la
parte inferior, damos el valor Si a1 apartado Requerido.
Precio:Seleccionamos el tip0 Moneda como tip0 de dato.
Con esto finalizamos la creaci6n de la segunda tabla con que constar6 nuestra
base de datos. Cerramos la ventana y llamamos Libros a la tabla, volviendo de
nuevo a1 cuadro de didlogo de la figura 3.2.
ci
Estd claro que las dos tablas que hemos creado en el punto anterior guardan
una relaci6n. Concretamente, la columna Editorial de la tabla Libros alojar6 el
identificador de una entrada de la tabla Editoriales. En cierta manera, la tabla
Edi tori a1e s actuard como primaria en una relacidn maestro / detalle o uno-amuchos respecto a la tabla Libros.
Encontrdndose en el cuadro de didlogo de la figura 3.2, en el que ya aparecerdn
las dos tablas recien creadas, pulse sobre el b o t h Relaciones que hay en la paleta
principal. Se abrird un primer cuadro de didlogo del que podrd elegir las tablas a
aiiadir a la relacidn. Seleccione las dos creadas, afiadihdolas y despues cerrando
el cuadro de diilogo. Accederd a otra ventana, similar a la de la figura 3.4, en la
que aparecen representadas las dos tablas. Situe el punto del rat6n sobre la columna Editorial de la tabla Libros,pulse el b o t h principal del ratdn y, sin soltarlo, mu6vase hasta la columna IdEditorial de la tabla Editoriales.
Una vez libere el b o t h del rat6n, se abrird un nuevo cuadro de didlogo (v6ase
figura 3.5) mostrando mdltiples opciones. Active las opciones Exigir integridad
referencial y Actualizar en cascada 10s campos relacionados. Asi consigue dos objetivos: impedir que en la tabla Libros pueda introducirse un identificador que
no exista en la tabla Editoriales y, por otra parte, actualizar automiticamente
las referencias desde la tabla Libros en caso de que se modifique el identificador
de una editorial, algo altamente improbable. Pulse el b o t h Crear.
lntroduccion de datos
El siguiente paso Idgico, una vez creadas las estructuras de la base de datos, es
ahora introducir alguna informaci6n en las tablas. Siempre partiendo del cuadro
www.detodoprogramacion.com
3 . Origenes de datos
de diAlogo mostrado en la figura 3.2, haga doble clic sobre la tabla Editoriales,
o bien selecci6nela y pulse Intro, para abrir la cuadricula de introduccion de datos.
Figura 3.4. La relacion entre las dos tablas una vez establecida
Tab para ir avanzando de una columna a la siguiente y de una fila a otra. Introducidos 10s datos, cerramos la ventana para retornar a1 cuadro de didogo de tareas.
En este momento tenemos algunas editoriales en la tabla E d i t o r i a1e s, totalmente imprescindible para trabajar con la tabla L i b r o s .
Aunque el objetivo que nos marcamos aqui no es otro que tener una base de datos Access con alguna informacih ~ t i para
l
utilizarla desde ADO.NET, creando
www.detodoprogramacion.com
aplicaciones para el usuario, lo cierto es que para nosotros mismos no resulta demasiado c6modo tener que introducir el codigo de cada editorial de manera manual, escribiendo dicho c6digo que o tenemos que recordar o bien comprobar en la
tabla E d i t oriales.
Podemos simplificar esta operacion de forma muy simple. Seleccione la tabla
L i b r o s , en el cuadro de diiilogo de la figura 3.2, y pulse sobre el b o t h Diseiio,
abriendo asi de nuevo la ventana de disefio de la tabla. Seleccione la columna
E d i t o r i a l y, en la parte inferior, abra la p6gina Blisqueda. En ella encontrar6
opciones que permiten asignar a esta columna un control de busqueda. Seleccione
10s valores que se aprecian en la figura 3.8 para cada uno de 10s apartados. Opcionalmente puede establecer el ancho de la columna y otros par6metros.
Ahora, a1 ir a introducir 10s datos de un libro, observarii que la columna E d i t o r i a l tiene asociada una lista desplegable. Puede escribir el c6digo de la editorial 0,si lo prefiere, abrir dicha lista y elegirlo, como se hace en la figura 3.9. No cabe
duda de que resulta mucho miis c6modo, especialmente si son muchas las editoriales existentes y no resulta f6cil recordar el identificador de cada una de ellas.
lntroduzca algunos datos en las tablas para tener inforrnacion con la que trabajar en capitulos posteriores 0,si lo prefiere, tome la base de datos que se faciiita en el CD-ROM, en la que existen algunas entradas.
www.detodoprogramacion.com
Figura 3
lualmente
A diferencia de Microsoft Access, SQL Server es un completo RDBMS, un servidor disponible en varias ediciones en el que es posible utilizar un lenguaje, TransactSQL, para programar procedimientos almacenados y desencadenadores, aparte de
poder definirse tablas, indices, vistas, etc. Visual Basic .NET cuenta con un proveedor ADO.NET nativo para trabajar con SQL Server, ofreciendo el mejor rendimiento posible. Como se indic6 en el capitulo previo, MSDE es el motor de SQL Server
pero, a diferencia de kste, no dispone de las herramientas de administracih que
vamos a usar en 10s puntos siguientes. Para operar sobre MSDE, en caso de que no
disponga de SQL Server, tendria que usar el propio Microsoft Access como interf'az
de usuario.
Puede solicitar una version de evaluacion de Microsoft SQL Server, valida durante 120 dias, en http: //www.microsoft.com/spain/servidores/
sql/productinfo/evaluate. asp. Es una buena opcion si desea probar
este producto. En este ejemplo se utiliza la version 2000 del producto operando
sobre un sistema Windows XP Professional.
www.detodoprogramacion.com
3 . Origenes de datos
Bases de
Seriiuos de bansformaom de dabs
dabs
Sernoor de
bansforma
Admwrebaoon
Dudtcaoon
Seguridad
Serriow
compatb
Meta Data
Servioos de compabbibdad
Serwes
Haga clic con el b o t h secundario del rat6n sobre la carpeta Bases de datos y
elija Crear nueva base de datos. Se abrir6 la pigina Propiedades de la base de
datos, en la que debemos introducir el nombre interno de la base y 10s datos de 10s
archivos en 10s que se almacenar6 fisicamente. En la primera p6gina (figura 3.11) facilite el nombre de la base de datos, Libros,y deje el resto de opciones como est6n.
Las otras dos paginas del asistente se utilizan para configurar 10s archivos de trabajo de la base de datos. Esta puede contar con uno o mas archivos para datos, que
se configuran en la p6gina Archivos de datos, y uno o mas archivos de registro de
transacciones, a configurar en la pigina Registro d e transacciones. Estos archivos
tienen un tamafio inicial, pueden crecer automaticamente y contar con un limite.
Dado que nuestra base de datos no va a contener una gran cantidad de informacion, ni va a experimentar un volumen de transacciones importante, dejaremos
10s padmetros por defecto para ambos archivos. Puede, si lo desea, modificar el
camino y nombre de 10s archivos, como se ha hecho en la figura 3.12. En este caso
se ha aceptado el nombre por defecto, si bien se ha modificado el camino en el que
residirbn. En este momento la base de datos ya est6 creada y aparece en la carpeta
Bases de datos del servidor SQL Server. Hemos dado el primer paso.
_
I
---.-
A diferencia de lo que ocurri6 con Access, que justo tras la creacion de la base
de datos nos encontrabamos con un recipiente vacio, la base de datos SQL Server
r e c i h creada cuenta con una serie de tablas de sistema, diversas funciones y usuarios. Es decir, no estd vacia. Tendremos, no obstante, que definir las estructuras de
datos que necesitamos, comenzando por las tablas donde se alojara la informaci6n. El proceso es similar a1 descrito previamente para Access dado que la interfaz
de usuario es parecida. Abra la carpeta Bases de datos y tambien la base de datos
Libros. Haga clic con el boton secundario del rat6n sobre el elemento Tablas y seleccione la opci6n Nueva tabla.
www.detodoprogramacion.com
Nombre
Los atributos de la colurnna IDEdi t o r i a l le convierte en el atributo de identidad de cada fila. Observe que en la parte inferior (vkase figura 3.13) aparece el valor inicial que tomara esta colurnna, asi como el increment0 que se aplicara a cada
fila sucesiva. En definitiva, tenemos un campo autoincrementado que actua como
identificador unico, que es lo que nos interesa en este momento.
Seleccione de nuevo la opci6n Nueva tabla para proceder con la creacidn de la
tabla L i b r o s . En este caso las columnas y sus atributos ser6n:
0
Editorial: Su tipo ser6 int y desactivamos la opci6n Permitir valores nu10s. Contendr6 el identificador de la editorial, para lo cual estableceremos
despu6s la relaci6n adecuada.
Precio: Elija el tip0 de dato money.
En este momento tenemos definidos todos 10s atributos de la tabla Libros, tal
campos relacionados. El resto de las opciones de integridad referencial estan marcadas por defecto, tal como puede verse en la figura 3.15, a excepci6n del borrado
en cascada. A1 hacer clic sobre el b o t h Cerrar se establecerd la relaci6n entre las dos
tablas. Ahora puede cerrar la ventana en la que estaba definiendo la tabla Libros
asigndndole dicho nombre.
www.detodoprogramacion.com
Tambien podriamos haber definido la relacion posteriormente, tras haber completado la creacion de las dos tablas, ya sea volviendo al cuadro de dialogo de
diseAo o bien creando un diagrama visual de la estructura de la base de datos.
I
--
_I___
-_^_
__I__
__
I
_
---__ _ _ _ ~ - __ __ __-_-_
~
a
4
II
www.detodoprogramacion.com
MOF de la b a r de datosque r va a a M a
s PBDDUsualBasicNET~~mplos
Cap-03 bbms-Data MDF
I-
I 1I
vista
Como se apuntaba anteriormente, SQL Server es un RDBMS con todas las posibilidades que tienen estas aplicaciones, posibilidades algunas inexistentes en Microsoft Access. Una de esas posibilidades es la definici6n de vistas, objetos que se
almacenan en la base de datos y ejecutan a demanda de las aplicaciones cuando 6stas las abren como si se tratasen de tablas. El us0 de las vistas ahorra a las aplicaciones y usuarios la composici6n de consultas mds o menos complejas para poder
obtener 10s datos que necesitan.
Vamos a definir una vista que, aunque simple, nos serviri para conocer 10s pasos que habriamos de dar en cualquier caso. Dicha vista devolverd las editoriales y
10s titulos que les corresponden, estableciendo una relaci6n entre ambas tablas.
Los pasos a dar son 10s indicados a continuacih:
1. Haga clic con el b o t h secundario del rat6n sobre la carpeta Vistas de la base
de datos y luego seleccione del menu emergente la opci6n Nueva vista. Apareceri una ventana con varias secciones, como la de la figura 3.19, inicialmente vacias.
- -
_ _
_ _
~-
7
*
L
gib-
i;r12
3 . Origenes de datos
E d i t o r i a l e s y L i b r o s y pulse el b o t h Agregar. Pulse el b o t h Cerrar para volver a la ventana anterior que, en este momento, mostrar6 el aspect0 de
la figura 3.20. Aparecen las dos tablas, con su relacion, y una consulta SQL
en la parte central
1'1
I>
FROM
1,
Figura 3.20. Aiiadimos las tablas a la vista
3. Haga clic con el boton principal del rat6n sobre las casillas que aparecen a la
izquierda de las columnas Nombre, en la tabla E d i t o r i a l e s , y T i t u l o y
P r e c i o , en la tabla L i b r o s . De esta manera las selecciona como columnas
para el resultado final. Observe c6mo esas columnas aparecen en el panel
que hay debajo del diagrama y t a m b i h en la consulta SQL.
4. Utilice el panel que aparece debajo del diagrama para establecer criterios de
busqueda u ordenacion. Puede, por ejemplo, desplegar la lista de la columna Orden asociada a la P r e c i o para que 10s datos se ordenen ascendentemente por el precio, es decir, de m6s baratos a m6s caros. T a m b i h puede
introducir condiciones de busqueda, por ejemplo que el precio est6 en un
cierto rango.
5. Pulse el b o t h Ejecutar, identificado con un signo de admiracion, para probar la vista y obtener, en la parte inferior, el resultado, como se ve en la figura 3.21. Puede modificar 10s criterios y el orden segun le interese. En la base
de datos de ejemplo no existen criterios y el orden es el obtenido por defecto.
www.detodoprogramacion.com
>
BEWEEN 10,75AND 40
WHERE
Hasta ahora, todos 10s elementos creados en la base de datos SQL Server han sido generados mediante asistentes que se han encargado de producir las sentencias
SQL adecuadas, enviindolas a1 servidor para su ejecuci6n.
A1 crear un procedimiento almacenado, sin embargo, no tendremos m i s remedio que escribir el cbdigo, ya que un procedimiento almacenado es, en si, un bloque de c6digo con un nombre.
www.detodoprogramacion.com
3 . Origenes de datos
T ~ O
REATE PROCEDURE NurnTtdulos
OEdtonal INTEGER
'-1
IL_
It
................ ............
i...............
-alairt&
"
"
- -1.11/11
.........
"
.i
www.detodoprogramacion.com
END
Apress
HcGraw-Bill
www.detodoprogramacion.com
3 . Origenes d e datos
Si ejecuta el procedimiento almacenado NumTi tulos siguiendo el mismo mktodo, Vera que en la parte inferior aparece un mensaje indicando que se ha ejecutado con &xito,per0 no se muestra conjunto de resultados alguno. El Analizador de
consultas SQL recoge 10s valores devueltos por consultas y 10s muestra, como se
ha visto, en la parte inferior, per0 el procedimiento NumTitulos no devuelve conjunto de resultados alguno, tan s610 un numero entero.
Para poder comprobar este procedimiento tendremos que recoger el valor devuelto en una variable, previamente declarada, usando a continuaci6n la sentencia
PRINT para mostrar el contenido en el panel de mensajes, como se ha hecho en la
figura 3.24. Si tras NumTitulos se pone el c6digo de una editorial, obtendra el numero de titulos con que cuenta esta. En caso contrario se indicara el numero total
de titulos que hay en la tabla L i b r o s .
Oracle siempre ha tenido fama de ser un producto robusto, fiable y muy escalable, per0 no precisamente ficil de instalar o administrar. Esto, por suerte, va cambiando en las tiltimas versiones del producto, como la 8i y 9i. Puede obtenerse el
RDBMSdeOracledesdehttp: / / o t n . o r a c l e . c o m / s o f t w a r e / c o n t e n t . h t m l ,
en distintas versiones y ediciones. Tan s6lo tiene que registrarse en OTN, es gratuito, proceder a la descarga e instalaci6n siguiendo 10s pasos indicados.
En 10s puntos siguientes va a utilizarse Oracle8i Release 3 (versi6n 8.1.7) sobre
un servidor Windows .NET Enterprise Server, asumiendo que el directorio raiz de
Oracle es OraHome81. Si en su sistema es uno distinto t6ngalo en cuenta por 10s
cambios que pudieran ser necesarios.
3. Origenes de datos
Pulse el b o t h Siguiente dejando seleccionada la opci6n Crear una base de datos. En el paso siguiente podrfi elegir entre una base de datos Tipica y otra Personalizada. Deje marcada la primera opci6n y pulse de nuevo el b o t h Siguiente.
Oracle puede crear una base de datos nueva copiando las estructuras bfisicas
de un modelo ya existente, almacenado en el CD-ROM del producto, o bien creando dichas estructuras a partir de cero, lo cual siempre es m6s lento. Deje seleccionada la opci6n Copiar 10s ficheros de base de datos existentes del CD y pulse el
b o t h Siguiente una vez m6s.
En el siguiente cuadro de di5logo debe introducir el nombre global para la base
de datos, asi como el SID o identificador 16gico. El primer0 se suele componer del
nombre de la base de datos mAs un dominio, formando asi un identificador Gnico,
mientras que el segundo es un identificador simple. Para este ejemplo, como se ve
en la figura 3.26, llamaremos libros a la base de datos, como en 10s casos previos.
1II bro s
SID:
Una vez tenemos la base de datos creada y en marcha, el siguiente paso serfi la
definici6n de las tablas que la formarh. Abra la carpeta Oracle - OraHome8l de
nuevo de la lista de programas y seleccione la opci6n Database AdministratiowDBA
www.detodoprogramacion.com
Studio para iniciar el Oracle DBA Studio. En el cuadro de di6logo que aparece,
preguntando si desea iniciarlo en mod0 est6ndar o conectando con un servidor de
administracidn, deje seleccionada la primera opcidn y pulse Intro. Transcurrido
un momento, deberia encontrarse con una interfaz como la de la figura 3.29. En el
panel izquierdo aparecen las bases de datos disponibles, conteniendo en su interior objetos tales como esquemas, tablas, procedimientos, etc.
Como ver6, en el Brbol que hay en el panel izquierdo no aparece nuestra base
de datos, la que hemos creado en el punto anterior, por lo que tendremos que afiadirla. Seleccione la opcidn File>Add Database to Tree. Aparecer6 un cuadro de diglogo con dos opciones: afiadir una base de datos manualmente, facilitando sus
datos, o bien seleccionar una de las que aparecen en el archivo tnsnames ora de
Oracle. Seleccione esta segunda opcidn y marque la base de datos Libros,haciendo clic a continuacidn sobre el b o t h OK. En ese momento la base de datos aparecer6 como un nuevo nodo del Brbol.
Haga clic sobre la base de datos para desplegar su contenido, iniciando sesi6n
como administrador de la base de datos (SYSDBA) utilizando la cuenta SYSTEM.
Despliegue la rama Schema y, dentro de ella, elija el nodo Table. Haga clic sobre
www.detodoprogramacion.com
3. Origenes de datos
61 con el b o t h secundario del rat6n y elija la opci6n Create Using Wizard para poner en marcha el asistente de creaci6n de tablas.
I
DBA Studio combines multiple
database tools in one application
Use DBA Studio to administer
b Instances.including startup.
Aunque para este ejemplo, y por inmediatez, vamos a usar la cuenta SYSTEM
para conectar con la base de datos, lo habitual es que se creen 10s usuarios que
van a tener acceso a ella y se utilice una de esas cuentas para operar.
Se pone en marcha el asistente para creaci6n de tablas, compuesto de nada menos que trece pasos. En 10s puntos siguientes se detallan uno a uno, asumi6ndose
que pulsari el b o t h Siguiente a medida que vaya ley6ndolos para ir de una ventana a la siguiente.
1. Introduzca el nombre de la tabla, en este caso EDITORIALES, y seleccione el
esquema del que formari parte. Por defect0 aparece el esquema SYSTEM
porque es la cuenta con la que hemos iniciado sesibn, per0 puede desplegar
www.detodoprogramacion.com
la lista Wich Schema do you want the table to be part of? y elegir cualquiera
de las creadas como ejemplo en la base de datos, por ejemplo el conocido esquema SCOTT.
2. El segundo paso consiste en la definici6n de las columnas que tendri la tabla. A la izquierda aparece una lista, inicialmente vacia, con las columnas,
mientras que a la derecha se reflejan 10s atributos de la columna elegida en
cada momento. Introduzca 10s datos de las columnas siguientes, pulsando el
b o t h Add para ir aiiadihdolas a la lista.
0
Columns Definftion
Columns defined
Pmpetttesof col
Column Name
Column Datatype
size
I1
Scale
Does this column have a defaultvalue7If so, please enter
.xJ
Add
1 Remwe)
- Cancelar
J,
Awda
__
4
@tarlor
Siguiente 9
Termlnar
3 . Origenes de datos
Unique a la derecha. A continuacibn podria establecer restricciones similares para las otras columnas, aunque en este caso las dejaremos con sus valores por defecto.
6. Otro paso que nos saltaremos serfi el sexto, ya que no vamos a aplicar restricciones adicionales de comprobaci6n a ninguna de las columnas de esta
tabla. Como se aprecia en la figura 3.31, no tenemos m6s que elegir una columna, a la izquierda, e introducir la restricci6n a la derecha tras activar la
opci6n Yes, the column has a Check Condition. En la parte inferior aparecen
algunos ejemplos.
7. La ventana de este paso se emplea para introducir opciones especificas sobre almacenamiento. Dejaremos la configuraci6n por defecto y pasaremos a
la siguiente.
Dado que hemos dejado en algunos apartados 10s valores por defecto, el asistente pasa directamente a1 paso 13 y nos muestra la sentencia SQL que se utilizarfi
para crear la tabla (v4ase figura 3.32). Basta con pulsar el b o t h Terminar para proceder a la creaci6n de la tabla.
Utilizando el mismo asistente, vamos ahora a crear la tabla LIBROS.h a contarfi con las mismas columnas que ya definimos previamente en SQL Server o Access,
per0 con 10s tipos de datos de Oracle. La columna IDLIBRO, por ejemplo, ser5 de
tipo NUMBER, a1 igual que EDITORIAL y PRECIO; ISBN Ser6 de tipo CHAR con una
www.detodoprogramacion.com
longitud de 13 caracteres y las demhs columnas serhn de tipo VARCHAR y 50 caracteres como limite.
Defina la columna IDLIBRO como clave primaria y apliquele las restricciones
necesarias para evitar que se introduzcan valores duplicados o que quede con un
valor nulo. Tambikn puede aplicar las mismas restricciones a la columna ISBN.
En el paso cinco deberh establecer la relaci6n entre la columna EDITORIAL de
esta tabla e IDEDITORIAL de la tabla EDITORIALES, tal y como se muestra en la
figura 3.33. Asi se asegura la integridad referencial entre ambas.
Name
UBROS
Schema SCOl?
S
"NOMBRE" VARCMRZ(50) NOT NUL1"DIRECCION"VARCWZ(50
NULL
CONSTMINT" PRIMARY KEYCIDEDITORW). UNIQU
TABLESPACE 'SYSTEM'
'I
Foreign Constraint
constraints on column EDITORW
Yes,me column is 8
www.detodoprogramacion.com
Ahora puede pulsar directamente el boton Terminar para ir a1 ultimo paso del
asistente, revisar la sentencia SQL y, pulsando otra vez el b o t h Terminar, crear la
tabla. En este momento ya tenemos definidas las estructuras que necesitamos.
Summaw
Name
Schema
LIBROS
SCOTT
SQL generated
ll__..l__
_ _ I -.__-l__ll_.l_____lll__
__.~
l
t'
I I:
lDEDllORlAL
NORIBRE
ci ~-
_ _ .DlRECClON
..
- .-.
i__._
__I_-
Anaya Multimedia
McGraw-Hill
_I
~-~
--
Como hicikramos en la base de datos SQL Server, vamos a definir una vista
simple que nos permita obtener una lista de todas las editoriales junto con 10s titu10s que le corresponden. Seleccione la carpeta View, en el panel izquierdo del Oracle DBA Studio, y seleccione la opci6n Create Using Wizard. En este caso el asistente
se compone de 10s siguientes cinco pasos:
1. En la primera ventana introduzca el nombre de la vista que vamos a crear,
LIBROSEDITORIAL, y seleccione el esquema SCOTT para alojarla. Pulse el
b o t h Siguiente.
2. La segunda ventana mostrarA en el panel izquierdo una lista de las tablas
disponibles, junto con sus columnas, a fin de que seleccionemos aquellas que
deseamos incluir en la vista. En la figura 3.37 puede ver c6mo se ha incluido
www.detodoprogramacion.com
3 . Origenes de datos
Selected Columns
vailable Columns
Summary
Name
LIBROSPOREDITORIAL
Schema SCOTT
r ModifyView Definition
This wll override the view deflnltion specifled in the prevlous pages Of
the wizard
i
_
l
_
_
_
,
I
__
Ayuda
Can ce Ia r
I
_
__
, - Anterior
-
(r)
C. Tituln
Editorial
Lpress
Cl,rr
4
Interraw Design lor Frngrammers
Preriu
C.
31
,Anaya Multimedia
1075
(Anaya Multimedia
1075
IAnaya Multimedia
39
(Anaya Multimedia
jAnaya Multimedia
40
39
jAnaya Multimedia
10 75
{Anaya Multimedia
1 0 52
IAnaya Multimedia
37 26
'Anaya Multimedia
1052
IAnaya Multimedia
Anaya Multimedia
jAnayaMultimedia
Anaya Multimedia
i
I
21 04
L
__
_
1052
1 0 5__
2
- _24 04
I
-.
Localice la carpeta Functions y haga clic sobre ella con el b o t h secundario del
ratbn, seleccionando la opci6n Create. Apareceri un cuadro de didogo en el que
tiene que dar tres pasos:
www.detodoprogramacion.com
3 . Origenes de datos
itorla
IN INTEGER IIEFALlLT 0)
N NIIXEEF,
BEGIA
I F IDEdltOrlaI = 0 THEN
*ELECT COUNT(1SBN) I N T U N FFnM Llbros:
EL E
ELECT COUNT(1SBN) IITTIJ N GO21 Llbros
IUHERE EdlcOr1al = IDEditonal:
ElII I F :
FETLIPIJ N:
Observe c6mo se indica que existe un pardmetro de salida, cuyo tip0 es el definido previamente en el paquete LIBROSPKG.Fijese tambidn en c6mo se inserta el resultado de la consulta SQL en la variable Resultado me.diante la sentencia OPEN.
A1 cerrar la ventana habr6 finalizado la creaci6n del procedimiento almacenado
que, en el punto siguiente, ver5 c6mo utilizar.
www.detodoprogramacion.com
3 . Origenes de datos
~ . - I I _ _ - ~
---I_I_
procedimiento almacenado. Despuks, no tenemos m6s que imprimir dicha variable para poder ver el resultado, como se aprecia en la figura 3.43.
En un capitulo posterior veremos c6mo acceder a estos datos desde una aplicaci6n escrita con Visual Basic, utilizando 10s servicios de ADO.NET.
Inter Base
Oracle es un RDBMS disponible en multiples sistemas operativos, segun se
apuntaba anteriormente, per0 no por ello ser5 siempre el product0 mhs adecuado,
www.detodoprogramacion.com
3 . Origenes d e datos
InterBase es un producto adquirido por Borland hace aiios a la empresa AsthonTate, la misma que cre6 dBase. Tras diversos vaivenes, InterBase actualmente es el
RDBMS de Borland y es ampliamente utilizado por aquellos que emplean las herramientas de desarrollo de dicha empresa, entre ellas el conocido Delphi, C++ Builder
y Kylix.
A pesar de sus posibilidades, InterBase es un RDBMS ligero, de pequefio tamafio, y f6cil de instalar, distribuir y configurar. Como todos 10s RDBMS, cuenta con
una parte que a c t ~ como
a
servidor y otra que es el software a instalar en 10s clientes para comunicarse con ese servidor. Ambos pueden instalarse, indistintamente,
en Windows, Linux y Solares.
Actualmente existen dos versiones de InterBase independientes. Una tiene una
licencia de software libre, sin coste per0 sin soporte alguno ni garantia por parte
www.detodoprogramacion.com
Help
ctwn
Login
Desciiption
Login to the relected sewer
Register
Un Register
Diagnose Conn
Pioperties
Add Certificate
6 objeck latec
Habitualmente IBConsole se utiliza en el mismo ordenador donde se ha instalado InterBase y, a1 iniciarse, ese servidor aparece ya como Local Server. De no ser
asi, pulse el primer b o t h que aparece en la parte superior, el que est6 m6s a la izquierda, para registrar el servidor local o un servidor remoto en caso de que este
usando IBConsole desde una m6quina diferente.
Teniendo seleccionado el servidor, en el panel izquierdo, haga doble clic en el
derecho sobre la opcion Login para iniciar sesi6n. Aparecerfi un pequefio cuadro
www.detodoprogramacion.com
--
I,
Server
Local Serve~
Fle(sL
En este momento ya tenemos a nuestra disposici6n una base de datos vacia, por
lo que podemos proceder con la definici6n de las tablas.
www.detodoprogramacion.com
tction
InterBaaeServers
LocalSe,ve,
- e
D
g
l
p
;
Properties
Domainr
Shutdown
Tables
Sweep
4 Views
a9
DatabaseStalirtcs
Indexer
&
Shied Procedures
fx
External F u n c l i ~ r
Generators
Exceptions
Blob Filters
Dcrcrrplion
Disconnect
Roles
Tiansaction Reco
View Metadata
Dalabare Restart
Restart a database
Drop Database
Databare Backup
Connected Users
Rertore Databare
Backup
Cert,laater
seiver Log
& Urm
dimension
Autor VARCHAR(50),
Editorial I N T E G E R ,
www.detodoprogramacion.com
3 . Origenes de datos
Precio DECIMAL ( 6 , 2 ) ,
FOREIGN K E Y (Editorial) R E F E R E N C E S
Editoriales(IDEditoria1)
I
hentrkakd3
AutoMy'oN
Tras ejecutar las dos sentencias puede cerrar la ventana de Interactive SQL. Vera que las tablas aparecen en la carpeta Tables de IBConsole. Abriendo su menti
emergente podri efectuar diversas tareas, como extraer el c6digo DDL o acceder a
su ventana de propiedades.
Volvemos a IBConsole para proceder a la introducci6n de datos en nuestras tablas. Haga doble clic sobre la tabla Editoriales, para abrir la ventana de propiewww.detodoprogramacion.com
dades, y luego seleccione la pdgina Data. En ella puede, como se aprecia en la figura 3.48, introducir 10s datos de las editoriales, sin olvidar asignar a cada una de
ellas un c6digo cinico.
IDependenclesI
3 Apress
Comnt h Relresh
Figura 3.48. Desde IBConsole podemos acceder al contenido de las tablas y editarlo
_
I
A1 igual que para definir las tablas, tendremos que recurrir a la herramienta Interactive SQL para crear la vista L i b r o s E d i t o r i a l . Introduzca el c6digo siguiente y pulse el b o t h de ejecuci6n.
CREATE VIEW LibrosEditorial AS
SELECT E.Nombre, L.Titulo, L. Erecio
FROM Editoriales E, Libros L
WHERE E.IDEditoria1 = L.Editoria1
www.detodoprogramacion.com
La vista es exactamente igual a la definida en 10s puntos previos usando TransactSQL y PL/SQL. Como ya sabe, puede afiadir condiciones adicionales, si asi lo desea, para filtrar 10s datos y obtener s610 parte de las filas.
Para ver el resultado vuelva a IBConsole, haga doble clic sobre la vista, en la carpeta Views, y abra la p6gina Data para ver el resultado. Seri similar a1 mostrado
en la figura 3.50.
Data
I DeDendenciesI
~PRECIO
Use! Interlace Design loi Programmers
31
1075
1075
39
40
39
1075
1052
37 26
1052
21 04
1052
1052
24 04
40
En lugar de volver a IBConsole, tambien puede ejecutar la vista desde Interactive SQL con una Sentencia cOmO SELECT * FROM L i b r o s E d i t o r i a l . El
conjunto de datos resultante aparecera en la parte inferior de la ventana.
La sintaxis para definir procedimientos almacenados en InterBase es ligeramente diferente a la de Transact-SQL o PL/SQL, como seria de esperar a1 tratarse de
un product0 RDBMS de otro fabricante.
Los procedimientos almacenados de InterBase pueden devolver valores, en
realidad varios si bien tan s610 uno de ellos, con el nombre RETVAL, actua como
verdadero valor de retorno. Los parimetros de entrada se declaran entre parkntesis, detris del nombre del procedimiento almacenado, y no pueden tener valores
por defecto.
www.detodoprogramacion.com
Cada una de las sentencias de un procedimiento almacenado InterBase debe finalizar con un punto y coma. Esto es tambien cierto en Oracle. El problema es que
la herramienta Interactive SQL identifica ese mismo carficter como final de sentencia, de tal forma que, a1 encontrarlo, da por terminada la ejecuci6n y, consecuentemente, el procedimiento almacenado no se crea apropiadamente. Para solucionar
este problema, es necesario utilizar la orden S E T TERM a fin de cambiar el finalizador ; por otro carscter, restituyhdolo a1 terminar.
Comencemos definiendo el procedimiento N u m T i t u l o s que, como en 10s casos
anteriores, debe facilitar el numero total de titulos o 10s de una cierta editorial en
caso de facilitarse su c6digo. Introduzca el cddigo siguiente en la herramienta Interactive SQL y ejecutelo.
SET TERM # ;
CREATE PROCEDURE NurnTitulos(CodEditoria1 INTEGER)
RETURNS (RETVAL INTEGER)
AS
BEGIN
IF [CodEditorial = 0 ) THEN
SELECT COUNT (ISBN) FROM Libros INTO : RETVAL;
ELSE
SELECT COIJNT (ISBN) FROM Libros
WHERE Editorial = :CodEditorid1 INTO :RETVAL;
SUSPEND;
END#
SET TERM
La primera sentencia cambia el carficter de fin ; por #, de tal forma que cuando
Interactive SQL encuentre el ; que hay tras el primer S E L E C T no crea que el procedimiento almacenado finaliza ahi. La ultima sentencia devuelve este parsmetro a
su estado por defecto.
Observe que tras la ejecuci6n de un S E L E C T u otro, dependiendo del valor de
C o d E d i t o r i a l , se usa una sentencia llamada SUSPEND. Esta hace posible la devoluci6n del resultado desde el procedimiento almacenado a1 c6digo que lo invoque.
El segundo procedimiento almacenado, N u m T i t u l o s E d i t o r i a l , se crearia de
forma muy similar. En este caso se declaran como valores de retorno tantas variables como columnas sigan a la clfiusula SELECT, introduciendo 10s valores extraidos en ellas mediante INTO.
SET TERM # ;
CREATE PROCEDURE NumTitulosEditorial
RETURNS (Nombre VARCHARISO), NumTitulos INTEGER)
AS
BEGIN
FOR SELECT E.Nombre, COUNT(L.Titulo)
FROM Editoriales E, Libros L
WHERE E.IDEditoria1 = L.Editoria1
GROUP BY E.Nornbre
INTO :Nornbre, :NumTitulos
DO SUSPEND;
www.detodoprogramacion.com
3. Origenes de datos
END#
SEI TERM
Con esto ya tenemos creados nuestros dos procedimientos almacenados. De forma similar podria crear otros m& sofisticados, incluyendo, aparte de condicionales
simples y consultas, bucles y otras operaciones sobre las tablas de la base de datos.
A1 iniciar Microsoft Excel se encontrar6 ya con un nuevo libro en blanco, mostrando la interfaz una apariencia similar a la que aparece en la figura 3.52. El libro tiene un nombre por defecto, L i b r o 1,y cuenta inicialmente con tres paginas llamadas
Hoj a l , H o J a 2 y H o J a3, a las que puede acceder utilizando las pestanas que aparecen en la parte inferior de la ventana.
Observe que el area central tiene el aspect0 de una cuadricula, identificindose
cada columna con una letra y cada fila con un numero. El cruce de cada columna con
cada fila es una celdilla, identificada por la letra de columna y nLimero de fila, por
ejemplo D5. A un conjunto de multiples filas adyacentes, a lo largo de varias filas
y / o columnas, es a lo que se llama rungo.
Haga clic sobre el b o t h que muestra el icono de un disquete. Apareceri el tipico cuadro de dialogo para guardar archivos. D6 el nombre L i b r o s . xls a1 libro.
Ya tiene creado el equivalente a una base de datos vacia.
Nota
En la carpeta de ejemplos de este capitulo encontrara el archivo L i b r o s . xls
tal y como quedaria al final del proceso que va a describirse en 10s puntos siguientes.
Con el objetivo de preparar este nuevo libro para introducir 10s datos que nos
interesan, similares a 10s escritos en las bases de datos de ejemplo, vamos a hacer
algunos cambios en su estructura. Los pasos, muy sencillos, son 10s que se describen a continuacion:
www.detodoprogramacion.com
3 . Origenes de datos
4
5
67 1
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
?m,
Hop1 ,( mJa7
ZFOjz
___
.Isto
Completados estos pasos, tenemos un libro Excel con una estructura similar a
las tablas creadas previamente en Oracle o Access. Como habra observado, no hemos indicado en punto alguno el tip0 de 10s datos, las relaciones, claves, etc. Excel
no es un RDBMS y la mayoria de estos aspectos no se contemplan. El tip0 de cada
una de las columnas, por ejemplo, sera deducido por ADO.NET a partir del contenido que tengan las celdillas.
6
7
Figura 3.53. El libro Excel tras introducir 10s titulos de las columnas correspondientes
a la hoja Editoriales
Intr
Microsoft Excel es una aplicacidn para usuario final y, por ello, la introduccih
de datos resulta muy sencilla, a1 contar con caracteristicas como el autocompletado,
la creacidn automatics de secuencias, etc. h t e , sin embargo, no es un libro sobre
Excel, por lo cual obviaremos toda esa funcionalidad y nos limitaremos a introducir 10s datos, sin mds.
En el punto anterior, a1 escribir 10s titulos de las columnas, ya hemos introducido varios datos en cada una de las hojas del libro, aunque esos datos fuesen 10s titulos o nombres de las propias columnas.
Usando exactamente el mismo m4todo escribiriamos la informacih de cada fila, no tenemos mds que utilizar las teclas del cursor para situarnos en la celdilla
www.detodoprogramacion.com
3 . Origenes de datos
adecuada en cada caso. En la figura 3.54 puede ver el aspect0 de la hoja Libros tras
introducir una serie de datos.
C
1 IDLibro ISBN
2
1 1 853115 94 1
3
2 84415 1136 5
4
3 84415 13243
5
4 84415 1392 9
6
5 84415 1376 7
7
6 84415 1351 1
8
7 81415 1290 6
9
8 81 415 12914
10
9 84415 1261 2
11
10 84 415 1255 8
12
11 84415 1230 2
13
12 84415 1202 7
14
13 84 415 1132 2
15
14 81415 11454
16
15 84 7615 234 5
17
Tilulo
User Interface Design for Programmers
SQL Server 2000
Guia practica para usuarios JBuilder 7
Programaclon con Visual C# NET
Programacion con Visual Studio IlET
Programacion con Visual Rasic NET
Guia practica para usuarios de Visual Basic NET
Guia practica para usuarios de Visual Studio PIET
Programacion con Delphi 6 Kvlix
Guia practlca para usuarios de Delphi 6
Manual a*,anzado Excel 2002
Guia practica para usuarios de Excel 2002
Guia practica para usuarios de Kylix
lntroduccion a la programacion
Manual del microprocesador 80386
Autor
Editorial Precio
3
31
Joel Spolsky
1 1075
Francisco Charte
1 1075
Francisco Charte
1
35
Francisco Charte
1
40
Francisco CharteiJorge Serrano
1
39
Francisco Charte
1 10 75
Francisco Charte
1 10 52
Francisco Charte
1 37 26
Francisco Charte
1 10 52
Francisco Charte
1 21 04
Francisco Charte
1 10 52
Francisco ChattelM Jesus Luque
1 1052
Francisco Charte
1 24 04
Francisco Charte
2
40
Chris H Pappas&William H Murray Ill
I
_
I
_
_
~
_ _~
_~
~ - .-_-^ _
~__
_ _
____ - - -__
- I
La estructura de 10s documentos XML se define mediante esquemas XML, tambien conocidos como esquemas XSD. Realmente, un esquema XSD es un documento XML que sigue unas reglas preestablecidas por el W3C, usando marcas especificas
para la definici6n de tipos y elementos que deben existir en el documento.
Para crear un esquema XSD, a1 igual que para editar cualquier documento XML,
no necesitamos miis que un editor simple de texto, como podria ser el Bloc de notas. No obstante, como usuarios de Visual Studio .NET tenemos a nuestro alcance
herramientas mucho miis sofisticadas, herramientas que pueden ahorrarnos la edici6n manual de este tip0 de archivos. Vamos a emplearlas para crear el esquema
XSD del documento XML que crearemos posteriormente.
Partiendo de un proyecto vacio, abra el cuadro de diiilogo Agregar nuevo elemento y, de la carpeta Datos, seleccione Esquema XML, como se muestra en la figura 3.55. Introduzca en la parte inferior el nombre del archivo donde se alojarii el
esquema, Libros x s d en este caso.
En la superficie de trabajo aparecerii una indicacion comuniciindonos que podemos arrastrar y soltar componentes para comenzar a disefiar. Observe que en la
parte inferior aparecen dos botones: Esquema y XML. Si pulsa este ultimo verii la
definici6n textual del esquema que, a medida que lo disefiemos visualmente, irii actualiz6ndose. Tome del Cuadro de herramientas un complexType e insertelo en
www.detodoprogramacion.com
3 . Origenes de datos
cualquier punto del Brea central. AparecerB un recuadro con dos columnas. Introduzca en la parte superior el nombre que va a darle a1 nuevo tipo, en este caso
Editorial.A continuaci6n vaya introduciendo, en la columna izquierda, el nombre
de cada columna de datos, indicando a la derecha su tipo. En el detalle de la figura 3.56 puede ver c6mo se han definido las tres columnas necesarias para registrar
las editoriales.
I/
Categorias:
Plantillas:
formulanos
...
___
ILibros xsd
Nombre
Cancelar
Ayuda
B K
-_-A
Punter0
element
attribute
attributeGroup
compbxType
simpleType
EZ group
El any
anyAttrlbute
facet
clave
% Relation
IDEditorial
Nombre
Direccion
integer
string
string
I
I
I
El ultimo paso ser6 la inserci6n en la superficie de un e l e m e n t , a1 que llamaremos L i b r o s . La diferencia entre un c o m p l e x T y p e y un e l e m e n t es la misma que
existe entre la definici6n de una estructura de datos y la declaraci6n de una variable. E d i t o r i a l y L i b r o son tipos de datos, a partir de 10s cuales se pueden
crear otros o bien declararse variables que, en el entorno XML, se conocen como
elementos.
Nuestro elemento L i b r o s estar5 compuesto de dos subelementos: E d i t o r i a l e s y L i b r o s . El primer0 de ellos seria de tip0 E d i t o r i a l y el segundo de tipo
L i b r o . De esta forma, el elemento L i b r o s hace las veces debases de datos, mientras que 10s subelementos indicados serian las tablas que habria en su interior. Visualmente el esquema quedaria como puede apreciarse en la figura 3.57. El c6digo
del esquema es el siguiente:
< ? xml v e r s i o rI= " 1 . 0 " e n c o d i ng= " u t f- 8 "
?>
Guarde el documento L i b r o s xsd, esquema que, alojado en un archivo independiente, serviri para establecer la estructura de 10s documentos XML que actuarian como bases de datos, contando siempre con un elemento de primer nivel
L i b r o s que contendria a E d i t o r i a l e s y L i b r o s .
www.detodoprogramacion.com
3 . Origenes d e datos
Irchivo
Edtcion
ter
Proyecto
J--l-G
Generar
pepurar
X Q .
Ezquema
@*
nerramientas
VeEtana
Ayuda
t Debug
q%.
Jadro de herramtentas 4 X
Libros.xrd*
,quema XML
Funtem
E element
A attribute
Libros
Edtoriales
(Libros)
Editorial
Libror
Libra
attributeGroup
E+ complexType
any
)a, anyAttribute
F facet
clave
&
Relation
(Fredetermmado)
(Predetermmado)
(Fredetermmado)
abstract
block
COrnplexType
default
(Predetermmado)
(Fredetermmado)
4 x 5 COmpleXType >
final
fixed
form
(Predetermmado)
5lmpleType
G group
0
Casesensitive
IsDataSet
Locale
Edtoriales
Editorial
Libros
Libro
(Predetermmado)
id
key
(Colecclo")
name
Libros
nillable
(Fredetetmmado)
rubsttutionGrat
type
(Libros)
Varlos
Figura 3.57. Aspect0 visual del esquema XML en el entorno de Visual Studio .NET
Nota
En este ejemplo el esquema XSD utiliza el espacio de nombres h t t p : / /
tempuri . org/,usado habitualmente durante pruebas. En la practica, habria
que sustituirdicho espacio por la referencia correcta donde se encuentre el esquema.
-_________
Partiendo del esquema anterior, crear un documento XML que se ajustase a su
---
"--
___x
-__^(
X I -
____
---___.-ll-__X
-____I_-
inferior el nombre del archivo, por ejemplo L i b r o s . xml. A1 pulsar Abrir se encontrarii en el editor de Visual Studio .NET con un documento compuesto de una
sola linea:
<?xml version="l .O" encoding="utf-t?"
?>
Esta linea indica simplemente que el archivo es un documento XML, comunicando el conjunto de caracteres en que se encuentra codificado.
Acceda a la ventana Propiedades y despliegue la lista que hay adjunta a la propiedad targetschema. Seleccione el elemento http: //tempuri.o r g / L i bros xsd, referencia a1 esquema que hemos creado en el punto anterior. En el
editor apareceri, bajo la anterior, la linea siguiente:
Ya tenemos la marca <Libras> que actua como raiz de todo, como si fuese el
inicio de la base de datos, asi como la marca de cierre </Libras>.
Aunque podriamos ir introduciendo 10s datos manualmente, el editor de Visual Studio .NET se encarga de ir introduciendo de forma automitica las etiquetas
de cierre y, ademis, ofrece listas de posibles etiquetas y parimetros, es mucho
m i s ficil pulsar el b o t h Datos que aparece en la parte inferior del editor. A1 hacerlo nos encontramos con una interfaz como la de la figura 3.58, en la que podemos introducir 10s datos como si de una tabla de una base de datos se tratase. En el
margen izquierdo seleccionamos el elemento a editar, mientras que a la derecha
vamos afiadiendo las filas de datos.
A medida que vamos editando visualmente 10s datos de cada editorial y libro,
Visual Studio .NET se encarga de actualizar el documento XML para que siempre
est6 sincronizado. Tambi6n podemos editar directamente el documento, viendo
posteriormente 10s datos en forma de tabla. Lo interesante es que la informacih,
el documento L i b r o s . xml que puede ver completo a continuacih, es compatible
con todos 10s sistemas operativos, plataformas hardware y Ienguajes de programaci6n. Es, por tanto, el recurso ideal para el intercambio de informacih.
<?xml version="l. 0" encoding="utf-8" ? >
< L i b r o s xmlns="http: //tempuri.org/Libros .xsd">
<Libras>
<IDLibro>l4</IDLibro>
<ISBN>84-415-1145-4</ISBN>
<TItulo>Introduccihn a la prograrnacihn</TItulo>
www.detodoprogramacion.com
3. Origenes de datos
<Lib rc s>
<IDLibro>l2</IDLibro,
<ISBN>84-415-1202-7</ISBN>
<TItulo>Guia prdctica para usuarios d e Excel 2002</TItulo>
<Autor>Francisco Charte/M.JesGs Luque</Autor>
<Editorial>l</Editorial>
<Frecio>l0.52</Precio>
</Libras>
<Lib ro s >
<IDLibro>ll</IDLibro>
<ISBN>84-415-1230-2</ISBN>
<TI t ul o>Manua 1 a v a n z a d o Exce 1 2 00 2</TI tulo>
<Auto r> Franc i sco Chart e < / Au t o r >
<Editorial>l</Editorial>
<Precio>21.04</Precio>
</Libras>
<Libras>
<IDLibro?lO</IDLibro>
<ISBN>84-415-1255-8</ISBN>
CTItulo>Guia prictica para usuarios de Delphi G</TItulo>
iAutor>Francisco Charte</Autor>
<Editorial>l</Editorial>
CPrecio>l0.52</Precio>
</Libras>
<Libras>
<IDLibro>g</IDLibro>
CISBN>84-415-1261-2</SSBN>
<TItulo>Programacihn con Delphi 6 y Kylix</TItulo>
<Autor>Francisco Charte</Autor>
<Editorial>l</Editorial>
<Precio>37.26</Precio>
</Libras>
<Libras>
<IDLibro>8</1DLibro>
<ISBN>84-415-1291-4</ISBN>
<TItulo>Guia pr2ctica para usuarios de Visua Studio .NET</TItulo>
<Autor>Francisco Charte</Autor>
<Editorial>l</Editorial>
<Precio>l0.52</Precio>
</Libras>
<Libras>
<IDLibro>7</IDLibro>
<ISBN>84-415-1290-6</SSBN>
www.detodoprogramacion.com
<Precia>39</Precio>
</Libras>
<Libras>
<I DLibro>5</ IDLibro>
<ISBN>S4-415-1376-7</ISBN>
<TItulo>Programacihn con Visual Studio .NET</TItulo>
<Autor>Francisco Charte/Jorge Serrano</Autor>
<Editorial>l</Editorial>
<Precio>40c/Precio>
</Libras>
<Libras>
<IDLibro>4c/IDLibro>
<ISBN>84-415-1392-9</ISBN>
<TItulo>Programaci6n con Visual C # .NET</TItulo>
<Auto r > Franc i sco C ti a r t e < / Au t o r>
<Editorial>l</Editorial>
<Precio>39</Precio>
</Libras>
<Libras>
<IDLibro>3</IDLibro>
<ISBN>84-415-1324-4</ISBN>
<TItulo>Guia prdctica para usuarios JBuilder 7</TItulo>
<Autor>Francisco Charte</Autor>
<Editorial>l</Editorial>
<Precio>l0.75</Precio>
</Libras>
<Libras>
<IDLibro>l</IDLibro>
<ISBN>1-893115-94-1</ISBN>
<TItulo>User Interface Design for Programmers</TItulo>
<Autor>Joel Spolsky</Autor>
<Editorial>3</Editorial>
<Precio>3i</Precio>
</Libras>
<Libras>
<IDLibro>2</IDLibro>
<ISBN>84-415-1136-5</1SBN>
<TItulo>SQL Server 2000</TItulo>
<Autor>Francisco Charte</Autor>
<Editorial>i</Editorial>
<Precio>l0.75</Precio>
</Libras>
<Editoriales>
<IDEditorial>l</IDEditorial>
www.detodoprogramacion.com
3 . Origenes de datos
&rchvo
EdKi6n
\Ler
Froyecto
senex
j LlbrOS.nml*
pepwar
XML
He%rarmentas
Ventana
Aygda
1 1 x
2
3
4
Francisco Charte
Francisco Charte
Francisco Charte
I5
6
,7
Francisco Charteilorge 5 1
18
19
10
111
12
113
I 14
,15
10,75
10,75
39
40
39
10,75
10,52
37,26
10,52
21,04
10,52
Francisco Charte
Francisco Charte
Francisco Charte
1
1
Francisco Charte
Francisco Charte
Francisco Charte
1
1
Francisco Charte/M.lesu
Francisco Charte
10,52
Francisco Charte
Chris H.Pappas&William
24,04
40
rio
En la mayoria de empresas actuales, especialmente de un tamaiio medio a grande, existen redes heterogheas, diferentes sistemas y todo ello distribuido geogrdficamente en distintas localizaciones que, incluso, se encuentran en distintos paises.
Gestionar 10s recursos de la infraestructura informdtica de este tip0 de empresas
supone un desafio para 10s administradores y, en ocasiones, tambien para 10s desarrolladores de aplicaciones.
Las redes se componen de ordenadores, dispositivos independientes o asociados a un ordenador, tales como impresoras o medios de almacenamiento, grupos o
perfiles, cuentas de usuario, etc. Generalmente cada sistema cuenta con un servicio de directorio propio que facilita la administracion de estos recursos, como el
servicio de directorio de Windows NT o el de Novel1 Netware. Existe un protocolo, bastante aceptado, para acceder a estos servicios de directorio llamado LDAP.
Con el objetivo de simplificar la gestion de recursos en distintos tipos de directorio, Microsoft incluy6 en Windows 2000 Server el Directorio activo (DA para
abreviar) o Active Directory. Mediante DA es posible acceder a recursos de cualquier punto de la red, sin importar el servicio de directorio subyacente del sistema
con que funcionen las mdquinas. Gracias a DA, 10s administradores pueden organizar la informacih de forma mucho mAs coherente y organizada, simplificando
la localizaci6n de 10s recursos y su gesti6n remota.
La information se almacena en el DA con estructura jergrquica, en lugar de relacional al estilo que hemos conocido en 10s puntos previos. En la posicih m6s alta se encuentran 10s bosques, formados For drboles jerdrquicos de dominios que, a
su vez, alojan unidades organizativas. Estas contienen mdquinas, usuarios y otros
elementos.
Por su complejidad, queda fuera del ambito de este capitulo entrar en 10s detalles sobre el funcionamiento y 10s esquemas del DA. Puede encontrar mas information sobre este servicio en h t t p : / / M S D N . M i c r o s o f t . e s .
Los administradores de sistemas acceden a1 DA mediante una interfaz de usuario tipica, similar a la que puede verse en la figura 3.59. En el panel izquierdo aparece la jerarquia de contenedores, en este caso perteneciente a un dominio llamado
es t e l a r n e t , mientras que a la derecha se muestran 10s objetos que existen en el
contenedor seleccionado en ese momento. Mediante operaciones de raton, seleccionando elementos y accediendo a sus respectivos menus de opciones, puede efectuarse cualquier operacidn de gesti6n.
www.detodoprogramacion.com
3 . Origenes de datos
dS
v s l t a Avvda
Builtin
0Computers
lc3J Domain Controllerr
Users
i- &J EarySoft
Administracion
Demono
II
77
Figura 3.59. Herramienta de administracion del Directorio activo
Como desarrolladores, lo que m i s nos interesari es el acceso a1 DA desde aplicaciones propias. Con ese objetivo se utilizan 10s servicios ADSI, una interfaz de
programacih compuesta de msltiples funciones a las que puede invocarse desde
cualquier lenguaje.
Ya que la mayoria de desarrolladores de datos estin habituados a emplear algun servicio de acceso a datos, una forma de simplificar el acceso a1 DA desde las
aplicaciones consiste en utilizar el controlador OLE DB para DA, en lugar de llamar directamente a 10s servicios ADSI. Desde ADO.NET podemos configurar una
cadena de conexi6n con cualquier controlador OLE DB, por lo que podemos usar
ADO.NET para acceder a1 DA y, por ejemplo, localizar un recurso en el que est4
interesado el usuario.
Un metodo alternativo, especialmente simple desde Visual Basic .NET, es usar
10s componentes D i r e c t o r y E n t r y y D i r e c t o r y S e a r c h e r del imbito S y s t e m . D i r e c t o r y S e r v i c e s . Gracias a ellos es posible efectuar todas las operaciones disponibles con ADSI per0 sin tener que llamar directamente a las funciones
de esta interfaz.
Resumen
A lo largo de este capitulo ha creado msltiples bases de datos y documentos,
recursos que nos servirin como origenes de datos para 10s ejemplos a desarrollar
en capitulos posteriores. Por el camino, y aunque muy vagamente, tambien habr6
adquirido cierta familiaridad con algunos de 10s productos, RDBMS y no RDBMS,
www.detodoprogramacion.com
que van a usarse como servidores o productores iniciales de 10s datos. Ha aprendido a definir estructuras de tablas en distintas bases de datos, codificar procedimientos almacenados en 10s lenguajes de varias de ellas, crear vistas y ejecutar algunos
de esos elementos para obtener unos resultados visibles de manera inmediata.
El objetivo principal, mAs a116 de esa familiarizacion con SQL Server, Oracle o
Excel, ha sido definir la estructura e introducir 10s datos que, tal y como se ha comentado, nos servirdn de base para 10s siguientes capitulos. Antes, no obstante,
deberemos conocer tambikn otros elementos, como la estructura de ADO.NET y
sus componentes principales. A ello est6n dedicados 10s dos capitulos que encontrar6 a continuacion de 4ste.
www.detodoprogramacion.com
www.detodoprogramacion.com
Con la denominacion generica ADO.NET se hace referencia a todos 10s servicios de acceso a datos disponibles en la plataforma Microsoft .NET, servicios que
podemos usar desde cualquiera de 10s lenguajes de programacion capaces de producir c6digo MSIL, entre ellos Visual Basic.
Los elementos de ADO.NET est6n pensados para simplificar el acceso a datos,
sin perder por ello flexibilidad y eficacia. Sus componentes se encuentran repartidos por varios imbitos con nombre que, en su mayor parte, tendr6 ocasion de conocer en el proximo capitulo.
Nuestro objetivo, en este capitulo, es obtener una vision general de ADO.NET
desde un punto de vista bastante teorico, obteniendo 10s conocimientos necesarios
para que, a medida que conozcamos estos servicios en 10s siguientes capitulos, comprendamos ficilmente su funcionamiento y raz6n de ser. Desde este nivel, relativamente alto, ser6 m6s sencillo percibir la arquitectura de ADO.NET.
Microsoft cuenta desde hace aiios con un mecanismo de acceso a datos, ADO,
muy asentado en el sector, disponible en la pr5ctica totalidad de las versiones de
Windows y usado por casi todas las herramientas de desarr,ollo disponibles. ADO,
gracias a la existencia de diversos controladores OLE DB, ofrece acceso a origenes
de datos de todo tip0 y facilita a1 desarrollador las operaciones m6s habituales.
www.detodoprogramacion.com
4. Introduccidn a ADO.NET
Para proponer un nuevo modelo de acceso a datos, en este caso ADO.NET, era
precis0 alcanzar unos objetivos que le hiciesen superior a ADO y, por tanto, el
cambio evolutivo de uno a otro, por parte de 10s desarrolladores, mereciese la pena. Dichos objetivos se han llegado a alcanzar y podrian resumirse en 10s siguientes puntos:
0
Modelo de objetos mas simple y racional. Partiendo de unas interfaces genericas, y aprovechando las caracteristicas de orientaci6n a objetos con que
cuentan todos 10s lenguajes .NET, el modelo de objetos es mucho mas simple y fticil de usar, con una curva de aprendizaje m6s suave respecto a ADO.
Tambien resulta mas sencillo extender este modelo, afiadiendo nuevas clases de objetos y componentes.
Representacion y transporte en formato XML. A pesar de que las ultimas
actualizaciones de ADO permitian guardar 10s recordsets en formato XML, lo
cierto es que la integraci6n total con este formato se alcanza en ADO.NET.
La transferencia de 10s datos se efectua en formato XML e, internamente, 10s
conjuntos de datos se representan como documentos XML. Esto simplifica la
interoperabilidad con otras aplicaciones, a1 poder entregar y recoger datos
en un formato entendido por todos 10s sistemas operativos y lenguajes.
Menor us0 de recursos en el servidor. Uno de 10s grandes problemas actuales de 10s RDBMS es la capacidad que tienen para atender solicitudes de conexi6n por parte de 10s clientes, puesto que cada uno de ellos abre una o miis
conexiones y su numero se encuentra limitado fisicamente por 10s recursos
de la maquina. ADO.NET no utiliza cursores en el servidor y, ademas, opera
usando un modelo de conjuntos de datos desconectados y comandos. Esto
significa que la conexi6n se mantiene s610 el tiempo necesario para ejecutar
un comando, ya sea de recuperacion o manipulaci6n de datos, trabajando el
resto del tiempo sin consumir ningun recurso del servidor. El resultado es
que 4ste se hace mucho mas escalable, pudiendo atender a un numero de
clientes muy superior sin problemas y sin necesidad de ampliar 10s recursos.
dependientemente de que nuestra aplicaci6n vaya a ejecutarse s610 en un ordenador de manera aislada o en una configuraci6n distribuida con servidores de datos y aplicaciones.
Los cambios en ocasiones son para mejor y, en 6sta concretamente, seguramente lo serii si comparamos las caracteristicas de ADO.NET con las del sistema de acceso a datos que estemos empleando actualmente.
i6
rn
Aunque ADO.NET cuenta con un mecanismo para lectura directa de datos desde el servidor a1 cliente, utilizando una conexi6n unidireccional y s610 de lectura
especialmente apropiada para la elaboraci6n de informes y tareas similares, lo miis
habitual sera trabajar con conjuntos de datos en el cliente.
Los pasos para obtener un conjunto de datos o Data S e t son, por regla general,
10s siguientes:
1. Se establece una conexi6n con el origen de datos.
2. Ejecuci6n de un comando que recupera informaci6n de dicho origen.
www.detodoprogramacion.com
4. lntvoduccidn a ADO.NET
Servidor de
aplicaciones
t
XML
Cliente Windows
Internet/lntranet
Cliente Linux
Figura 4.1. La transferencia de 10s conjuntos de datos en formato XML abre las puertas
a la interoperabilidad con clientes heterogeneos
Los conjuntos de datos son estructuras dinAmicas. Es posible insertar, modificar y eliminar informacih, operaciones que se registran temporalmente en forma
de DiffGrarns. Estos sirven para resolver posteriormente con el origen de datos, generando 10s comandos apropiados de inserci6n actualizacih o eliminacidn.
Se indicaba en un punto previo que ADO.NET no emplea cursores en el servidor, reduciendo el us0 de recursos en 10s servidores de datos. Si esta acostumbrado a utilizar este elemento en sus aplicaciones, algo habitual en la mayoria de
motores de acceso a datos actuales, seguramente se preguntari c6mo va a poder
efectuar su trabajo sin poder crear un cursor.
Tradicionalmente, las aplicaciones establecian una conexi6n con el servidor y
6ste creaba un cursor que facilitaba el acceso a 10s datos por parte del cliente. Este,
mediante operaciones simples, solicitaba la fila anterior o siguiente, la inserci6n o
edici6n de datos. El cursor se encargaba de bloquear 10s datos que estaban en edic i h , evitando el acceso por parte de otros usuarios, siguiendo un cierto esquema
de comportamiento. El us0 de cursores, y la configuracibn de funcionamiento de
esas aplicaciones, con conexidn continua con el servidor de datos, tenian sentido
especialmente en 10s escenarios cliente / servidor en el que 10s clientes conectaban
directamente con el RDBMS y, ademas, su numero era facilmente predecible segun el tamafio y necesidades de la empresa.
La extensi6n de las tecnologias de Internet y, especialmente, las aplicaciones
que se ejecutan en un cliente Web y 10s servicios Web, han modificado de manera
significativa las necesidades y, por tanto, es preciso buscar nuevas soluciones.
Mantener una conexi6n continua con el servidor de datos no es lo m6s apropiado
y, en ocasiones, ni siquiera es posible en una red donde la conexi6n no est6 garantizada. Ademas, las aplicaciones que emplean 10s clientes suelen ser meras interfaces
de usuario, sin posibilidades de acceso direct0 a un RDBMS y que dependen de
componentes alojados en un servidor de aplicaciones segun la configuracibn esbozada en la figura 4.1.
Tampoco es fticil anticipar el numero de clientes que existiran, especialmente
en aplicaciones que no se ejecutan en una intranet corporativa sin0 a trav6s de Internet y abierta a todos 10s potenciales usuarios. Si cada uno de ellos abriese una
conexi6n con nuestro servidor y crease su propio cursor de datos, posiblemente
nos vi6ramos obligados a incrementar constantemente 10s recursos de la mtiquina,
entre ellos la memoria.
Frente a estos nuevos problemas, ADO.NET ofrece soluciones como el trabajo
sin conexi6n continua y 10s conjuntos de datos sin conexi6n. La conexi6n con el
servidor de datos es transitoria, s610 durante el tiempo preciso para ejecutar un
comando y obtener el correspondiente resultado. Este se transfiere a1 servidor de
aplicaciones o cliente, dependiendo de ddnde est6 ejecutkdose ADO.NET, y a
partir de ese momento se opera sobre un conjunto de datos sin conexi6n. Las acciones tipicas sobre el cursor, como el desplazamiento por las filas, se efectua de
manera inmediata en el cliente, sin tener que enviar una solicitud a1 servidor y esperar la respuesta ni, por supuesto, consumir recurso alguno en el servidor.
Si todas las acciones se efectuan sobre un conjunto de datos sin conexibn, ic6mo se actualiza la informaci6n en el servidor? En el modelo cliente servidor, segun
www.detodoprogramacion.com
4 . Introduccidn a ADO.NET
decia antes, era el propio cursor el que se encargaba de ir bloqueando y gestionando 10s conflictos entre clientes. En ADO.NET se generan comandos de actualizaci6n de forma dinarnica, enviandose a1 servidor cuando es necesario consolidar la
informacibn. En caso de conflicto, se obtiene una enumeraci6n de 10s problemas que
es precis0 gestionar en el cliente.
En resumen, ADO.NET se adapta mejor a las configuraciones distribuidas, utilicen o no Internet como medio de comunicaci6n, a1 tiempo que ofrece una alternativa a1 us0 de cursores en configuraciones cliente/ servidor.
--
___---
_~
_--
- --
Los servicios de ADO.NET dan cabida a las necesidades de todo tip0 de aplicaciones, desde las mas sencillas de tip0 monousuario hasta aquellas que deben operar con conexi6n esporadica a1 servidor. Esto demuestra la flexibilidad y versatilidad
de ADO.NET respecto a otros mecanismos de acceso a datos, mucho mas limitados en cuanto a posibilidades se refiere.
Las distintas combinaciones de componentes ADO.NET, proveedores y controladores dan como resultado diferentes soluciones que pueden aplicarse a multiples escenarios, entre 10s cuales se encontrarian las siguientes configuraciones:
0
Monousuario: Aplicaciones con necesidades bisicas de tratamiento de datos, almacenamiento local de la informacidn, en la misma miquina, y que no
precisan la consolidaci6n con un servidor. Es el modelo representado esquemtiticamente en la figura 4.2, en la que el recuadro representaria a1 ordenawww.detodoprogramacion.com
dor del cliente y 10s elementos que hay en su interior 10s diversos componentes. La aplicacih utilizaria un conjunto de datos ADO.NET que podria
guardar directamente, en formato XML, o bien emplear una base de datos
de escritorio o un documento Excel como deposit0 de la informacih. La primera opci6n es la mas eficiente y simple, ya que no se precisa ninguna otra
aplicacih externa como seria Excel, mientras que la segunda habilitaria la
posibilidad de tratar la informaci6n desde fuera de la aplicacion cliente, con
un product0 estandar.
I-------
Los conjuntos de datos o DataSet pueden guardarse y recuperarse localmente con una llamada a un metodo, siendo la alternativa mas simple y rapida para
el tratamiento de datos en aplicaciones sencillas.
0
4. lntroduccion a ADO.NET
a,
Configuracion cliente/servidor
Figura 4.3. Esquerna de una configuracion cliente/servidor tipica
0
Cliente / Servidor con conexi6n espor6dica: Similar a la anterior, se caracteriza porque el cliente en ocasiones tiene la necesidad de trabajar con 10s datos sin contar con una conexion con el servidor, precisando una consolidation
www.detodoprogramacion.com
v)
configuracion cliente/servidor
con conexion esporadica
Figura 4.4. La configuracion con conexion esporadica es similar a la cliente/servidor
www.detodoprogramacion.com
4. Introduccidn a ADO.NET
Distribuida: Cuando las empresas tienen un cierto tamafio, el mantenimiento de aplicaciones que siguen el modelo cliente / servidor se convierte en un
problema, ya que la actualizaci6n de 10s algoritmos de proceso de la informaci6n se encuentran codificados en la aplicaci6n que ejecuta cada ordenador cliente, lo cual implica que cualquier cambio conlleve una actualizaci6n
a1 nivel de toda la empresa. Las aplicaciones distribuidas solucionan este
problema, a1 aislar la 16gica de proceso de datos en un servidor de aplicaciones que actua como intermediario entre clientes y RDBMS. Es el modelo representado en la figura 4.5. En el aparecen en el servidor de aplicaciones 10s
componentes ADO.NET necesarios para comunicarse con el RDBMS y efectuar todas las operaciones de manipulaci6n de datos. La informaci6n se
transfiere a y desde el cliente, convertido en una simple interfaz de usuario,
usando el formato XML. En este caso se habla de un modelo en tres capas o
three-tier, por ser el m i s habitual, per0 es posible afiadir capas adicionales
segun las necesidades de la empresa.
Web: En realidad es una variante del modelo anterior. Bisicamente se sustituye en el cliente la aplicaci6n nativa, basada en formularios Windows, por
una aplicaci6n tip0 ASP.NET, obteniendose un cliente Zigero ejecutable en
cualquier navegador. Los elementos ADO.NET asi como su distribuci6n serian idhticos.
Como puede ver, ADO.NET solventari nuestras necesidades en todos 10s casos, empleando siempre 10s mismos elementos bisicos: proveedores ADO.NET,
controladores en caso de ser necesarios, adaptadores y conjuntos de datos.
Configuracion distribuida
Figura 4.5. Configuracion de una aplicacion distribuida en tres capas
4. Introduccidn a ADO.NET
Este breve capitulo nos ha servido para obtener, de una manera tebrica, una
idea general sobre las posibilidades y funcionalidad del modelo de acceso a datos
ADO.NET, un modelo compuesto por interfaces y componentes que, en su mayor
parte, va a conocer en el pr6ximo capitulo. Ahora ya sabe que ADO.NET no utiliza
cursores ni conexiones continuas con el servidor para efectuar su trabajo, que 10s
conjuntos de datos se transfieren y almacenan en formato XML y que es posible
utilizar ADO.NET en cualquier configurac%n, desde la mas sencilla hasta la m i s
compleja.
A partir del sexto capitulo, tras conocer en el quinto 10s Ambitos, interfaces y
clases m6s importantes de ADO.NET, comenzar6 a usar todos esos elementos para
conectar con un origen de datos y ejecutar diversos comandos. Todos 10s ejemplos
se basan en el us0 direct0 de ADO.NET, sin ayuda de 10s asistentes, disefiadores y
elementos de Visual Studio .NET. Una vez conozca perfectamente c6mo funciona
y c6mo utilizar ADO.NET, pasaremos, en la tercera parte, a estudiar c6mo Visual
Studio .NET puede ahorrarnos una parte importante del trabajo.
www.detodoprogramacion.com
www.detodoprogramacion.com
Aunque mantenihdonos aun en el campo te6rico iniciado en el capitulo previo, en 6ste vamos a ir conociendo 10s Bmbitos con nombre que componen ADO.NET
y las interfaces y clases que podemos encontrar en ellos, informacion fundamental
para, en 10s capitulos siguientes, ir utiliz6ndolos para conectar con un origen de
datos, recuperar informacih, ejecutar comandos, etc.
Recuerde que en la ayuda electrhica de Visual Studio .NET existe una referencia de toda la biblioteca de clases .NET, en la que encontrara la lista de elementos
relacionados con ADO.NET.
Nuestro objetivo, en este capitulo, es introducir 10s elementos de mayor inter&
y esbozar un esquema general del modelo de objetos ADO.NET, per0 recuerde que
todos 10s detalles sobre Bmbitos, clases y sus miembros se encuentran en la informaci6n de referencia de Visual Studio .NET.
El modelo de objetos ADO.NET est6 construido de forma coherente y facilitando la posterior extensibn, gracias a la herencia y la implementaci6n de interfaces.
Sus elementos podrian clasificarse en dos categorias: dependientes e independientes del origen de datos. En la primera entrarian todas las clases especificas para
cada origen de datos concreto, como pueden ser OleDbDataAdapter y SqlDataAdapter para OLE DB y SQL Server, respectivamente. La segunda se compone de
www.detodoprogramacion.com
5. Modelo de objetos
Los elementos independientes del origen de datos son de us0 general, independientemente de que conectemos con SQL Server, Oracle, dBase, Excel o un archivo
XML. El mayor exponente es la clase DataSet, que representa un conjunto de datos en una aplicaci6n sin importar de d6nde se haya extraido. Las operaciones disponibles son siempre las mismas, lo cual nos facilitarB el trabajo a1 no tener que
recurrir a distintos caminos segun el origen de datos empleado.
Aquellos componentes que necesitan comunicarse con el origen de datos, y entender 10s comandos, funciones y estructuras de este, implementan interfaces comunes a pesar de sus diferencias. Asi, es posible tratar de manera homogenea un
adaptador de datos de SQL Server o de Oracle, por poner un ejemplo, ya que cuentan con similares mktodos y propiedades aunque la implementacibn, como es 16gico, difiere de un componente a otro.
Dada la independencia del origen de datos, las clases de us0 generico, como la
citada DataSet, no necesitan ser extendidas para usos especificos. El conjunto de
datos siempre serd el mismo, sin importar el origen de datos del que se haya obtenido o a1 que se vaya a enviar. Las clases con dependencias, por el contrario, tienen una estructura que permite una ampliaci6n fbcil. Esto ha facilitado, por ejemplo,
que Microsoft aiiada ripidamente proveedores de datos especificos para ODBC y
Oracle a 10s ofrecidos inicialmente con Visual Studio .NET para SQL Server y OLE
DB. De igual manera, terceros fabricantes, e incluso nosotros mismos, podemos
crear proveedores especificos para nuestros origenes de datos.
s ys tem. Data: Aloja las clases independientes del origen de datos, asi como las interfaces que deben implementar las clases que son dependientes.
0
System.Data. SqlClient: Como el anterior, alberga clases especificas para operar sobre un determinado origen de datos, en este caso SQL Server.
www.detodoprogramacion.com
System. Data. SqlTypes: Relacionado con el anterior, en este 6mbito encontramos definiciones de tipos de datos especificos para trabajar con SQL
Server.
acceder a cualquier origen de datos para el que haya disponible un controlador OLE DB.
Para poder utilizar estos dos ~ltirnos,en caso de que 10s necesite, tendra que
aAadir una referencia en la carpeta Referencias del proyecto al ensamblado
correspondiente. En un capitulo posterior se indicara de donde puede obtener
estos controladores y como instalarlos y usarlos.
roveedores
Como se comentaba anteriormente, ADO.NET es un mecanismo de acceso a datos extensible, pudiendo crearse nuevos proveedores que faciliten el trabajo con
otros origenes de datos.
El nucleo de ADO.NET, por tanto, debe estar preparado para operar con proveedores que no conoce de antemano. Esto es posible gracias a la existencia de
unas interfaces genericas, predefinidas en el Ambito system. Data, que todo proveedor de datos, ya sea directa o indirectamente, debe implementar.
Las interfaces de System. Data pueden dividirse en dos grupos: aquellas que
aplicables a cualquier origen de datos, sea o no una base de datos relacional, y las
especificas para bases de datos relacionales. Las primeras inician su nombre, como
es habitual en todas las interfaces, con el prefijo I, mientras que las segundas emplean el prefijo I Db.
Como se ver6 en 10s puntos siguientes, las del segundo grupo suelen estar derivadas de las del primero, contando con algunas implementaciones por defect0
alojadas como clases en el Ambito system. Data. Common.
www.detodoprogramacion.com
5. Modelo de objetos
A1 crear un conjunto de datos local, en el ordenador en el que se ejecuta la aplicaci6n cliente, es preciso establecer una correspondencia entre las columnas del
origen de datos y las existentes en dicho conjunto local. Esas dependencias se representan mediante la interfaz IColumnMapping, implementada en la clase ColumnMapp ing y todas las implementaciones especificas derivadas de ksta.
IColumnMapping es una interfaz compuesta tan s610 de dos propiedades publicas: DataSetColumn y Sourcecolumn. La primera contiene el nombre de la
colurnna en el DataSet,el conjunto de datos local, y la segunda el nombre que recibe en el origen de datos. Cualquier clase que implemente IColumnMapping estd
obligada a implementar estas dos propiedades. Para facilitar dicha operacidn, en
el Bmbito System. Data. Common encontramos la clase DataColumnMapping,
que se limita a implementar las dos propiedades y ofrecer un constructor. Cualquier proveedor puede utilizar esta clase como base para crear las suyas propias
en caso de que fuese necesario, si bien una asociaci6n entre columnas de origen y
locales no requiere un trabajo adicional.
Dado que un conjunto de datos suele estar formado por multiples columnas,
por 16gica tienen que existir varios DataColumnMapping. La interfaz IColumnMappingColl e ction, implementada en la clase Da taColumnMapping Co 11e ction, actua como colecci6n de enlaces entre columnas origen y locales.
En la figura 5.1 puede ver la relaci6n existente entre las interfaces y clases indicadas, asi como sus miembros mds destacables, en este caso las propiedades DataSetColumny SourceColumn.
Las columnas no existen en un DataSet de manera aislada, sin0 que se agrupan en tablas representadas por objetos DataTable. Es preciso, por lo tanto, establecer tambien una correspondencia entre las tablas del origen de datos y las que
existir6n en el DataSet, tarea de la que se encarga la interfaz ITableMapping.
Esta cuenta tan s610 con tres propiedades:
0
Los origenes de datos de tip0 RDBMS son capaces de facilitar un cursor, un motor software que el cliente puede utilizar, en el caso de ADO.NET, para acceder a
www.detodoprogramacion.com
System.Data
IColurnnMapping
IColurnnMappinqCollection
ColumnMapping
ColumnMappingCollection
DataSetColumn
SourceColumn
System.Data.Common
www.detodoprogramacion.com
tir varios.
C l o s e ( ) : Cierra el lector.
Svstem.Data.SalClient
System.Data .OleDb
SqlDataReader
OleDbDataReader
System.Data
IDa taRecord
Fieldcount
Itern
GetXXX ( )
IDa t a R e a d e r
Read ( )
NextResult ( )
Close ( )
OdbcDataReader
Microsoft.Data.Od bc
Figura 5.2. Cada proveedor de datos implementa una clase DataReader que
implementa 10s miembros de las interfaces I D a t a R e c o r d e I D a t a R e a d e r
Como se explic6 en el capitulo anterior, ADO.NET no emplea cursores de servidor para tratar la informaci6n si exceptuamos 10s cursores unidireccionales s610
de lectura representados por las clases DataReader.En su lugar, siempre que es
precisa una navegaci6n mBs compleja o la edici6n de 10s datos, lo que se hace es
ejecutar un comando y obtener un conjunto de datos local o DataSet. Para efectuar esa operation se necesita un adaptador de datos.
Un adaptador de datos es el nexo de uni6n entre un origen de datos y un DataSet, el eslab6n que se encarga de adaptar la informaci6n de las dependencias
propias del origen a1 caricter independiente del conjunto de datos local. Como seria de esperar, cada proveedor de datos cuenta con su propio adaptador especifico, si bien todos ellos implementan una interfaz comun: IDataAdap te r.
Los miembros de la interfaz I Da taAdap te r tienen dos objetivos: recuperar
filas del origen de datos convirtiendolas en filas del DataSet, por una parte, y
generar 10s comandos necesarios para enviar las modificaciones del Data S et de
vuelta a1 origen de datos. Entre sus propiedades y metodos m6s importantes estBn:
0
F i l l ( ) : Es el metodo encargado de recuperar filas del origen de datos incluyendolas en el Data S et local.
Update ( ) : Complementario a1 anterior, efectuaria las operaciones necesarias en el origen de datos para transferir las acciones de edici6n que haya sufrido el DataSet.
www.detodoprogramacion.com
5. Modelo de objetos
En la figura 5.3 se ha representado la relaci6n existente entre las interfaces IDataAdapter e IDbDataAdapter respecto a las clases DataAdapter, DbDataAdapter y SqlDataAdapter,perteneciente a1 proveedor SqlClient.6sta podria
ser sustituida por OleDbDataAdapter, OracleDbDataAdapter o bien OdbcDataAdapter sin cambiar m6s que el 6mbito de System. Data. SqlClient a1
que corresponda.
Svstem.Data
I D b D a taAdapter
IDa taAdapter
Fill ( )
Update ( )
SelectCommand
Insertcommand
Updatecommand
Deletecommand
DataAdapter
DbDataAdapter
System.Data.Common
SqlDataAdapter
Svstem.Data.SalClient
--
- . ~ _ _ _ _ I _ _
___
L O proveedores
~
de datos que acceden a origenes de tip0 RDBMS o bases de
datos de escritorio, la mayor parte de ellos, deben facilitar operaciones adicionales
como es la conexi6n con la base de datos, la definici6n de comandos y control de
las transacciones. Estas operaciones son especificas y diferentes en cada proveedor, per0 con el fin de facilitar, si es que desea, una codificaci6n independiente del
www.detodoprogramacion.com
proveedor, existen las interfaces IDbConnection, IDbCommand e IDbTransaction. Como puede suponer, la primera contiene 10s miembros relacionados
con la conexi6n a la base de datos, la segunda tiene que ver con 10s comandos y la
tercera con las transacciones.
De la interfaz IDbConnection habria que destacar 10s miembros Connectionstring, Open ( ) , Close ( ) , Createcommand ( ) y BeginTransaction ( ) ,
que contiene la cadena de conexi6n a la base de datos, utiliza esa cadena para abrir
la conexibn, cierra la conexidn, crea un nuevo comando asociado a esta conexi6n e
inicia una transaccibn, respectivamente.
En el punto anterior se indico que la interfaz IDbDataAdapter contaba con
cuatro propiedades: S e 1e ct Command, InsertCommand, Upda t eCommand y
Deletecommand. Todas ellas son referencias a la interfaz IDbCommand, en la que
se definen 10s miembros que debe tener un comando que va a ejecutarse sobre una
base de datos.
Las propiedades CommandType y CommandText de la interfaz establecen el
tip0 de comando y el texto, que puede ser el nombre de una tabla, una sentencia
SQL, el nombre de una vista o procedimiento almacenado, etc., dependiendo del
valor dado a CommandType.
Un comando siempre se obtiene a partir de una conexi6n. La relaci6n entre esta
y el comando la fija la propiedad Connection de IDbCommand, conteniendo una
referencia de tip0 IDbConnection.Finalmente, IDbCommand cuenta con una serie de metodos cuya funci6n es ejecutar el comando, ya sea obteniendo un lector
de datos o sin recuperar resultado alguno.
Tambien las transacciones estan asociadas a una conexi6n de base de datos, por
ello la interfaz IDbTransaction tiene una propiedad Connection, como IDbCommand. Por lo demAs, tan s610 hay tres miembros en esta interfaz: IsolationLevel, que determina el nivel de aislamiento de la transacci6n; Commit ( ) , que la
confirma, y Rollback ( ) , que la descarta.
Ninguna de estas tres interfaces cuenta con una implernentacion por defect0 en
el dmbito System. Data. Common,a diferencia de la mayoria de las enunciadas en
10s puntos previos. Son 10s proveedores, directamente, 10s responsables de implementarlas. En cada uno de ellos debe existir una clase XXXConnection, una
XXXCommand y una XXXTransaction, donde XXX seria el prefijo del proveedor:
S q l , OleDb, Oracle u Odbc.
La figura 5.4 resume algunos de 10s miembros de las tres interfaces, asi como
las clases que las implementan en 10s Bmbitos de cada uno de 10s proveedores.
~-
Tras leer 10s puntos anteriores, ya se habra hecho una cierta idea sobre la composici6n de un proveedor de datos .NET y su funcionamiento. Cada proveedor se
compone de una serie de clases que implementan determinadas interfaces definidas en System. Data, ya sea directamente, como ocurre con las tratadas en el
www.detodoprogramacion.com
5. Modelo d e objetos
Svstem.Data
IDbConnec tion
IDbCommand
Connectionstring
open 0
Close ( )
Createcommand ( )
BeginTransaction ( )
II
bqlConnection
OleDbConnection
OracleConnecticn
OdbcConnectior'
CommandType
CommandText
ExecuteReader ( )
ExecuteNonQuery ( )
ID b T r - d n s a ct i o n
IsolationLevel
Commit ( )
Rollback ( )
J
hqlConunand
OleDbCommand
Oraclecommand
OdbcCornmand
(1) System.Data.SqlClient
( 3 ) System.Data.OracleC1ient
bq1,ransaction
OleDbTransaction
OracleTransaction
OdbcTransaction
c
I 1
(2) System.Data.OleDb
( 4 ) Microsoft.Data.0dbc
Figura 5.4. Cada proveedor cuenta con implementaciones especificas de las interfaces
IDbConnection, IDbCommand e IDbTransaction
Todo proveedor de datos debe constar, como minimo, de las clases necesarias
para:
0
base de otras, personalizadas para cada proveedor de datos concreto. Estas clases
son DbDataPermission, DBDataPermissionAttribute, RowUpdatedEventArgs y RowUpdatingEventArgs.
Otros mdtodos, a pesar de no contar con una interfaz gendrica ni derivar de una
clase comitn definida en system. Data. Common, tambidn existen en la mayoria
de proveedores, aunque su implementacih no es obligatoria. Las clases SqlCommandBuilder, OleDbCommandBuilder, OracleCommandBuilder y
OdbcCommandBuilder, cada una de ellas perteneciente a 10s cuatro proveedores
que ya conoce, basicamente son iddnticas de cara a1 programador aunque, como es
logico, internamente cada una de ellas funciona de manera distinta. Su finalidad
es generar las sentencias necesarias para insertar, actualizar y eliminar informaci6n del origen de datos, para lo cual disponen de 10s mdtodos GetInsertCommand ( ) , Getupdatecommand ( ) y GetDeleteCommand ( ) . Lo que se obtiene
es un comando de insercih, actualizacih o borrado especifico para el proveedor
en el que estemos trabajando, de tal forma que una misma llamada, por ejemplo a
Get InsertCommand ( ) , generaria una sentencia distinta segitn que el origen de
datos sea SQL Server, Oracle o un controlador OLE DB u ODBC.
Algo similar ocurre con las clases Parameter,ParameterCollection y Error,
si bien esta ultima no existe en el proveedor de Oracle y, en su lugar encontramos
la clase OracleException.
Por ultimo, cada proveedor aporta sus clases exclusivas, inexistentes en 10s demas proveedores, enfocadas a aprovechar las caracteristicas propias de un cierto
origen de datos. Su USO, no obstante, resulta mucho menos habitual puesto que, en
cierta medida, limita o hace mas dificil una posible transicion futura a otro producto de almacenamiento de datos.
5. Modelo de objetos
Como se indica en la propia ayuda de Visual Studio .NET, el componente Data s e t es un elemento fundamental de ADO.NET, una clase en torno a la que existen muchas otras de las que depende. Un DataSet puede crearse mediante codigo
0, lo que resulta mucho m6s corriente, obtenerse a partir de un origen de datos
mediante el correspondiente adaptador de datos. En el noveno capitulo conocer6
con detalle la forma de trabajar con la clase Data S e t y otras relacionadas con ella,
por ahora nos limitaremos a mencionar sus miembros m6s relevantes. Estos son:
DataSetName: Cada conjunto de datos cuenta con un nombre que le identifica, de igual forma que una tabla, vista o procedimiento almacenado tiene
un identificador Linico. Este nombre normalmente se establece en el momento de la creacion del objeto DataSet, facilit6ndolo como par6metro a1 constructor, mientras que esta propiedad permite tanto obtenerlo como cambiarlo.
0
Relations: Si el conjunto de datos cuenta con varias tablas, entre ellas necesariamente existirAn relaciones. Esta propiedad es una referencia a un objet0 DataRelationCollection que aloja todas esas referencias.
Haschanges ( ) : Devuelve True en caso de que haya alg6n cambio en el
conjunto de datos, ya sea de insercibn, modificaci6n o eliminaci6n. Estos
www.detodoprogramacion.com
cambios se almacenan provisionalmente separados de 10svalores del conjunto de datos original, permitiendose posteriormente su aceptaci6n o rechazo.
Acceptchanges ( ) : Provoca una llamada en cascada a1 m6todo hom6nimo
de cada una de las tablas referenciadas en la propiedad Tables que, a su
vez, llaman a1 mismo metodo de cada una de las filas, propagando asi la
aceptaci6n de todos 10s cambios que hubiese pendientes en el conjunto de
datos.
Re] ectchanges ( ) : Su funcionamiento es similar a1 del metodo anterior,
per0 en este caso deshaciendo 10s cambios en lugar de aceptandolos.
Writexml ( ) /ReadXml ( ) : Guardan y recuperan el conjunto de datos localmente en formato XML, ya sea en un archivo o flujo de datos previamente
preparado.
WriteXmlSchema ( ) /ReadXmlSchema ( ) : Sirnilares a 10s anteriores, per0
afectando tan s610 a1 esquema XML de 10s datos, no a 10s datos en si.
ROWS: Da acceso a la colecci6n de filas de datos que componen la tabla, representada cada una de ellas por un objeto de la clase DataRow.
Columns: Colecci6n de todas las columnas de la tabla. Cada columna se representa con un objeto de tipo Datacolumn.
Constraints: Referencia a un objeto Constraintcollection que contiene todas las restricciones de esta tabla.
PrimaryKey: Identifica la columna o columnas que actdan como clave primaria de la tabla.
www.detodoprogramacion.com
5. Modelo de objetos
Mediante la propiedad Rows se tiene acceso a las filas de datos actuales, pudiendose modificar su contenido o eliminarse. Si queremos aiiadir filas se emplea
el metodo NewRow ( ) del propio objeto DataTable. Los cambios efectuados pueden aceptarse, con Acceptchanges ( ) , o descartarse, llamando a Re] ectChanges ( ) . Utilizando el metodo Select ( ) es posible filtrar las filas de la tabla,
obteniendo s610 aquellas que se ajustan a un cierto criterio.
A1 igual que otras muchas clases, DataTable dispone de multiples eventos.
Con ellos se notifica el cambio del contenido de una columna, el cambio en una fila
o la eliminaci6n de una fila. Todos estos eventos tienen una forma en gerundio y
otra en pasado, por ejemplo RowDeleting y RowDeleted, produciendose el
primer0 en el momento en que va a efectuarse la acci6n y el segundo una vez que
se ha completado.
Fi las
Las filas de datos de una tabla, tal y como se ha indicado en el punto anterior,
se representan mediante objetos DataRow alojados en la colecci6n Rows. Como en
toda colecci6n, es posible aiiadir nuevos elementos, acceder a 10s existentes y
eliminarlos. Una vez tengamos una referencia a un DataRow, a una fila de datos
propiamente dicha, utilizariamos 10s miembros de dicha clase para manipular su
contenido.
Cada fila se encontrar6, respecto a1 estado original de la colecci6n de filas a la
que pertenece, en un determinado estado. h e se aloja en la propiedad s610 de
lectura Rows tate, indicando si se ha modificado, permanece sin cambios, ha sido
aiiadida o eliminada. Las operaciones bisicas que podemos llevar a cab0 sobre la
fila, y que provocan el cambio de su propiedad Rows t a t e, son las enumeradas a
continuacibn:
0
Afiadir una fila. Tomando como base la propiedad Rows del DataTable,
que contiene una referencia a una colecci6n, no tenemos m6s que usar el habitual metodo Add ( ) de cualquier colecci6n para aiiadir una nueva fila.
Eliminar una fila. Basta con llamar a su metodo Delete ( ) .
Modificaci6n del contenido de una fila. La clase cuenta con una propiedad
llamada ~tem, que es la propiedad por defecto, mediante la cual es posible
acceder a cada columna de la fila, ya sea mediante su nombre o con el indice
de posici6n que ocupa en la fila. Este acceso permite tanto leer el valor actual como cambiarlo.
www.detodoprogramacion.com
A medida que se modifican 10s valores de las columnas de una fila, se iran ejecutando automaticamente todas las comprobaciones y restricciones que haya definidas en el conjunto de datos. Esto, en ocasiones, puede no ser lo mas adecuado,
especialmente si van a hacerse muchos cambios que tienen restricciones y, ademas, dichos cambios tienen interdependencias que pudieran causar estados invalidos. De ser asi, antes de iniciar las modificaciones deberiamos llamar a1 metodo
BeginEdit ( ) del DataRow, inhibiendo tanto las comprobaciones como la generaci6n de 10s eventos de cambio. Cuando hayamos terminado de manipular la fila,
confirmaremos todos 10s cambios con una llamada a EndEdi t ( ) . Sera en ese momento cuando se ejecuten todas las restricciones y produzcan 10s eventos. Tambi4n puede utilizarse el m6todo CancelEdi t ( ) para devolver la fila a su situaci6n
inicial.
Las restricciones y tipos de datos de las columnas pueden dar lugar a que, tras
una modificaci6n, una o mas columnas queden en estado de error. La clase DataRow
dispone de la propiedad HasErrors, que nos permite saber si existen o no errores, y el metodo GetColumnsInError ( ) , que devuelve un arreglo con todas las
columnas que tienen errores, pudiendo obtenerse la descripci6n del error.
Nota
A medida que van editandose, las filas de una tabla pueden contar con multiples versiones de valor que almacenan, por ejemplo el valor por defecto, el que
tenia anterior a1 cambio y el posterior. El metodo Hasversion ( ) permite
saber si un cierto DataRow tiene 0 no multiples versiones del valor, en caSO
afirmativo puede accederse a ellos utilizando 10s valores de la enurneracion
DataRowVersion.
Cada una de las columnas existentes en un DataRow cuenta con una serie de
atributos que definen, por ejemplo, el tip0 de informaci6n que puede contener, el
valor por defecto si es que existe, si 10s valores que contendra deben ser 6nicos o
no, etc. Todos estos atributos son accesibles mediante 10s miembros de la clase
Da ta Co1umn.
De esta clase nos interesarin basicamente una docena de sus propiedades, ya
que el resto de 10s miembros son heredados de las clases ascendientes y no tienen
que ver directamente con el trabajo con datos.
Algunas de esas propiedades son:
ColumnName: Nombre de la columna.
DataType: Tip0 de dato de la columna.
0
5 . Modelo de objetos
Unique: Determina si 10s valores de la columna deben ser unicos entre todas las filas de la tabla.
AutoIncrement: Especifica si la columna contiene un valor que se incrementar5 autombticamente.
Como puede ver, 10s miembros de DataRow definen las caracteristicas a 10s
que tendran que ajustarse 10s valores de una cierta columna. Dichos valores, no
obstante, se almacenan en las filas, es decir, en objetos DataRow.
__
- _-
Una de las propiedades de DataTable,llamada Constraints,es la encargada de contener la coleccion de restricciones a aplicar a la tabla, estando definida
cada una de ellas mediante 10s miembros de una clase derivada de Constraint.
Esta, clase abstracta en la que se define la propiedad ConstraintName que albergar5 el nombre de la restriction, es base de las clases ForeignKeyConstraint y
Uniquecons t raint, que representan 10s dos tipos de restriccih m5s habituales.
La clase Uniqueconstraint, aiiadida a la coleccion Constraints de la tabla, asegura que 10s valores que tiene una cierta columna Sean siempre unicos en
todas las filas. Crear un objeto Uniqueconstraints y afiadirlo a la citada coleccion es exactamente igual que dar el valor True a la propiedad Unique del DataColumn que representa a la columna cuyos valores tienen que ser unicos.
Las restricciones de clave externa, correspondientes a la clase ForeignKeyConstraint,son m5s complejas. A1 crearse relacionan una columna de una tabla
con una columna de otra tabla, impidiendo la inconsistencia de sus valores. Adem5s, esta clase dispone de dos propiedades, UpdateRule y DeleteRule,que establece qu6 debe hacerse cuando se modifique o elimine, respectivamente, el valor
de una columna en la tabla maestra que tienen dependencias en la tabla de detalle.
DataRelation, cretindose un objeto a partir de ella por cada relacion que exista
en el conjunto de datos. Una vez se ha establecido una relacion entre las tablas, se
evitar6 cualquier actuaci6n sobre ellas que pudiera infringirla, garantizando la integridad de la informacion.
Las propiedades de DataRelation suelen establecerse en el momento de la
creacion del objeto, facilitando a1 constructor 10s partimetros apropiados. Para ello
se entrega el nombre de la tabla maestra y la columna o columnas que actuan como
clave principal, asi como el nombre de la tabla de detalle y el de la columna o columnas que actuarian como clave externa. Estos valores tambikn pueden ser establecidos con las propiedades ParentTable, Parentcolumns, ChildTable y
Chi IdColumns, respectivamente.
A1 crear una relacion 6sta genera implicitamente dos restricciones que se aplican a las tablas participantes en dicha relacion. Por una parte, se aplica una restricci6n Uniqueconstraint a la columna indicada de la tabla maestra, a fin de que
no pueda repetirse su valor ya que, de ocurrir esto, tendriamos un conflict0 porque no se sabria a quk fila de la tabla maestra corresponden las de la tabla de detalle. Por otra parte, tambien se crea una restriccion ForeignKeyConstraint
aplicada a la columna de la tabla de detalle, impidiendo asi que se introduzcan valores inexistentes en la tabla maestra.
En la figura 5.5 puede ver un esquema de bloques en el que se representa un
DataSet con dos DataTable, relacionados mediante un DataRelation, conteniendo cada uno de ellos sus DataRow, Datacolumn y Constraint, accesibles
mediante las propiedades comentadas en todos 10s puntos anteriores.
Un objeto DataTable facilita en su propiedad Rows todas las filas que contiene la tabla del origen de datos a1 que estti asociado, ofreciendo una vista por defecto. No obstante, partiendo de ese objeto DataTable es posible crear vistas de
datos mtis elaborados gracias a la clase Dataview.Mediante un objeto DataView
las operaciones de busqueda, ordenaci6n y manipulacion de 10s datos resultan
mds sencillas, ya que dispone de las propiedades y mktodos apropiadas para ello.
Los criterios de filtrado y el orden pueden fijarse durante la creacion del DataView o bien posteriormente, sirvikndose de las propiedades RowFil ter, RowStateFilter y Sort. La primera contendrti una cadena de caracteres con las
condiciones de filtrado de filas, la segunda aplica un filtro basado en el estado de
las filas y la tercera determina las columnas sobre la base de las cuales se ordenartin las filas de la tabla.
Teniendo las filas ordenadas, operaciones como la busqueda resultan mucho
mds f6ciles. Usando 10s mktodos Find ( ) y FindRows ( ) de DataView es posible
encontrar la fila o filas que coinciden con el valor clave que se indique, busctindolo
en la columna por la que estti ordentindose. Tambidn pueden usarse 10s mktodos
AddNew ( ) y Delete ( ) para adadir y eliminar filas, asi como editar 10s valores de
las existentes accediendo a ellas mediante la propiedad I tem.
www.detodoprogramacion.com
5. Modelo de objetos
II
DataTable
II
DataTable
DataSet
Figura 5.5. U n conjunto de datos formado por dos tablas relacionadas entre si,
www.detodoprogramacion.com
www.detodoprogramacion.com
Tras instalar Visual Studio .NET tenemos a nuestra disposici6n dos proveedores
de datos: SqlClient y O l e D b . El primer0 es especifico para SQL Server, mientras
que con el segundo es posible emplear cualquier controlador OLE DB instalado en
el sistema, tema sobre el que volveremos despuks. Acceder a un cierto origen de
datos mediante el proveedor OleDb y un controlador OLE DB supone, como es
facil deducir, una capa mas de cbdigo, lo cual implica mayor us0 de recursos y menor rendimiento. Por ello, siempre que sea posible es preferible el us0 de proveedores de datos nativos y especificos para cada origen.
www.detodoprogramacion.com
Tras la presentacidn de Visual Studio .NET Microsoft ha liberado dos proveedores m6s: Oracleclient y Odbc,parar operar directamente sobre bases de datos Oracle y usar controladores ODBC, respectivamente. A continuaci6n se indica
d6nde puede obtener estos controladores y c6mo instalarlos en su sistema.
El primer paso seri localizar 10s proveedores adicionales que haya publicado
Microsoft, en este momento 10s que acaban de indicarse, y transferirlos a nuestro
ordenador. Vaya a la sede M S D N Library de Microsoft introduciendo este URL
http: //msdn.microsoft.com/library/ en su cliente Web habitual. Despliegue la secci6n del menu que aparece a la izquierda el apartado Downloads y seleccione la opci6n Developer Downloads. En el panel de la izquierda habr6 aparecido
una lista jerirquica con distintos nodos. Abra el nodo .NET Framework y alli encontrari 10s proveedores, por ejemplo en ODBC .NET Data Provider y Microsoft
.NET Data Provider for Oracle.
A1 seleccionar uno de 10s nodos, aparecer6 un documento facilitando diversa
informaci6n y un enlace para obtener el archivo de instalaci6n del proveedor. En
la figura 6.1, por ejemplo, puede ver el documento del proveedor para Oracle, con
el enlace en la parte superior derecha. Obtenga el archivo y repita el paso con el
proveedor ODBC.
~~~~~
~ %,
Wel~ometo Downloads
CDmpOnentDeYelopment
1,351
07J17J2002
NO
NET Framework
0
0
0
0
0
0
custom s e t u p
select the way you want k a t u r s to be mrtakd
a& on the m
1-
Miuosoftaade .MTDataFravdef
www.detodoprogramacion.com
Tal como ya se indicara en el capitulo anterior, la mayoria de las clases implementadas por 10s proveedores tienen una clase base comun o bien implementan una
misma interfaz. En este caso se da lo segundo, y la interfaz que determina la lista
minima de miembros con que deben contar 1as clases de conexion es IDbConnection.La relacion entre esta interfaz y el conjunto de clases que la implementan es
la mostrada esquemiiticamente en la figura 6.3.
Aunque, como ya sabe, no es posible crear objetos a partir de una interfaz, nada
nos impide almacenar la referencia devuelta por el constructor de una de las clases
Connection en una variable de tip0 IDbConnection.Esto nos permitird codificar de manera generica 10s pasos de la conexion, conociendo tan so10 10s miembros
de esta interfaz.
Component
7
I D b Connec tion
Sqlconnection
Figura 6.3. Las clases Connection de 10s distintos proveedores implementan
la interfaz IDbConnection
- ~ _ _ _ _ _ _
~
l_^-...-_l__l_^___l_----------
Existe una sede Web, llamada CONNECTIONSTRINGS, en la que puede encontrar inforrnacion rapida sobre las cadenas de conexion para acceder a 10s
origenes de datos mas usuales mediante OLE DB y ODBC. El URL de dicha
sede es http: //www.connectionstrings. corn.
I_
___ ___
__
_
I
I
_-
__ ___
__
___
_l____l_
___I__ I__
-~
______
Tras abrir la conexion, con el comando Open ( ) , se conecta con una base de
datos o archivo que dependera de 10s parametros facilitados en la cadena de
www.detodoprogramacion.com
conexion. Puede cambiarde una base de datos a otra, sin necesidad de cerrar
la conexion y volver a abrirla, mediante el metodo ChangeDatabase ( ) .
Aparte de Connectionstring y State, en la interfaz IDbConnection existen dos m6s cuyo unico objetivo es facilitar el nombre de la base de datos que estti
utiliztindose, en el caso de Database,y el tiempo mdximo de espera antes de cancelar un intento de conexih, en ConnectionTimeout. Estos son datos que, normalmente, se facilitan en la cadena de conexibn, aunque la base de datos tambi4n
puede especificarse mediante el metodo ChangeDatabase. Estas dos propiedades son s610 de lectura.
Los otros dos miembros de la interfaz IDbConnection, Createcommand y
BeginTransaction, no nos interesan en este momento ya que no tienen que ver
con el establecimiento de la conexion propiamente dicha.
MSDataShape
MS Pers is t
MSDAIPP.DS0
ADSDSOObj ect
MSIDXS
Microsoft.Jet.OLEDB.4 . o
MS DASQL
MSDAORA
SQLOLEDB
MSDAOSP
www.detodoprogramacion.com
Los nombres de 10s controladores ODBC suelen ser mucho mfis descriptivos
que 10s anteriores. Para utilizar el controlador para Access u Oracle, por continuar
con 10s mismos ejemplos propuestos, usariamos 10s identificadores { Mi c r o s o f t
A c c e s s D r i v e r ( * . m d b ) } y { M i c r o s o f t ODBC f o r O r a c l e } , respectivamente. Observe que se han utilizado unas llaves para delimitar a 10s identificadores, llaves que hay que incluir en la cadena de conexion.
A continuacion, suponiendo que ConnOleDb tiene una referencia a un objeto
O l e D b C o n n e c t i o n , puede ver varios ejemplos de selection de controlador. Tenga en cuenta que estas cadenas de conexion no son vhlidas, ya que ademfis del controlador son precisos parfimetros adicionales antes de poder llamar a Open ( ) para
establecer la conexion.
OLE: DB par-a SQL S e r v e r
e c t i o n s t r i r i g = " t ' r - o v i r r i e r = s q l ~ ) l e ~ J. b. .
' Controlador
'
...
C n n t r o l a d o r O L E DB d e M i c r o s o f t p a r a O r a c l e
e c t i a r , S i . r i r l g = "Prc\liitr=rr~s'~aora
...
Si en lugar de un objeto O l e D b C o n n e c t i o n hubiesemos creado un OdbcConn e c t i o n , para servirnos de un controlador ODBC, el formato de la cadena de conexi6n seria similar al mostrado en 10s ejemplos siguientes:
' C o r l t r c , l a d o r ODBC p a r a S Q I , S e r v e r
C o n r ~ O d h c . ~ o n n e c t i r ~rr i~nSgt = " D r i v e r = { S Q L S e r v e r ]
"Ijriver=iI'licrcr:;oft
Acces:,
Driver
(*.mdb)
...
Nota
Ademas de 10s controladores OLE DB y ODBC que se instalan por defect0 con
Windows y ciertos productos, como Visual Studio .NET, existen otros, desarrollados por terceros fabricantes, para facilitar el acceso a sus productos. En:
h t t p :/ /
1.1
i)
1e r i b V e n .h t m
puede encontrar una lista de productos relacionados con OLE DB, principalmente controladores, y en:
h t t F) : / / o u rwci r 1d . c ompii s e r v e . corn / h o m s p a g e s / K e rl N 0I-t h / O D B C V e rlii . H TM
~
__--__~~-
____
___-_~
--
--^___-
^
I
--
Lo mismo valdria para el proveedor OLE DB, anteponiendo Provider=sqloledb, o el proveedor Oracleclient. En el caso del proveedor ODBC, tan s610
hay que cambiar Data Source por Server.
En caso de usar 10s proveedores OLE DB u ODBC para acceder a un origen de
datos no RDBMS, como puede ser una base de datos Access o una hoja de c6lculo
Excel, el dato a facilitar es el camino y nombre completos del archivo. A causa de
ello, el parametro Server del proveedor ODBC se sustitira por Dbq, por ejemplo:
..__._____
........ _.
........ ._
......_II_..
.
.I
__.._...... .
.,..._I
Para acceder a una base de datos Access o una hoja de c6lculo Excel basta con
conocer el nombre del archivo en que se encuentra, per0 a1 trabajar con un RDBMS,
como Oracle o SQL Server, no basta con conocer el nombre del ordenador en el que
est6 ejecut6ndose el servidor. AdemAs, es precis0 que indiquemos sobre cu61 de las
bases de datos existentes en 41 deseamos trabajar.
Los proveedores OleDb y Sqlclient admiten en la cadena de conexi6n la
propiedad I ni tia1 Cat a1og,a la que se asignaria el nombre de la base de datos.
Si utilizamos el proveedor Odbc, la propiedad a usar es Database.
En ocasiones, para poder conectar con un determinado origen de datos es precis0 identificarse adecuadamente ya sea directa o indirectamente. La seguridad es
www.detodoprogramacion.com
un aspect0 especialmente importante en 10s sistemas RDBMS, depositos de informaci6n de las empresas y que deben estar resguardados de acciones, accidentales
o intencionadas, y la revelacion de datos confidenciales a terceros.
Como acaba de decirse, la identificacion ante el origen de datos puede ser directa o indirecta. En el primer caso se entregan de manera explicita un nombre de
usuario y una clave, mientras que en el segundo se deja que sea el sistema, en el
que previamente hemos iniciado sesion, el que presente nuestras credenciales ante
el servidor de datos. La propiedad Integrated Security determinarh qu6
metodo va a utilizarse. Presente en tres de 10s cuatro proveedores, hay que exceptuar Odbc, esta propiedad puede tomar 10s valores yes o no. En el primer caso se
utilizar6 la seguridad integrada del sistema para identificarnos, mientras que en el
segundo habr6 que entregar un nombre de usuario y clave.
&
El valor asignado a la propiedad User ID en la cadena de conexion del proveedor Oracleclient determina el esquema inicial de trabajo al conectar
con la base de datos.
www.detodoprogramacion.com
"
"
I
"
xI____I__--I________I
- - ~
AdemAs de todas las anteriores, que son las de us0 m6s habitual y general entre
proveedores y controladores, tambi6n existen propiedades que son exclusivas de
un cierto proveedor o controlador. Estas propiedades se introducen en la cadena
de conexi6n siguiendo exactamente el mismo procedimiento, especificando el nombre de la propiedad y el valor separados por un signo =. Para poder conocer las
propiedades exclusivas de cada proveedor o controlador tendr6 que consultar su
documentaci6n.
A1 final del punto anterior, tras revisar 10s distintos par6metros que pueden
formar parte de una cadena de conexih, se han propuesto varias asignaciones
distintas para la propiedad Connectionstring de varios objetos Connection.
S610 con esto ya estariamos en disposici6n de conectar con el origen de datos, que
es lo que perseguimos, llamando a1 m6todo Open ( ) inmediatamente despu6s de
la asignaci6n.
Si la cadena de conexi6n tiene el formato correct0 y, adem&, la configuraci6n
de red, el estado del servidor y otros par6metros permiten conectar con el origen
de datos, la propiedad State deberia cambiar de Closed a Open. Cualquier incidencia que impida la conexi6n provocara una exception, por ejemplo Argumen tException si hay un parametro incorrect0 en la cadena de conexion.
En 10s puntos siguientes va a tratarse, paso a paso, el proceso para conectar con
algunos de 10s origenes de datos creados en un capitulo previo, comprobando esa
conexi6n y cerrindola finalmente. El resultado no sera muy espectacular, per0 es
el primer paso en el tratamiento de datos con ADO.NET.
ss
~-
Vamos a comenzar por uno de 10s casos m6s simples, escribiendo un pequefio
ejemplo en Visual Basic .NET que conecte con la base de datos Access que habiamos
creado en el tercer capitulo. Para ello no es necesario que en el ordenador donde
est6 la base de datos, y va a ejecutarse este ejemplo, se encuentre instalado Microsoft
Access, basta con la instalaci6n de 10s MDAC.
Por simplicidad, estos primeros ejemplos van a crearse como aplicaciones de
consola. Simplemente genere una aplicaci6n de consola vacia, utilizando el asistente Aplicacion de consola, y a continuaci6n introduzca el c6digo indicado que,
en este caso, seria el siguiente:
Imports Systern.Data.OleDb
www.detodoprogramacion.com
>
( )
C n n n O 1 e ~ b . C ~ n n e c t i o n S t r i n=g
" P r o v i i ~ r = M i c r o s o f tJet.OLEDB.4.0;
.
"
&
"Data Source-\PBddVisualBasicNET\Capp03\Libros.nidb"
CorlnOleDb.C
Else
'
End I f
Catch '
sole.WritPLine["*** Error a 1 irlterltar l a c u n e x i u n * * * " 1
End T r y
End Sub
End Module
- 10:x
exe
Figura 6.4. Conseguimos conectar sin problemas con una base de datos Access
El mismo controlador OLE DB que hemos utilizado para conectar con Microsoft
Access, Microsoft. Jet.OLEDB. 4. 0, nos servir6 tambien para acceder a cualquier hoja de c5lculo Excel. Lo unico que tenemos que hacer es cambiar la cadena
de conexibn, facilitando el camino y nombre del libro.
Ademds, tendremos que usar el pardmetro Extended Properties,utilizado
para enviar a1 controlador pardmetros exclusivos, indicando que lo que va a abrirse es una hoja de Excel y, opcionalmente, si la primera fila de cada hoja contiene titulos de columnas o no.
Tomando como base el c6digo anterior, cambie la asignaci6n a la propiedad
Connectionstring para que quede como se muestra a continuacih:
C o n n O l e D b . ConnectionString
= -
"
&
Observe c6mo las propiedades extendidas, que en este caso indican que el
archivo es un libro de Excel que cuenta con una cabecera de titulos, se delimitan
entre comillas simples. De no hacerlo asi, el pardmetro HDR=Yes pasaria a1 proveedor OLE DB de ADO.NET, que intentaria interpretarlo y, a1 no reconocerlo,
provocaria un error. Con el entrecomillado conseguimos que ese pardmetro, junto con Excel 8 . 0, pase directamente a1 controlador OLE DB de Microsoft Jet.
www.detodoprogramacion.com
___
Nota
Para acceder mediante el controlador OLE DB a una hoja de calculo Excel no
es necesario tener instalado Microsoft Excel en el equipo.
Tanto Access como Excel son origenes de datos a 10s que se accede localmente,
sin necesidad de utilizar un software cliente para, a trav4s de protocolos de red,
comunicarse con un servidor que se encargue de efectuar fisicamente la manipulaci6n de 10s datos. De ahi que la conexi6n sea bastante sencilla, como acaba de verse en 10s dos puntos previos.
Para poder conectar con nuestra base de datos SQL Server deben darse 10s siguientes requisitos:
0
El servidor SQL Server, ya sea 7,2000 o MSDE, debe estar en funcionamiento, bien en el mismo ordenador donde va a ejecutarse la aplicaci6n o en un ordenador remoto al que se tenga acceso mediante una infraestructura de red.
En el equipo donde va a ejecutarse la aplicaci6n debe haberse instalado el
software cliente de SQL Server. Esto no es necesario si es el mismo equipo
donde est6 ejecut6ndose el RDBMS o bien se trata de un ordenador donde se
ha instalado la plataforma .NET y la ultima versi6n de 10s MDAC, que ser6
nuestro caso.
www.detodoprogramacion.com
Hay que conocer el nombre del servidor donde est6 ejecut6ndose el RDBMS,
asi como disponer de una cuenta, nombre de usuario y clave, para poder conectar con 61 en caso de que no vaya a utilizarse la seguridad integrada.
En caso de que vayamos a ejecutar el ejemplo siguiente en el mismo equipo
donde estii ejecutiindose el servidor, podemos cambiar el valor de Data Source
por localhos t.En mi caso SQL Server se ejecuta en una miiquina distinta, de ahi
que sea precis0 indicar su nombre. Ademiis, va a utilizarse la seguridad integrada
de Windows, empleando nuestra cuenta de acceso a1 sistema cliente para identificarnos ante el servidor y poder acceder a1 RDBMS.
Si tiene problemas con el acceso al servidor a causa de la configuracion de seguridad, facilite explicitamente un nombre de usuario y clave 0 ,en su defecto,
consulte con su administradorde red para que configure su cuenta de tal manera que pueda acceder a SQL Server.
Asumiendo que se cumplen todos 10s requisitos previos, y que hemos comprobad0 que es posible el acceso desde el cliente a1 servidor utilizando el software
cliente de SQL Server, 10s pasos para conectar con la base de datos, partiendo del
c6digo del punto anterior, serian 10s indicados a continuaci6n:
Sustituci6nde System.Data.0leDb por System.Data.SqlC1ient e n l a
instrucci6n Imports, a1 inicio del m6dulo de c6digo.
0
"
&
Cambio de las referencias a la variable ConnOleDb por ConnSql en las lineas siguientes del programa.
Por lo demis, la configuraci6n para poder conectar con nuestra base de datos
InterBase, creada en el tercer capitulo, no difiere de la explicada en el punto anterior para SQL Server, siendo precis0 tener el RDBMS en funcionamiento, ya sea en
el equipo local en un servidor, el software cliente instalado en el ordenador donde
vaya a utilizarse la aplicacidn y la configuracibn correcta de red para comunicar
cliente con servidor.
"
&
"Database=\PBddVisualBasicNET\Cap_03\Libros.gdb;"
&
"UID=SYSDBA; PWD=masterkey")
A pesar de que la facilidad de us0 del RDBMS Oracle ha ido mejorando de versi6n a versibn, hasta llegar a las actuales 8i y 9i, lo cierto es que resulta un product0
www.detodoprogramacion.com
bastante mds complejo que cualquiera de 10s tratados en 10s puntos previos. El
proceso de conexih, desde el cbdigo, no difiere del utilizado en 10s ejemplos anteriores, pero, para que funcione, es precisa una preparacidn preliminar configurando 10s servicios en el software cliente.
C:WBddVbua8aricN~CaP~06\o1texlonOdbc\bin\onewionOdbc exe
-101 x
www.detodoprogramacion.com
....................................................................................................
fi Conriguracion del Nombre del SeMcio de Red Local
....................................................................................................
... f?:;
/ei-m
Una vez que el asistente conoce todos 10s parAmetros necesarios, en el paso siguiente se ofrece la posibilidad de efectuar una prueba de conexih. Seleccione la
www.detodoprogramacion.com
opci6n Si, realizar una prueba y pulse el b o t h Siguiente. El resultado obtenido deberia ser el de la figura 6.10. Si obtiene un error revise toda la configuraci6n previa
pulsando el b o t h Anterior.
.. ..... ..... ..
...
Detalles
____I__
~
~
l
l
l
~
_
_
_
_
l
l
-
Carnbiar Conexid"]
-
Para efectuar la prueba de conexion, el asistente utiliza la cuenta y clave creadas a mod0 de ejemplo en todas las bases de datos Oracle, Scott y tiger.
Puede pulsar el boton Cambiar Conexion, en la ventana de resultado de la
prueba de conexion, para cambiar el esquema y clave y probar con 10s que haya definido o le haya indicado su administrador de bases de datos.
Por tiltimo, antes de volver a1 inicio del asistente, tendri que introducir el nombre de servicio local para acceder a esta configuracih. Introduzca Libros y pulse el b o t h Siguiente. Salga del asistente, ahora ya est6 en disposici6n de introducir
el c6digo Visual Basic .NET para conectar con la base de datos.
Al igual que con el proveedor ODBC, es precis0 agregar en el proyecto una referencia al ensamblado que contiene el proveedor para Oracle, el ensamblado
System.Data.OracleClient.dl1.
El c6digo base utilizado en todos 10s ejemplos anteriores tendr6 que sufrir las
modificaciones siguientes:
www.detodoprogramacion.com
La variable de conexi6n ahora seria de tip0 Oracleconnection y la cadena de conexibn, entregada a1 constructor, seria "Data Source=Libros ;
User ID=scott; Password=tiger".
Habria que eliminar el acceso a las propiedades Database y ConnectionTimeout que mostr6bamos m6s abajo, ya que el proveedor Oracle carece de
ellas, pudiendo mostrar en su lugar el contenido de la propiedad ServerVersion.
En 10s cuatro ejemplos del punto anterior, conectando con diversos origenes de
datos, hemos introducido siempre 10s parfimetros de conexi&, tales como nombre
de servidor, usuario y clave, directamente en la propia cadena de conexi6n. Esto,
www.detodoprogramacion.com
en ocasiones, puede resultar un inconveniente, ya que cualquier cambio que hubiese que efectuar, por ejemplo por cambiar el RDBMS de un servidor a otro, implicaria una modificaci6n del cbdigo, recompilaci6n y redistribucih de la aplicacih.
Hay disponibles distintas alternativas para evitar este potencial problema, comenzando por la posibilidad de que el usuario configure, en la misma aplicacih,
pardmetros como el servidor para lo cual, logicamente, tendriamos que habilitar
esa posibilidad.
Si estamos utilizando el proveedor Microsoft ODBC para .NET, una alternativa
es la configuracih de un DSN, un mecanismo por el que toda la informacih de
conexihn, exceptuando generalmente el nombre de usuario y clave, se asocia con
un identificador. Este se almacena en el registro de Windows o bien en un archivo,
pudiendo utilizarse posteriormente desde c6digo en sustituci6n de 10s par6metros
a 10s que representa.
Los DSN siempre tienen el mismo objetivo y cuentan con 10s mismos parGmetros,
per0 la forma en que se almacenan hace que pueda hablarse de tres categorias diferentes de DSN:
De usuario. La informacih se almacena en el registro de Windows, concretamente en la rama perteneciente a un determinado usuario. De esta forma,
ese DSN s610 puede utilizarlo el usuario a1 que pertenece.
0
Elegir un tip0 u otro depended directamente de las necesidades de cada proyecto. En cualquier caso, recuerde que un DSN puede utilizarse tan so10 desde ODBC,
no resultando Gtil con 10s otros proveedores ADO.NET.
que en las piiginas DSN de usuario, DSN de sistema y DSN de archivo encontrarii
10s DSN de cada tip0 existentes en este momento.
Seleccione la pdgina DSN de sistema y pulse el b o t h Agregar. Elija de la ventana que aparece, con una lista de todos 10s controladores, el controlador Microsoft
Access Driver (*.mdb), haciendo doble clic sobre el. Entonces verii la ventana Configuration de ODBC Microsoft Access (v6ase figura 6.13) en la que debe introducir
el nombre que va a dar a1 origen de datos y todos 10s demds pariimetros. En este caso bastard con pulsar el b o t h Seleccionar y facilitar el camino y nombre del archivo de Microsoft Access que ya habiamos empleado anteriormente como ejemplo.
& kce=
T&
400601900
400601900
400601900
400601900
1000200
1000005
2 01 22 01
400601900
400601900
rmm)
1-
Wansoft1
MmosoftI
Marsdt
Marsoftl
t&msoftI
IBPhoenu
No rnrXCi
Marsoft1
t&msoftl[d
Figura 6.12. El Administrador de origenes de datos ODBC cuenta con multiples paginas
WknpaadepSgna
rw-
15 T ~ A S I W W
rT*ibw
_____
www.detodoprogramacion.com
En caso que desee asociar una cuenta de usuario y clave con el DSN, evitando
que la aplicacion o el propio usuario tenga que facilitar esta informacion, pulse
el boton Avanzadas de la ventana Configuracion de ODBC Microsoft Access.
Para terminar, pulse el boton Aceptar del cuadro de dialog0 anterior. Volvera a
la pdgina DSN de sistema del Administrador de origenes de datos ODBC, en cuya
lista debe aparecer el DSN r e c i h creado.
c
Una vez que tenemos creado el DSN en el equipo donde va a ejecutarse la aplicacibn, utilizarlo desde &a, con el proveedor Odbc, es realmente sencillo. Tome
el ejemplo anterior en el que ustibamos este proveedor para acceder a una base de
datos InterBase, cambie la cadena de conexi6n facilitada a1 constructor dejdndola
como "DSN=Libros" y ejecute el programa. El resultado deberia ser el de la figura 6.14. Ha conectado con Microsoft Access mediante ODBC facilitando s610 el nombre de un DSN.
Observe que ahora la propiedad Database facilita el camino en el que se encuentra el archivo, asi como su nombre sin extensi6n.
-
--__
- -
Archivos UDL
Los DSN son u n recurso de ODBC para almacenar la informacidn de conexion,
una soluci6n exclusiva que no puede utilizarse si, posteriormente, en nuestro c6digo no vamos a emplear el proveedor O d b c . OLE DB cuenta con un mecanismo
similar, si bien en este caso la information siempre se almacena en un archivo con
extension udl.
Para efectuar una prueba, sencilla y rapida, dk 10s pasos que se indican ahora:
En la carpeta correspondiente a1 proyecto Visual Basic .NET en el que conectabamos, mediante el proveedor O l e D b , con Microsoft Excel, haga clic con
el b o t h secundario del rat6n sobre el contenido de la carpeta (en el panel
derecho del Explorador de Windows), seleccione la opci6n Nuevo>Documento
de texto y llame a1 archivo Conexion. u d l . Responda afirmativamente a la
pregunta de si desea cambiar la extension del archivo.
Haga doble clic sobre el archivo recikn creado, abriendo la ventana Propiedades de vinculo de datos.
0
Rowedom dc OLE DB
Micros& ISAM 1 1 OLE DB Provider
Mmmsoit OLE DB Praviderfor lndmng Sewice
I&msoft OLE DB Providerfor Internet Publishing
Microsoft OLE GB PiovideifoiOGBC Gwen
Micros& OLE DB PmviderforOMP Services
Micms& OLE DB Pmviderfor O d e
Microsoit OLE DB Piowderfor SOL S e w s
Mcrosoft OLE DB Simple Provider
MSDataShape
Omde PrnvidwforOLE DB
Pmveedor de bares de datos OLE para s e ~ c i o sde diredono d
VSEE Vemonmg Enlistment Manager Prmy Data Source
En la p6gina Conexih pulse el b o t h ... que hay asociado a la primera opc i h , facilitando el camino y nombre del documento Microsoft Excel usado
anteriormente como ejemplo.
www.detodoprogramacion.com
Vaya a la psigina Todas y haga doble clic sobre la propiedad Extended Properties, en la lista que aparece en el sire, central de la ventana.
La ventana Modificar valor de propiedad nos permite introducir el valor que
deseamos dar a la propiedad Extended Properties. En este caso, como
puede verse en la figura 6.16, escribimos la secuencia Excel 8 . 0 ;HDR=Yes
y pulsamos el b o t h Aceptar.
I/
Figura 6.16. Propiedades extendidas de la configuracion de conexion
0
Utilizar el archivo udl desde una aplicaci6n propia es tan f6cil como usar un
DSN. Abra el proyecto en el que, mediante el proveedor OleDb, conect6bamos con
una hoja de c6lculo Excel. Cambie entonces la cadena de conexih, asignada en este caso a la propiedad ConnectionString, dejhndola como "File Name=. . \
Conexion. udl".A1 ejecutar el programa se obtendria una conexi6n satisfactoria,
si bien en este caso la propiedad Database no nos indica el origen de datos a1 que
estamos conectados.
www.detodoprogramacion.com
Como ha podido ver en este capitulo, mediante las clases Connection de cada uno de 10s proveedores ADO.NET es posible conectar virtualmente con cualquier origen de datos, tanto RDBMS como no RDBMS. Por una parte tenemos dos
proveedores especificos, Sqlclient y Oracleclient, capaces de comunicarse
directamente con SQL Server y Oracle, respectivamente. Por otra, 10s proveedores
OleDb y Odbc abren las puertas a1 us0 de cualquier controlador OLE DB u ODBC
que pudiera existir, facilitando el acceso a Microsoft Excel, Microsoft Access o InterBase, pero tambie'n a dBase, Paradox, Sybase, DB2, MySQL y, en general, cualquier base de datos.
Ahora que ya conocemos la sintaxis general de las cadenas de conexih, asi como 10s miembros de la interfaz IDbConnection que permite abrir, cerrar y comprobar la conexion, estamos en disposicion de empezar a recuperar datos desde el
origen a1 que se haya conectado. Este serd el objetivo del pr6ximo capitulo.
www.detodoprogramacion.com
www.detodoprogramacion.com
La mayoria de las aplicaciones que tratan con datos, una vez que han conectado
con el origen solicitan directamente la informacih que precisan o ejecutan 10s comandos pertinentes. Estas aplicaciones, por regla general, ya conocen de antemano la estructura de la base de datos, ya que &ta, habitualmente, estaba disponible
cuando el equipo de desarrollo planific6 la aplicacih. Este escenario podriamos
denominarlo como normal. No obstante, las excepciones tambien existen en este
campo y es posible que a1 crear nuestra aplicaci6n desconozcamos 10s nombres de
las tablas o columnas. Es un caso que se da, sobre todo, cuando el programa no
esti construido especificamente para operar sobre un cierto origen de datos sin0
que, por el contrario, debe facilitar el acceso a cualquier estructura de informaci6n. Es el caso tipico a1 escribir alguna utilidad general para un RDBMS 0,como
en este capitulo, cuando quiere simplemente experimentarse para conocer c6mo
conseguir una determinada informacih.
El objetivo de este capitulo es describir el proceso a seguir para obtener informaci6n de esquema de una base de datos, utilizando para ello 10s servicios del
proveedor ADO.NET 0,si este carece de ellos, 10s especificos del origen con el que
vaya a tratarse.
cion de esquerna?
Salvo excepciones, como es el caso de las hojas de cilculo Excel, todos 10s origenes de datos almacenan, aparte de 10s datos propiamente dichos, informacih
www.detodoprogramacion.com
sobre la estructura de 6stos. Todos 10s RDBMS, las bases de datos locales e, incluso, 10s archivos XML utilizan esta informaci6n de esquema para saber cu6les son
las tablas existentes, con qu6 columnas cuentan, qu6 tip0 de dato corresponde a
cada una de ellas, etc.
Si conectamos con un origen de datos cuya estructura desconocemos, la recuperaci6n de la informaci6n de esquema, tambi6n conocida como meta-informacidn,
nos permitir6 adaptar diniimicamente el funcionamiento del programa para que
trate 10s datos apropiadamente.
Los proveedores ADO.NET no cuentan con servicios que faciliten la recuperaci6n de informaci6n de esquema, ya que su finalidad es ser lo m6s simples y eficientes posible, facilitando asi tambien el desarrollo de nuevos proveedores.
Para recuperar la informacih de esquema de la base de datos, por tanto, tendremos que recurrir a medios alternativos. Existen biisicamente dos: utilizar 10s
servicios del controlador OLE DB, si es que vamos a usar el proveedor ADO.NET
OleDb, o servirnos de las instrucciones que el propio origen de datos facilite para
obtener esa informacibn. En 10s puntos siguientes vamos a tratar ambos casos.
El proveedor OleDb de ADO..NET no accede directamente a un origen de datos, como si hacen SqlClient u Oracleclient, sin0 que utiliza a mod0 de intermediario un controlador OLE DB existente. Los controladores OLE DB, como
10s proveedores ADO.NET, se ajustan a un estiindar definido por Microsoft, contando todos ellos con m4todos que permiten recuperar informaci6n de esquema
del origen a1 que han conectado. Por eso el objeto OleDbConnection dispone de
un metodo, llamado GetOleDbSchemaTable ( ) , que hace us0 del metodo original del controlador OLE DB, limitiindose a devolver el resultado.
En caso de que no tuvi6semos una alternativa mejor con el proveedor original
del origen de datos a1 que vayamos a acceder, siempre existe la alternativa de usar
el proveedor OleDb para recuperar la information de esquema y, posteriormente,
emplear el proveedor nativo para el resto del trabajo. Conociendo el funcionamiento de dicho origen de datos, sin embargo, esto no seria preciso.
El m4todo OleDbConnection. GetOleDbSchemaTable ( ) necesita dos parametros y devuelve como resultado un objeto DataTable con la informaci6n solicitada. El primer0 de los pariimetros selecciona la informaci6n de esquema a
obtener: lista de las tablas, procedimientos almacenados, vistas, etc. Los valores
posibles son 10s definidos en la clase OleDbSchemaGuid como campos compartidos, algunos de 10s cuales se enumeran en la tabla 7.1.
Como segundo pariimetro, el m6todo GetOleDbSchemaTable ( ) necesita un
arreglo de objetos Ob j ect, conteniendo cada uno de ellos una restricci6n aplicable a una columna del resultado que se obtenga. Las restricciones posibles dependeriin del valor entregado como primer parimetro. Si este es OleDbSchemaGuid.
Tables, por poner un ejemplo, el arreglo a facilitar como segundo partimetro dewww.detodoprogramacion.com
bera constar de cuatro elementos: nombre del catalogo a consultar, nombre del esquema, nombre de la tabla y tip0 de la tabla. La mayoria de 10s valores pueden ser
nulos. Si no se indica un catalogo, por ejemplo, se retornan todas las tablas de todos 10s catalogos. Para obtener todas las claves primarias de una tabla, otro ejemplo, 10s parametros serian tres: el nombre del catalogo, el del esquema y el de la
tabla cuya clave primaria deseamos recuperar.
Tabla 7.1. Valores a usar como primer parametro del metodo
GetOleDbSchemaTableO
recu
Valor
lnformeci6n a
0leDbSchemaGuid.Tables
0leDbSchemaGuid.Columns
0leDbSchemaGuid.Table-Constraints
0leDbSchemaGuid.Procedures
OleDbSchemaGuid. Procedure-Parameters
0leDbSchemaGuid.Views
www.detodoprogramacion.com
vbTab)
&
Next
Si conocemos 10s datos que van a devolverse, en lugar de mostrarlos todos podemos obtener solo aquellos que m6s nos interesan. A1 recuperar una lista de tablas existentes en el origen, por ejemplo, recuperariamos el nombre de cada tabla
con Fila ( "TABLE -N A M E " ) , sin necesidad de recorrer todas las columnas.
Sub M i i e s t r i E s q u t m a (ByVal
Titiilr
As String,
Dim T b l R e s u l t a d o As D a t a r d b l e
Dim Fila As D a t a R i w , ColiJrnrla As D a t d r c l u m n
ConnOleDb. Operl 1
'
TblResultado = ConnO1eDb.LetOleDbSc h e m a T a b l c = (
OleDbSchemaGuid.Tablp5,
New O b J e c t O {Nothing, Nothing, Nothing, Nothlng})
~
www.detodoprogramacion.com
& vbTab)
Console.WriteLine (Fila("TABLE-NAME" ) . ToString)
Next
Console.WriteLine (vbCrLf & vbCrLf)
End Sub
Disponiendo de esta funcibn, lo irnico que tenemos que hacer es afiadir a1 m4todo Main ( ) las dos sentencias siguientes:
r,
L
MuestraEsquerna ("Ho]a de
"Provider=Microsoft. Jet.OLEDB. 4.0; " &
" Da t a
Source= \ PBddV 1 s u a 1B a s 1 cNE T \ Cap- 03\L 1b ro s . x 1s ;
"Fxtended Properties='Excel 8.0; HDR=Yes"')
t
"
&
Como se indicaba antes, ninguno de 10s proveedores ADO.NET cuenta con medios propios para recuperar la informacih de esquema del origen de datos si exceptuamos lo que acabamos de ver en el punto anterior. Para recuperar la lista de
tablas de una base de datos SQL Server u Oracle, utilizando sus respectivos proveedores, tendriamos que utilizar las sentencias Transact-SQL o PL / SQL, respectivamente, que procediesen.
Tendriamos que definir la cadena de conexi6n con la base de datos, ejecutar
una sentencia SQL y recoger el resultado que, como en el caso de G e t O l e D b S c h e m a T a b l e ( ) , seria un objeto DataTable. Como intermediario tendriamos que usar
un adaptador de datos, como si ejecutasemos cualquier sentencia SQL de recuperaci6n de informacih. Este es un tema del que nos ocuparemos mas adelante, concretamente en el noveno capitulo, per0 en el siguiente ejemplo usaremos sendos
adaptadores para poder recoger la lista de tablas que hay en las bases de datos
SQL Server y Oracle.
Ambos RDBMS, SQL Server y Oracle, cuentan con una serie de tablas especiales en las que almacenan la informacih de esquema de la base de datos. Estas tablas pueden ser consultadas, siempre que se cuente con 10s permisos adecuados,
como cualquier otra tabla, mediante una sentencia S E L E C T .
En el caso de SQL Server existe un esquema, llamado I N F O R M A T I O N SCHEMA,
en el que existen diversas tablas, como TABLES, COLUMNS, R O U T I N E S , etc. Podemos ejecutar la sentencia S E L E C T * FROM I N F O R M A T I O N SCHEMA. TABLES, por
ejemplo, para recuperar todas las tablas de la base de datosTAlgunas de las columnas de datos devueltas, relativas a las tablas, son TABLE CATALOG, TABLE NAME
y TABLE TYPE, que pueden ser usadas, en caso necesarioTpara filtrar el resatado.
Oracledispone de tablas similares, 1lamadasusER TABLES, U S E R VIEWS, U S E R
CATALOG, etc., mediante las cuales podemos recuperar diversa infGrmaci6n de la
base de datos. En el caso de U S E R TABLES, algunas de las columnas existentes son
TABLESPACE-NAME, TABLE-NAME, PCT -FREE y PCT -USED.
. . . . . . _
"
.r.:-
..
. . ,
-._ll__-_l_..____-_--.-
_ll.._._. ."I--
.-..___~-~.l______.~
Veamos c6mo podemos crear un pequedo programa que nos muestre por consola la lista de tablas existentes en las bases de datos SQL Server y Oracle que creamos en el tercer capitulo. A fin de tener un unico ejemplo, como en el caso de Excel
www.detodoprogramacion.com
( )
AdaptadorSql.Fill(TblResultado) '
MuestraEsquema
1
( ' I * * *
S Q L Server
TblResultado)
* * * ' I ,
i _
&
TblFesultado = New D a t a T a b l e O
Adaptadororacle. Fill (TblResultado) '
MuestraEsquema("*** Oracle
End Sub
* * * ' I ,
TblResultado)
www.detodoprogramacion.com
&
vbCrLf)
End Module
TABLELNNE
TABLESPACELNbME CLUSTERLNIIME
IOTLNeME
PCTLFREE
PCTLUSED
INILTRANS
MAXTRANS
IN1
1
1
YES
YES
YES
====-==ii=====E=======iii=====_I======ii=
ACCOUNT SYSTEM
BONUS
SYSTEM
DEPT
SYSTEM
EDITORIALES
EMP
SYSTEM
LIBROS SYSTEM
RECEIPT SYSTEM
SALGRADE
1.1
10
10
10
SYSTEM
10
10
10
SYSTEM
40
40
40
10
40
40
40
10
1
1
1
40
1
1
1
40
255
255
255
1
255
255
255
1
65536
65536
65536
255
65536
65536
65536
255
65536
65536
65536
65536
65536
65536
65536
65536
1
1
1
65536
1
1
1
65536
2147483645
50
2147483645
50
2147483645
50
1
2147483645
2147483645
50
2147483645
50
2147483645
50
1
2147483645
1
50
1
1
1
50
1
1
1
1
1
1
1
1
1
YES
YES
YES
dl
Figura 7.2. Lista de tablas SQL Server y Oracle mostradas en el Bloc de notas
www.detodoprogramacion.com
Aunque en 10s ejemplos previos nos hemos limitado a recuperar una lista de las
tablas existentes en el origen de datos, en el caso de Excel y Access no hay mas elementos disponibles puesto que no 10s creamos en su momento, en la practica podriamos utilizar el mismo procedimiento para, por ejemplo, conocer cu6les son las
vistas predefinidas, si hay procedimientos almacenados, etc. Tomando como base
el ejemplo previo, que conecta con SQL Server y Oracle, pruebe usted mismo con
10s valores alternatives mencionados antes: INFORMATION-SCHEMA.VIEWS,USERVIEWS, etc., y asi conocer cuiles son 10s datos devueltos.
Si conociesemos tan solo el nombre de cada tabla o vista, sin mas, tampoco podriamos hacer mucho. La siguiente necesidad sers conocer las columnas de cada
una de esas entidades: nombre, tipo, etc. Aunque podriamos seguir empleando
metodos especificos de cada proveedor u origen de datos para obtener esta informacibn, existe una alternativa m i s f6cil y, sobre todo, aplicable a cualquier origen
con el que se haya conectado.
La interfaz IDataReader, implementada por las clases DataReader de cada
proveedor, dispone de un metodo, llamado GetSchemaTable ( ) , que facilita un
DataTable con 10s datos de cada una de las columnas del conjunto de resultados
que va a leerse.
Este conjunto de resultados viene definido por un comando ejecutado previamente con el metodo ExecuteReader ( ) de IDbCommand,interfaz implementada
por todos 10s comandos.
Descrito paso a paso, el proceso para obtener las columnas de cualquier tabla o
vista seria el siguiente:
Creacion de un nuevo comando, OleDbCommand, SqlCommand, OracleCommand u OdbcCommand, con una sentencia del tip0 SELECT * FROM
Tabla, donde Tabla seria el nombre de una de las tablas previamente obtenidas en un DataTable. A1 crear el comando este se asocia directamente
con la conexi6n ya abierta con el origen de datos.
0
Llamada a1 metodo ExecuteReader ( ) del comando, facilitando como parametro CommandBehavior SchemaOnly. Asi solicitamos so10 la recuperation de informaci6n de esquema, sin datos. El resultado devuelto por este
metodo es una referencia IDataReader que tendremos que almacenar en
una variable, ya sea de ese tip0 o del DataReader especifico del proveedor
que este utilizindose.
que encontramos, por ejemplo, el nombre de cada columna, su tip0 original y tip0
.NET, precisi6n numkrica, si es o no unico, si es s610 de lectura, etc.
Tomando como punto de partida el primer ejemplo desarrollado en este capitulo, en el que se enumeraban las tablas del documento Excel y la base de datos
Access, vamos a introducir algunos cambios para obtener, asimismo, el nombre y
tip0 de todas las columnas de cada tabla.
El mktodoMain ( ) , desde el que invociibamos dos veces aMuestraEsquema ( ) ,
permanecer5 sin cambios. El metodo MuestraEsquema ( ) , a1 que pertenece el c6digo siguiente, si ha sufrido algunos retoques.
Sub MuestraEsquema(ByVa1 Titulo As String,
ByVal C ad e ri d C o n ex 1ori As String )
TblResultado = ConnOleDb.GetOleDbSchernaTable( __
OleDbSchemaGuid.Tables, New Object( ) {Nothing, Nothing, Nothing, "TABLE"} )
. ToSt ri ng )
www.detodoprogramacion.com
Console.WriteLine (vbCrLf
&
vbCrLf)
'
ConnOleDh.Close ( 1
End Sub
If NombreTaDla.EndsWith!"$") Then
NombreTabla
End If
"SELECT * FROM
"["
"
&
&
NombreTabla
NombreTabla,
Dim Lector A s I D a t a R e a d e r
&
"I"
Conexlor,)
( C o m m a n j B i h a b l ir. S c h e m a O n l y )
Dim T b l h ~ ~ d l t a dAs
r DataTable
Ler-tnr. ( 7 e t S c h e r n a T a b l e !)
,
Dim F i l a As D a t a h o w
C o n s v l e . W r i t e L i r i e (vbCrLf
b
&
If
vbTab L
"Tipo")
www.detodoprogramacion.com
"
&
vbTab)
Next
Lector.Close i 1
Console.WriteLine(vbCrLf
End Sub
&
vbCrLf)
El primer condicional comprueba si el nombre de la tabla finaliza con el simbolo $, habitual a1 operar sobre documentos Excel, en cuyo caso lo delimitamos entre
corchetes para evitar problemas en la ejecuci6n de la consulta. Act0 seguido implementamos 10s pasos antes descritos: creamos el comando con la consulta, obtenemos el IDataReader y llamamos a su metodo GetSchemaTable ( ) . A partir
de ahi el c6digo es similar a1 del metodo MuestraEsquema ( 1, recorriendose todas las filas para mostrar el nombre y tipo de cada columna.
A1 ejecutar el programa deberia obtener un resultado similar a1 de la figura 7.3.
En ella pueden verse todas las columnas de las dos tablas que habiamos definido
en Excel y Access. Observe 10s tipos asociados a las columnas de Excel. A1 crear este documento no se indic6 tip0 de dato de cada columna, por lo que el proveedor
lo deduce a partir de la informacion que contienen las celdillas. En cualquier caso,
con esta informacion podriamos crear una interfaz que, por ejemplo, permitiese
conectar con cualquier origen de datos y enumerase sus tablas, vistas, procedimientos, etc., accediendo a la lista de columna cuando el usuario seleccionase una tabla,
vista o procedimiento en concreto.
Nota
Puede utilizar el mismo camino para enumerar las columnas de las tablas SQL
Server, Oracle o bien InterBase. Una vez ejecutado el comando y obtenido el
DataReader,todo el proceso es identico.
Los proveedores de datos ADO.NET est6n diseiiados con una arquitectura que
es relativamente simple, facilitando su desarrollo y, sobre todo, potenciando el
rendimiento sobre 10s dem& aspectos. Esta es la raz6n de que en ellos no existan
metodos para acceder a la informaci6n de esquema de 10s origenes de datos, siendo precis0 utilizar medios mas especificos y, por lo tanto, dependientes de cada
origen en particular.
En este capitulo ha conocido 10s procedimientos para obtener informaci6n de
esquema mediante controladores OLE DB y consultando tablas especificas de SQL
www.detodoprogramacion.com
Server y Oracle. Los dem6s RDBMS cuentan con mecanismos similares, no tenemos m6s que consultar la documentaci6n de referencia y localizar las tablas, vistas
o procedimientos almacenados que entregan esa informaci6n de esquema.
Una vez se conoce el nombre del objeto a consultar, la recuperaci6n de informaci6n sobre sus columnas resulta mucho m6s f6cil gracias a1 metodo G e t S c h e m a T a b l e ( ) de la interfaz I D a t a R e a d e r . En el capitulo siguiente conoceremos con
m6s detalle esta interfaz y las implementaciones que efectuan 10s diversos proveedores.
www.detodoprogramacion.com
www.detodoprogramacion.com
nerali
re 10s comandos
8. Recuperacidn de datos
se apunt6 la existencia de la interfaz IDbCommand, en la cual se definen 10s miembros con que deberia contar la clase de ejecucidn de comandos de cada proveedor.
En la figura 8.1 se puede ver la relaci6n existente entre esta interfaz y las clases
OdbcCommand, OleDbCommand, OracleCommand y SqlCommand, todas ellas derivadas de SystemComponentModel . Component.
Component
OdbcCommand
OleDbCommand
IDbCommand
Figura 8.1. Las clases Command de cada proveedor implementan 10s miembros
de la interfaz IDbCommand
-~
C o n r ~ O l e D b . C r e a t e C o m r n a n d( )
En el capitulo previo, con el fin de crear un lector de datos, vimos c6mo cre6bamos un comando directamente con el constructor de una de las clases Command,
concretamente con 01eDbCommand. Dicho constructor acepta un 01e Db Conne cti on como segundo partimetro, asociando el comando con la conexi6n. L6gicamente, 6sta deber6 haberse creado previamente.
Dim Comando As New OleDbCommand(Texto, ConnOleDb)
www.detodoprogramacion.com
Otra posibilidad es que creemos el comando sin facilitar ese segundo parfimetro,
s610 con el texto del comando a ejecutar:
En este caso, antes de llamar a ninguno de 10s metodos de ejecucibn, habria que
asignar la conexion a la propiedad Connection. Tambien podemos leer esta
propiedad, a1 obtener un comando, para asi poder acceder a 10s parfimetros de la
conexi6n. Dicha propiedad es de tipo IDbConnection en la interfaz IDbCommand,
per0 en la implementaci6n de cada proveedor el tip0 es el exclusivo de ese proveedor por lo que, en la prfictica, no podriamos asignar a la propiedad Connection
de un comando una conexi6n de tip0 distinto.
an
Una vez tenemos el comando preparado, podemos ejecutarlo recurriendo a uno
de 10s tres m6todos con que cuenta IDbCommand o bien a algun m6todo especifico
del proveedor que estemos utilizando.
www.detodoprogramacion.com
8. Recuperacidn de datos
Closeconnection
Default
KeyInf o
SingleResult
SingleRow
Schemaonly
El valor de retorno de ExecuteReader ( ) es un DataReader, el de ExecuteNonQuery ( ) un Integer y el de Executescalar ( ) un Object con el dato
obtenido que podemos convertir a1 tip0 que interese.
www.detodoprogramacion.com
I
I
-1
-hi
\
--
-(
IDa t a R e c o r d
IDa t a R e a d e r
SqlDataReader
Figura 8.2. Las clases D a t a R e a d e r de cada proveedor implementan las interfaces
IDataRecorde IDataReader
www.detodoprogramacion.com
8. Recuperacidn de datos
~ u e s t r a T a b l a("Editoriales")
MuestraTabla("Llbr0s")
End Sub
Sub MuestraTablaiByVal NombreTabla As String)
D i m Comando As OleDbCornrnarld
r )rnand
) .
,rnmandType
xt
=
=
Conexion.C r e a t eComrnand (
LornmandType. Tab1 e D i r e c t
N rnbreTabla
D i m Ltct ~ ) As
r 0let)bDat~aReader = Cornando. ExecuteReader
Dim I n d i i
As Byte
Fo
Next
Con5ole.WriteLine(vbCrLf
&
New String("=", 6 0 ) )
= 0 To Lector.FieldCount - 1
Console.Write(Lector.GetValue(1ndice)
Next
For Indice
www.detodoprogramacion.com
&
vbTab)
( )
Console.WriteLine(vbCrLf
End Sub
&
vbCrLf)
End Module
www.detodoprogramacion.com
8. Recuperacidn de datos
Sub Main( )
-. -
1.2
if.
~'
"
&
co
Cornando.ComrnandText = "SELECT * FROM Editoriales;" h
"SELECT * FROM L i b r o s ; SELECT COUNT ( * ) FROM LIBROS"
I
J - , , ( a n
n _
Comando.ExecuteReader()
Dim Indice As B y t e
www.detodoprogramacion.com
Fo
nt
&
vbTab)
< - ] ~1
1 7
'
( )
'
End Module
Observe que, salvo la conexi6n y ejecuci6n del comando, la mayor parte del c6digo se encuentra en el interior del bucle Do/Loop While L e c t o r . NextResult ( ) .
Asi procesaremos 10s tres conjuntos de datos obtenidos. Dentro de &te tenemos
otro bucle, el equivalente a1 del ejemplo anterior, para recorrer todas las filas de cada conjunto. El resultado, como se aprecia en la figura 8.4, es prdcticamente i d h tico. A diferencia del programa anterior, sin embargo, tan s610 hemos conectado
con el origen una vez y tan s610 hemos ejecutado un comando.
No todos 10s proveedores ADO.NET contemplan la posibilidad de ejecutar lotes de sentencias SQL,como se ha hecho en este ejemplo con Sqlclient.
S
~
8. Recuperacidn de datos
Suponga que desea obtener el titulo de cada uno de 10s libros que hay en la tabla L i b r o s , junto con el nombre de su editorial y el precio. Estos datos podria utilizarlos para generar un informe impreso, un documento HTML o cualquier otro
tip0 de resultado.
En el c6digo siguiente nos limitamos a mostrarlos por consola, per0 el proceso
seria btisicamente el mismo.
Imports System. Data.OleDb
Module Module1
Sub Main( )
2
Dim Conexion As New OleDbConnection ( "Provider=Microsoft. Jet.OLEDB. 4.0; " & "Data Source=\PBddVisualBasicNET\Cap~03\Libros.~ls;"
"Extended Properties='Excel 8.0; HDR=Yes'")
0 '
Cone
t i
I
I
Conexion. CreateCommand
&
( )
..
,~
A?
\I
Comando.ExecuteReader0
www.detodoprogramacion.com
'I
&
vbCrLf
&
Wh
C o n s o 1 e . W r i t e i L e c t o r . G e t St r 1 nq ( 0 . P a d R i g h t (50) L vbTab)
C o n s o 1 e .W r i t e i L e c t o r . Get S t r i rlg ( 1 . P a d R i g h t ( 2 5 ) L vbTab)
C o n so 1 e .W r i t eL 1 ne f " { 0 ,5 1 ' I , Lect o .GetDouble(2)
End While
L e c t r L .Close ( )
'
End Sub
End Module
Ya que conocemos el tip0 de las columnas seleccionadas en la consulta, podemos utilizar directamente 10s metodos GetXXX ( ) del D a t a R e a d e r , por ejemplo,
G e t s t r i n g ( ) para recuperar el titulo y nombre de la editorial y GetDouble ( )
para leer el precio. Observe c6mo en la consulta se han facilitado 10s nombres de
las tablas entre corchetes, puesto que el car6cter $ no puede introducirse directamente en la consulta.
En la figura 8.5 puede ver el resultado de la ejecuci6n de este ejemplo. L6gicamente, en lugar de utilizar el documento Excel como origen puede usar cualquier
otro. Tan s610 tiene que utilizar la conexi6n adecuada, segun se explic6 en el sexto
capitulo, y eliminar de la sentencia de consulta 10s corchetes y el simbolo $ a1 final
del nombre de cada tabla.
www.detodoprogramacion.com
8. Recuperacidn de datos
Al acceder a Excel, el proveedor deduce el tip0 de 10s datos a partir del contenido de las celdillas, como se indico anteriormente. Por eso el precio se trata
como un Double. Al conectar con un origen distinto podria tener que cambiar
G e t D o u b l e ( ) pOr G e t D e c i m a l ( ) .
_-.-____
_x
."_.._l""
- ..-.I
_.."
.......
.-.^__I_..-_x_-^_-.-~ _ _ ) - _____
.__
Las sentencias SQL usadas en 10s ejemplos anteriores son constantes, lo que significa que siempre se ejecutan igual y obtienen 10s mismos resultados. Una sentencia, no obstante, puede contener pardmetros cuyo valor se desconoce en el momento
de expresar la propia consulta, lo que se conoce normalmente como parimetros
sustituibles. Observe, por ejemplo, la siguiente consulta:
Nota
La sintaxis para indicar la existencia de un parametro difiere de un proveedor a
otro. En la sentencia anterior se ha precedido C o d E d i t o r i a l con dos puntos,
sintaxis adecuada p a r a o r a c l e c l i e n t . El p r o v e e d o r s q l c l i e n t , pore1 contrario, usa el caracter @ para denotar la existencia de un parametro sustituible.
Los objetos que implementan IDbCommand disponen de la propiedad P a r a comentada brevemente antes, que mantiene la lista de parimetros necesarios para la ejecuci6n del comando. En principio esa lista est6 vacia, pudiendo
afiadirse 10s parimetros que se necesiten mediante el metodo Add ( ) . Este necesita
como argument0 el objeto que representa a1 parimetro, un objeto que seri dependiente del proveedor, por ejemplo S q l p a r a m e t e r u O r a c l e p a r a m e t e r .
Una alternativa es llamar a1 metodo C r e a t e p a r a m e t e r ( ) del objeto Command
que estemos usando. Este devuelve un objeto del tip0 adecuado, no teniendo mis
que asignar, usando sus propiedades, el nombre y valor del partimetro, datos que
usando el metodo indicando antes se entregarian a1 constructor de la clase P a r a m e t e r adecuada.
meters,
www.detodoprogramacion.com
Suponga que quiere crear una consulta de libros pertenecientes a una cierta
editorial, permitiendo a1 usuario que sea 151 quien seleccione dicha editorial. Asumiendo que utilizaremos la base de datos creada anteriormente en Oracle, el c6digo necesario seria el siguiente:
Imports Systern.Data.OracleC1ient
Module Module1
Sub Main()
I
L-Fj,-jy,la
.js ,:c;I,,Jzld,-) a I;, j:>,s-J .f-. ,>'a
tjs s p l s;.r\--;.r
Dim Conexion As New OracleConnection( " Data Source= L ib ros ; Us e r I D= s cot t ; Pass wo rd= t ig e r " )
Conexion. Open (
'
1 ) -
"
&
D i m NurnEditorial As Integer
:;:~lj:i tc:;:-;s +i
~
::jilL:,3
,G+=
.,
? , : i ~ r ~ ? r i ~~i: >
l - J I .!.t~i,-j~rjk
i n t~5L-
Cornando.Parameters.Add(New Oracleparameter(
"CodEditorial", NumEditorial) )
'
Z
,
2
Dim Lector As OracleDataReader
(
77
Cornando.ExecuteReader0
"
i'
+ ,
->
c1
I-
/ >
&
Whlle Lector.Read0
Console.WriteLine (Lector("1SBN")
End While
&
vbTab
&
Lector("Tltu1o") )
End Module
8. Recuperacio'n de datos
el c6digo necesario para mostrar el c6digo y nombre de cada una de ellas, facilitando asi la selecci6n.
e un solo valor
Hasta ahora hemos usado reiteradamente el metodo ExecuteReader ( ) para
acceder a uno o varios conjuntos de datos. En ocasiones, el resultado de una sentencia de consulta ser6 dnico, por ejemplo una suma, contador o algdn otro cdculo. En casos asi, aunque podriamos utilizar ExecuteReader ( 1, resulta m6s fdcil
y eficiente utilizar el m6todo ExecuteScalar ( ) . h e devuelve directamente el
resultado, sin necesidad de recorrer filas ni columnas.
Partiendo del ejemplo del punto anterior, modifique la consulta dej6ndola asi:
Comando.CornrnandText = "SELECT COUNT(*) FROM Libros
"WHERE Editorial=:CodEditorial"
"
A continuaci6n se solicita el c6digo de editorial a1 usuario e introduce como par6metro en el comando, que ahora ejecutaremos asi:
Dim Resultado As Integer = Cornando.ExecuteScalar0
Console.WriteLine("Esa editorial tiene { O l titulos", Resultado)
Hemos eliminado la declaraci6n del DataReader y la llamada a1 metodo Close ( ) . Si ejecuta ahora el programa, e introduce el c6digo de una editorial, ver6
aparecer el ncmero de titulos que corresponden a ese c6digo.
atos
Aunque el titulo de este capitulo hace referencia expresa a la recuperaci6n de
datos, y a este tema se dedica la mayor parte del mismo, hay que apuntar que un
www.detodoprogramacion.com
comando preparado en un objeto Command puede contener cualquier tip0 de sentencia SQL, incluidas las que aiiaden filas, modifican las existentes o las eliminan.
Este tip0 de sentencias no devuelve conjuntos de resultados, sino un entero que
indica el numero de filas que se han visto afectadas por la operaci6n realizada. Por
ello se ejecutan con el metodo ExecuteNonQuery ( ) en vez de ExecuteReader ( ) .
Conociendo la sintaxis SQL del origen con el que vayamos a conectar, efectuar
cualquier operaci6n de manipulaci6n de datos no implica mayor complejidad. El
siguiente ejemplo aiiade una fila de datos a la hoja Libros del documento Excel.
La operaci6n se efectuaria de manera anfiloga en cualquier otro origen y, de forma
similar, podrian modificarse o eliminarse filas.
Imports System.Data.OleDb
Module Module1
Sub Main ( 1
rA
Conexion.CreateCommand
&
( )
Cone
I
"
'.'
, :
i,i
Conexion.Close i
End Sub
'
'
Comando.ExecuteNonQuery()
End Module
Para ver el resultado puede ejecutar alguno de 10s ejemplos previos, recuperando el contenido del documento y mostrhdolo por la consola, o bien abrir directamente el documento en Microsoft Excel para observar el cambio.
Otras operaciones
Dado que con un comando podemos ejecutar cualquier sentencia SQL sobre el
origen de datos, podemos virtualmente extraer y manipular todo su contenido.
www.detodoprogramacion.com
8. Recuperacidn de datos
*-
'
1 + 3
D i m Comando As SqlCommand
Conexion. Open (
'
<
"
&
_ =
c cx
Conexion.CreateCornrnand()
I Ti
Comando. CornrnandText
D i m Indice As Byte
www.detodoprogramacion.com
&
&
"{1,-50]"
&
Lector.Close0 '
Conexion.Close( )
End Sub
End Module
Como puede ver, la sentencia SQL asignada a CommandText bien podria ser la
de consulta a una tabla llamada LibrosEditorial. Sabemos, sin embargo, que
tal tabla no existe, puesto que 10s datos de las editoriales y 10s libros se encuentran
separados. LibrosEditorial es una vista que, a1 ejecutarse, devuelve la lista de
datos que puede verse en la figura 8.7.
/'I
Ejecutar un procedimiento almacenado es, si cabe, m6s f6cil que abrir una vista. B6sicamente tenemos que dar tres pasos, asumiendo que tenemos la conexi6n
ya preparada:
www.detodoprogramacion.com
8. Recuperacidn d e datos
Hecho esto, ejecutariamos el comando con ExecuteReader ( ) , ExecuteScalar ( ) o ExecuteNonQuery ( ) , segun devuelva un conjunto de datos, un solo valor o nada. En este ultimo caso, como ya sabe, obtendria el numero de filas afectadas
por la operation. Hemos usado previamente 10s tres m&odos, por lo que no necesitamos saber nada nuevo para ejecutar uno de 10s procedimientos almacenados
que tenemos en nuestra base de datos.
Tomando como base el ejemplo previo, mantenemos la primera parte, definiendo la conexion, creando el comando y abriendo la conexion, y modificamos a partir de la asignacion de la sentencia SQL, introduciendo el codigo siguiente:
Dim L e c t o r As S q l D a t a R e d d e r
Comando. ExecuteReader ( )
Dim I n d i c e As Byte
&
While Lector.Read ( 1
vbTab
&
www.detodoprogramacion.com
www.detodoprogramacion.com
A diferencia de la mayoria de elementos que hemos conocido en 10s tres capitu10s previos, que se caracterizan por implementar alguna interfaz comun per0 con
www.detodoprogramacion.com
9. Conjuntos de datos
implementaciones especificas para cada proveedor, 10s conjuntos de datos tan s6lo cuentan con una clase: D a t a S e t . En esta clase pueden existir, segun se apuntaba en el quinto capitulo, multiples tablas, con sus filas y columnas, restricciones y
relaciones.
Un conjunto de datos puede obtenerse a partir de un origen de datos, mediante
un adaptador, o bien definirse mediante c6digo. Independientemente de esto, el
contenido del conjunto de datos puede almacenarse y recuperarse localmente, existiendo tambien, como es 16gic0, la posibilidad de resolver 10s cambios con el origen de datos del que se extrajo la informaci6n.
Si bien en principio no existen clases derivadas de D a t a S e t, nada nos impide
crearlas a fin de que se ajusten a la estructura concreta de 10s conjuntos de datos
sobre 10s que vamos a operar. Estas clases, derivadas de D a t a S e t , serian conjuntos de datos con comprobaci6n de tipos que facilitarian el acceso a 10s datos comprobando, a1 tiempo, que Gstos Sean de 10s tipos apropiados. Aunque podriamos
crear estas clases manualmente, Visual Studio .NET dispone de asistentes que se
ocupan de hacerlo. Los conocerb en un capitulo posterior, a1 tratar las herramientas del entorno para el trabajo con datos.
En este capitulo utilizaremos siempre conjuntos de datos genericos, es decir,
objetos de la clase D a t a S e t .
Tablas y relaciones
Las dos propiedades fundamentales de un D a t a S e t son T a b l e s y R e l a t i o n s .
Cada una de ellas mantiene una referencia a una colecci6n de objetos, en el primer
caso de la clase D a t a T a b l e y en el segundo de D a t a R e l a t i o n . La primera es
importante ya que nos permite recuperar y modificar la informaci6n almacenada
en el conjunto de datos, mientras que la segunda define la relaci6n entre tablas en
caso de que el conjunto est4 compuesto por varias.
Cuando se llena un D a t a S e t a partir de un origen de datos, mediante un adaptador, las colecciones de tablas y relaciones se definen autombticamente. Nada nos
impide, sin embargo, afiadir nuevos elementos a las colecciones, es decir, crear
nuevas tablas y relaciones en el interior del D a t a S e t . Es algo que veremos en la
prbctica posteriormente.
Cada tabla se compone, como ya sabe, de filas y columnas, representadas por
las colecciones Rows y Columns, respectivamente, de la clase D a t a T a b l e . Mediante la colecci6n Rows podemos acceder a 10s datos que contienen las filas,
mientras que con la coleccion Columns tenemos a nuestro alcance la informaci6n
de esquema de cada columna: nombre, tipo, etc. La tabla tambien puede contar
con una colecci6n de objetos C o n s t r a i n t especificando las restricciones aplicables a 10s datos.
Mediante objetos D a t a R e l a t i o n , alojados en la propiedad R e l a t i o n s , se
establecen 10s enlaces entre las tablas que forman parte del D a t a S e t . Estas, a1
igual que el contenido del resto del D a t a S e t , pueden recuperarse mediante un
adaptador de datos o bien definirse con c6digo.
www.detodoprogramacion.com
Seleccih de datos
Mediante la propiedad Rows de cualquier D a t a T a b l e es posible acceder a la
totalidad de las filas que componen la tabla en ese momento. Utilizando el mgtodo
S e l e c t ( ) de la clase D a t a T a b l e , no obstante, es posible establecer filtros de selecci6n para recuperar un arreglo compuesto tan s610 por aquellas filas que 10s
cumplen.
Observe que el metodo S e l e c t ( ) no afecta a la propiedad Rows, es decir, no
provoca que en la colecci6n aparezcan o desaparezcan filas, sin0 que es el mismo
metodo el que devuelve un arreglo de objetos DataRow con el resultado.
A1 efectuar busquedas con el m6todo S e l e c t ( ) ,por defecto, no se distingue entre mayusculas y minusculas. Este comportamiento est6 controlado por la propiedad C a s e s e n s i t i v e del D a t a S e t que, por defecto, tiene el valor F a l s e . Puede
asignarle T r u e si necesita que a1 establecer un filtro se distinga entre mayusculas y
minusculas.
Aunque, como se veri mis adelante en este capitulo, es posible almacenar y recuperar conjuntos de datos usando archivos locales, al trabajar con objetos D a t a S e t
asociados a origenes de datos, que es el caso m6s habitual, resultan imprescindibles 10s adaptadores de datos, introducidos tambien en el quinto capitulo. Un
adaptador de datos actua como intermediario entre el origen de datos, con dependencias de cada product0 particular, y el D a t a S e t , que tiene una estructura totalmente independiente.
www.detodoprogramacion.com
9. Conjuntos de datos
La relaci6n entre 10s distintos elementos relacionados con adaptadores de datos, interfaces, clases gen6ricas y clases de proveedores, es la que puede apreciarse
en la figura 9.1. Como puede ver, la clase DataAdapter implementa la interfaz
IDa t aAdap t e r, sirviendo a su vez como base para la clase generica DbAdap t e r.
Esta sirve como base de OdbcAdapter, OleDbAdapter, OracleDataAdapter y
SqlDa t aAdap t e r, adaptadores de datos de cada proveedor que, adem&, tambien tienen en comun la implementacih de la interfaz IDbDataAdapter.
-elo
IDbDa t a Adap t e r
Ningiin pariimetro. Se obtiene un adaptador que no est6 asociado a una conexion ni tiene un comando de recuperaci6n de datos. Seria precis0 asignar
posteriormente un objeto Command a la propiedad SelectCommand, facilitando un comando de selecci6n ya asociado a una conexi6n.
U n objeto Command. El adaptador se crea ya asociado a1 comando que se entrega como parsmetro.
Una cadena de caracteres y un objeto Connection. El propio adaptador se
encarga de utilizar la cadena de caracteres para crear el comando de selecci6n, asociindolo con la conexi6n que se entrega como segundo par6metro.
Dos cadenas de caracteres. La primera seria el comando de selection y la
segunda la cadena de conexi6n a1 origen de datos. Con esto el adaptador se
encargaria de crear 10s objetos Connection y Command del proveedor apropiado, estableciendo todas sus propiedades.
A diferencia de lo que ocurria con 10s lectores de datos, un adaptador no requiere que la conexi6n con el origen de datos est6 abierta de antemano. El mismo
se ocupa de abrirla y cerrarla cuando es necesario.
Una vez que tenemos el adaptador preparado, con su comando de selecci6n definido, para ejecutarlo y obtener 10s datos en el DataSet no tenemos m6s que invocar a1 metodo Fill ( ) . Este puede tomar distintas listas de par6metros, aunque
la sintaxis m6s habitual es la siguiente:
AdaF)tadorDatos.F i l l ( C o n j u n t o O a t o s 1
ConjuntoDatos seria el DataSet destinatario de la informacih, en cuyo interior se crearia, con el resultado de la sentencia de seleccibn, un DataTable llamado Table.
Si deseamos que el objeto DataTable tenga otro nombre, no tenemos m6s que
facilitarlo como segundo par6metro al mismo metodo Fill ( ) .
El comportamiento del metodo Fill ( ) viene determinado, en parte, por el valor que tengan las propiedades MissingMappingAction y MissingSchemaAction del adaptador. La primera determina qu6 ocurre cuando se obtienen del
origen de datos tablas o columnas que no existen aun en el DataSet.Los posibles
valores son 10s enumerados en la tabla 9.1.
Mediante la segunda se especifica qu6 hacer con la nueva informaci6n de esquema que pudiera derivarse del origen, pudiendo tomar uno de 10s cuatro valores indicados en la tabla 9.2.
www.detodoprogramacion.com
9. Conjuntos de datos
Valor
Comentario
MissingMappingAction.Ignore
MissingMappingAction.Error
MissingMappingAction. Passthrough
Valor
Comentario
MissingSchemaAction.Ignore
MissingSchemaAction.Error
MissingSchemaAction.Add
MissingSchemaAction.AddWithKey
Si se llama al metodo Fill ( ) facilitando un DataSet vacio, alg0 muy habitual, es imprescindible que el adaptador aiiada todos los datos del origen y
la informacion de esquema, de ahi que 10s valores por defecto de las dos propiedades Sean esos y no otros. Podria ocurrir, sin embargo, que tuviesemos un
DataSet con una cierta estructura ya definida, caso en el cual podria interesarnos recuperar informacion en 10s DataTable ya existentes, sin aiiadir nada. En un caso asi asignariamos a ambas propiedades 10s valores Ignore o
~ r r o rseglin
,
deseemos simplemente ignorar el hecho u obtener una excepcion para conocerlo.
www.detodoprogramacion.com
Si ademas de la informacion de esquema de las columnas, que es lo que se recupera por defecto, deseamos tambikn que se obtenga la relativa a las columnas clave, antes de llamar a1 metodo Fill ( ) tendriamos que asignar el valor AddWi thKey
a la propiedad MissingSchemaAction. Debe tener en cuenta, sin embargo, que
a1 recuperar datos teniendo esta informacion se sustituiran automhticamente aquellas filas en las que el valor de la columna clave coincida con las recuperadas del
origen.
OdbcCommandBuilder
OleDbCommandBuilder
OracleCommandBuilder
SqlCommandBuilder
www.detodoprogramacion.com
9. Conjuntos de datos
Puede ver c6mo funciona un objeto CommandBuilder con un ejemplo tan simple como el siguiente, en el cual se crea un SqlCommandBuilder a partir de un
adaptador de datos ya existente. Una vez creado, podemos utilizar 10s m6todos
antes citados para acceder a 10s comandos y obtener las sentencias SQL. El resultado de la ejecuci6n seria el de la figura 9.3. Cambie de proveedor y ver6 c6mo las
sentencias se ajustan, en consecuencia, a la sintaxis del nuevo origen de datos.
I m p o r t s System. Data. S q l C l i e n t
Module Module1
Sub Main( )
Dim Adaptador As New SylDataAdapteri
"SELECT * FROM Editoriales", "Data Source=inspiron; Initial Catalog=Libros;
"User ID=sa; Password=")
~
"
&
End Sub
End Module
www.detodoprogramacion.com
En la figura 9.4 se ha representado de forma esquemitica, y simplificada, el modelo de objetos empleado para acceder a un origen de datos, llenarlo con informaci6n y despues actualizarla. Observe que el Data S e t no forma parte del proveedor
de datos, mientras que el resto de elementos si. Establecidos 10s parimetros de la
conexih, creariamos un DataAdapter y un CommandBuilder asociindolo a1
primero. A continuacih llamariamos a1 metodo Fill ( ) para obtener 10s datos,
con 10s que trabajariamos internamente o mediante una interfaz de usuario. A1 Ilamar a1 metodo Update ( ) , el DataAdapter haria us0 del CommandBuilder para enviar a1 origen las sentencias necesarias.
DataAdapter
Connection
InsertCommand
Updatecommand
Debe tener en cuenta que el metodo Update ( ) del adaptador se sirve del estad0 de cada DataRow de la tabla para determinar si necesita 0 no ser actualizada. No debe llamar al metodo Acceptchanges ( ) del DataSet antes de
invocar a Update ( ) , ya que, de hacerlo, todos 10s RowState volverian a su
estado por defect0 y el adaptador no encontraria nada que actualizar. Tras Ilamar a Update ( ) , a fin de mantener sincronizado el DataSet, puede llamar
a Acceptchanges 0 bien volver a invocar al metodo Fill ( ) a fin de ver no
solo 10s cambios propios sin0 tambien 10s de terceros.
9. Conjuntos de datos
Recuperacion de datos
Utilizando el proveedor S q l c l i e n t , para acceder a SQL Server, vamos a preparar un adaptador que nos devuelva en un DataSet las tablas E d i t o r i a l e s y
L i b r o s que hay en la base de datos. Recuperaremos las tablas por separado, con
dos sentencias independientes, obteniendo asi varios conjuntos de datos segtin se
vio a1 tratar 10s DataReader. En este caso, sin embargo, no tendremos que pasar
explicitamente de un conjunto a otro y leer las filas de manera individual, sin0 que
obtendremos toda la informaci6n de una vez.
Creado el adaptador de datos y el propio DataSet, nos limitamos a llamar a1
metodo F i l l para ejecutar 10s comandos y recuperar la informaci6n de esquema y
datos propiamente dichos. El resto del programa, como puede verse a continuaci6n'
es una sucesion de bucles con 10s que recorremos todas las columnas de cada fila
de cada tabla que contenga el Da t aS e t .
Imports System.Data.SqlClient
Module Module1
Sub Main( )
x-
Dim Adaptador As New SylDataAdapter( "SELECT * FROM Editoriales; SELECT * FROM Libros",
"Data Source=inspiron; Initial Catalog=Libros; " &
"Uscr l D = s a ;
Fasswoid-")
Adaptador.Fi11 (Datos)
&
Tabla. Tab l e N a m e
&
www.detodoprogramacion.com
"
'")
La llamada a1 m4todo F i l l ( ) provoca el envio del comando a1 origen de datos, en este caso SQL Server, que procesa las dos sentencias SQL facilitadas de manera independiente, devolviendo dos conjuntos de resultados. fistos son recogidos
por el DataAdapter, que se encarga de crear un DataTable por cada conjunto
de datos recibido.
Puesto que no hemos especificado de manera explicita nombre alguno para las
tablas, el propio adaptador les darii un nombre por defecto. A continuacih, dentro de cada DataTable, se definiriin 10s Datacolumn que se precisen, utilizando
para ello la informacih de esquema facilitada por SQL Server. De esta forma se
estableceriin, entre otros datos, el nombre y tip0 de cada columna. Por Liltimo, se
aiiadir6n a cada DataTable tantos DataRow como filas de datos compongan cada
conjunto.
A1 ejecutar el programa deberia obtener un resultado similar a1 de la figura 9.5.
Observe 10s nombres asignados a las tablas, Table y Tablel.
www.detodoprogramacion.com
9. Conjuntos de datos
"
&
Di
Observe que en este caso hemos facilitado como segundo parametro del metodo Fill ( ) el nombre que deseamos dar a 10s DataTable. Otra opcidn seria ariadir un elemento a la colecci6n TableMappings de cada adaptador, indicando el
nombre de la tabla origen, que suele ser Table si en la sentencia SQL no se ha establecido ninguno, y el nombre que deseamos dar a1 DataTable.En cualquier caso,
a1 ejecutar el programa tras estos cambios el resultado sera practicamente identico, tan s610 diferiran 10s nombres de 10s DataTable existentes en el DataSet.
En el ejemplo anterior, por la consola se da salida a una combinacidn de informacidn de esquema (el nombre de las columnas) y de datos contenidos en las tablas. Vamos ahora a centrarnos en la informaci6n de esquema que, en cierta manera,
restringira las operaciones que podemos efectuar con 10s datos de cada fila de
cada tabla.
En principio, a1 llamar a1 metodo Fill ( ) de un adaptador de datos, la unica
informaci6n de esquema que se recupera es la de las columnas: nombre, tipo, longitud maxima, valor por defecto, etc. No se obtienen, por el contrario, las restricciones aplicables a las columnas que actuan como clave primaria, ni se indica que
dichas columnas deben mantener valores unicos o que se generan automaticamente
como una secuencia.
www.detodoprogramacion.com
NombreTabla
El primer y tercer padmetro corresponden a 10s que hemos facilitado a1 metodo Fi 11 en el ultimo fragment0 de codigo del punto anterior. El segundo determina si la informacih de esquema creada en el DataSet es la del origen de datos,
SchemaType . Source, 0, por el contrario, es necesario establecer algun tipo de
asociacion, SchemaType .Mapped.
Como en el ejemplo anterior, en el que recupergbarnos datos, habria que hacer
una llamada a Fi 11Schema ( ) por cada conjunto de datos a recuperar, generando
en el DataSet un DataTable con toda la informacih, incluidas las restricciones
de claves primarias. A1 aiiadirse de rnanera independiente, no obstante, lo que ni
10s adaptadores ni el DataSet pueden determinar es la relacion entre 10s distintos
DataTable creados, por lo que no se generan las restricciones apropiadas de clave externa.
Sin embargo, esta informacih puede generarse f6cilmente creando una relaci6n, un DataRelation, entre las tablas, aiiadiendola a la coleccion Relations
del DataSet.
Esto es, precisamente, lo que se hace en el c6digo siguiente:
D i m C o n e x i o n As New SqlConnpction ( "Data Sour(-t=inspiron; I r l i t i a l Catalog=Libros;
"IJCcr ID=sa; Pa-sword=")
"
&
D i m A i a p t a d r F d i t c r i a l e s As New SqlDataAdapteri
"SELEPT * FROM E d i t o r i a l P s " , C o n e x i o n )
Dim A d a p t a d o r L i b r o s As New S y l D a t a A d a p t e r i
"SELECT * FROM L i b r o s " , C i r l e x i o n )
A J , p t a ~ o r E d i t o r i a l e s .F i l l S c h ~ r n a(
D2t J s , S c h e m a T y p e . S o u r c e , " E d i t o r i a l e s " )
A ? a y t a d o r L i b r r > s .F i l l S c h e m a ( D a t o s ,
S i hemaTyye. S o u r c e , " L i b r o q " )
..
D a t o s . R e l a t i o r i s . A d d (New D a t a R e l a t i o n ( " F K - E d L i b r o " , Datos.Tables ( " E d i t o r i a l e s " ) . C o l u m n s ( " I D E d i t o r i a l " ) ,
Datos.Tables("Libros"). C o l u m n s ("Editorial")) )
www.detodoprogramacion.com
9. Conjuntos de datos
Tras las dos llamadas a Fillschema ( ) , observe c6mo se afiade la relaci6n entre las tablas creando un objeto DataRelation. Facilitamos a su constructor el
nombre que deseamos darle a la relacion, una referencia a la columna de la tabla
principal y otra a la columna de la tabla de detalle. Con esto se generan automiticamente las restricciones apropiadas. A1 ejecutar el codigo anterior, tendremos un
DataSet sin datos per0 con toda la informaci6n de esquema. Podemos mostrar
6sta por consola con el codigo siguiente, que producirs el resultado mostrado en la
figura 9.6. Observe 10s atributos de las columnas IDEditorial e IDLibro, asi
como las restricciones definidas en cada tabla.
Dim I d k > l a As D a t a T a b l e ,
For Each l i b l a I n b a t
R e s t r i c c i i n As C o n - t r a i n t
-.T2bles
bla
''I
&
Tabla.TabltName
* * * * * ' I
&
""'
&
&
vbirLf)
{ "Nombre",
Columna.Columr~Ndme},{"Tip"",
C o l u m n a . D a t a T y p e . T o S t r i r , ~ ( )1 , { "Admite nulo", Columna.AllowDBNull}, { "Autoincremento",
Columna .AutoIilcrement 1
{"Valor unico", Colurnna.Unique), -
,-15]..: {l]",
DatosColumnas (Contador,
DatosColurnnas (Contador,
O i ,
1 ))
&
vbCrLf1
C o n s tr a i n t s
Fo
mbre
CType(Restriccior1,
..:
O]",
Restriccion.ConstraintName)
F o r e i g n K e y C o n s t r a i n t ) . C o l u m n s (01,
CType(Restriccior1, F o r e i g n K e y C o n s t r a i n t ) . R e l a t e d C o l u r n n s ( 0 )1
Else
Console.WriteLine("Valor l i n i c o : {O)", C T y p e ( R e s t r i c c i o r 1 , UniqueConstraint).Columns(O))
www.detodoprogramacion.com
www.detodoprogramacion.com
9. Conjuntos de datos
Debe tener en cuenta que, una vez se han definido las restricciones, el orden
en el que invoque a 10s metodos Fill ( ) de cada adaptador es importante. Si
tras las dos llamadas a Fillschema ( ) del ejemplo anterior intenta ejecutar
la sentencia AdaptadorLibros. Fill (Datos, "Libros"), Veria que se
produce una excepcion. Esto es asi porque, al no haber todavia datos en la tablade editoriales, 10s libros estan haciendo referencia a editoriales que no existen, violando una de las restricciones.
Sub Main I
r
pe
).
-- ,.,>1,,,,.;5
7
:
Lind
:<;n??>
lL5i1
L-t.;:nLjil
I'
&
1-
-1
-.,' I . '
,.
' .i
Da tos .Re 1at io ns .Add (New DataRe 1at io n ( " FK-EdL ib ro " , Datos .Tables ("Editoriales") .Columns ("IDEditorial"),
Datos.Tables ("Libros").Columns ("Editorial")) )
+_
Dim Filas
www.detodoprogramacion.com
9. Conjuntos de datos
Fi
w York" 1 )
Filas. Find(1)("Direccion") = "Telkrnaco, 43"
AdaptadorEditoriales.Update(Datos, "Editoriales"]
Da t os ,
Filas
"
Datos.Tables ("Libros").Rows
i
.
I
I ,
L L L '
ctualizaEditoriales(
ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)
~
If args.StaternentT
-_
Ademis de afiadir una nueva editorial, se utiliza el metodo Find ( ) de la coleccidn Rows de la tabla de editoriales para encontrar la que corresponde a1 identificador 1 y modificar su direcci6n.
Observe c6mo se afiaden nuevas filas a las tablas, mediante el m6todo Add ( ) ,
facilitando como argument0 un arreglo con todos 10s valores. Fijese t a m b i h en la
codificacidn del m6todo ActualizaEditoriales ( 1 , que se ejecutar6 cada vez
que se actualice una fila de la tabla Editoriales. En su interior comprobamos si
lo que se produce es una insercidn, caso en el cual recuperamos el valor del identificador y lo almacenamos en una variable.
www.detodoprogramacion.com
Si ejecuta este programa varias veces, se aAadiran multiples editoriales y Iibros a las respectivas tablas, con exactamente la misma informacion per0 distintos identificadores, ya que estos 10s genera automaticamente SQL Server.
Ademas del metodo Find ( ) , que se emplea para encontrar la fila que tiene un
cierto valor en la columna que actua como clave principal, tambien puede usar
el metodo Select ( ) para recuperartodas aquellasfilasque cumplen un cierto
criterio de busqueda. Consulte la informacion de referencia de la clase DataTable para ver las diferentes versiones que existen de dicho metodo y saber
como se usa.
9. Conjuntos de datos
aSet ("Hospital")
Di
D i m Pacientes A s DataTable
D i m Historial As DataTable
=
=
W i t h Pacientes .Columns
Type.GetType("System. Int32") )
.AutoIncrement = True
.AutoIncrementSeed = 1
.AutoIncrementStep = 1
.Readonly = True
W i t h .Add("Nombre", Type.GetType("System.Stririg") )
.MaxLength = 40
.AllowDBNull = False
End W i t h
W i t h .Add ( " Dire ccion", Type. Ge tT ype ( "System. St r i rig" )
.MaxLength = 50
End W i t h
W i t h .Add ( "Tel e fono", Type. GetType ( "System. String" ) )
.MaxLength = 12
End W i t h
End W i t h
,
I-
1-
Type.GetType("System.Int32") )
"
.AutoIncrementSeed
.AutoIncrementStep
.Readonly = True
End W i t h
100
.Add("Paciente", Type.GetType("System.Int32") )
.Add("Fecha", Type.GetType ("System.DateTirne"))
W i t h .Add("Descripcion", Type.GetType ("System.String"))
.MaxLength = 1024
.AllowDBNull = False
End W i t h
End W i t h
.,
I
,ji
. ., . - .
,*..Lil.iii,C'L;
i.7
::i.t:,-e
c,r;iQrL?
www.detodoprogramacion.com
E a c i e r i t ~ s . C o l u m n (s " I D P a c i e n t e " ] ,
H i r t i r i a l . c o l u m r ~ s( " P a c - i e r l t e " ) ) )
Creamos un DataSet vacio a cuya propiedad Tables afiadimos dos elementos, dos tablas llamadas Pacientes e Historial, cuyas referencias almacenamos en sendas variables. A continuacicin tenemos dos bloques de c6digo similares,
en 10s cuales vamos afiadiendo elementos a las colecciones Columns de cada uno
de esos DataTable. Para ello usamos el metodo Add ( ) que, como puede ver, toma dos partimetros: el nombre del nuevo Datacolumn y el tip0 de dato. No podemos entregar directamente, como valor, Integer o System. Int32,ya que &tos
son tipos y lo que necesita el constructor es un valor que identifique a1 tipo. Lo obtenemos mediante el metodo compartido GetType ( ) de la clase Type.
A medida que van afiadiendose columnas, se usa la referencia devuelta por el
metodo Add ( ) para establecer algunas propiedades adicionales, como MaxLeng th
oAllowDBNul1. Las columnas que actuan como clave, IDPaciente eAdentrada,
se definen solo de lectura y con increment0 automtitico. Fijese tambien c6mo se establecen como claves principales asigntindolas a la propiedad PrirnaryKey de sus
respectivas tablas. Dicha propiedad necesita un arreglo de objetos Da taColumn,
ya que la clave principal puede componerse de multiples columnas. En este caso
creamos el arreglo con un unico elemento: la columna IDPaciente o IDEntrada,
segun la tabla.
Finalmente, aiiadimos una relaci6n a1 Data Set creando una clave externa en la
tabla Historial, concretamente en la columna Paciente, enlazada con la clave
primaria de la tabla Pacientes. Como sabe, esta relacion generarti automtiticamente otras restricciones.
En este momento tenemos un Data S e t con informacion de esquema per0 vacio, el mismo estado que obteniamos tras las llamadas a Fillschema ( ) de un
ejemplo previo. Para llenar el DataSet con datos no vamos a conectar con un origen, definir un comando y llamar a1 mktodo Fill ( ) de un adaptador, sino que
iremos afiadiendo fila a fila e introduciendo 10s datos apropiados en cada una de
las columnas.
La primera columna de cada tabla, clave primaria definida como so10 de lectura y con autoincremento, tomarii su valor automiiticamente a medida que vayamos
afiadiendo filas. Podemos recuperar su valor leyendo la columna de la fila r e c i h
ariadida. Es lo que se hace en el c6digo siguiente para enlazar las entradas de historial con el paciente que corresponda:
I
Dim P a c i e n t e As DataRow
= Pacientes.NewRcw()
P a c i e n t e ("Nornbre" ) = " F r a n c l s c o C h a r t e "
P a c i e n t e ( " D i r e c c i o n " ) = "Apdo. 5 4 "
www.detodoprogramacion.com
9. Conjuntos de datos
P a c i e n t e ( " T e l e f o n o " ) = " 7 6 3 376 3 2 1 "
P a c i e n t e s . ROWS . A d 3 ( P a c i e n t e )
Dim E r t t r a d a As D a t a R o w = H i s t o r i a l . N e w K o w ( )
C n t r a d a ("Paciente") = Paciente ( " I D P a c i e n t e " )
Erltrada ("Fecha")
F r l t r a ?a ( " Des c r I p
) = " ( ' ~ l i c o renal"
Hlst. r i a l . RI ds . A d A ( E n t r a d a )
I'acierlte
Pdcientes.NewKow( )
" F i l i ~ ~ i Fr i~r l ~o "~ ,
1 e r A t e( " N ~ ~ r n b r e " )
" )
= " P e r , 12"
P,icier,te("Telefor,r~r")
= " 1 2 3 4 5 6 789''
P a c i e n t e s . ROWF. A d d ( P a c i e r L t e )
--
obtener esa informacion y contenido son 10s mismos que ya conocemos. Para verlo
en la practica, vamos a aiiadir a1 programa compuesto por 10s dos bloques de c6digo previos, introducidos en el metodo Main ( ) , dos metodos adicionales. El primero, a1 que llamaremos InformacionEsquema ( ) , recibe como parimetro una
referencia a un D a t a S e t y muestra por la consola su estructura. El c6digo de este
metodo, muy similar a1 usado en un ejemplo anterior, seria el mostrado aqui:
Sub I r t f o r m a c l o n E s q u e m a (ByVal D a t o s As D a t a S e t )
www.detodoprogramacion.com
Fo
Console.WriteLine ("Tabla ' ' I & Tabla.TableName
vbCrLf & New String("-", 4 0 ) )
C o n s ~ l e . W r i t e L i n e ( " * * ~ *COLUMNAS
*
*****'I
&
I""
&
"Nombre", Columna .ColumnName], ["Tipo", Columna.DataType.ToString()} , ["Admite nulo", Columna.AllowDBNull], { "Autoincremento", Columna .AutoIncrement
{"Valor unico", Columna.Unlque), { "Longitud", Columna.MaxLength1 1
J,
,-15)..: {l)",
DatosColumnas (Contador, 0 ), DatosColumnas (Contador, 1) )
Ne
Console.WrlteLlne(New String("=", 6 0 ))
Next
Cons o 1e .W r 1 t eL 1 n e ( " * *
Fo
* REST R ICC IO N E S * * * *
"
&
vbTab,
r,
www.detodoprogramacion.com
9. Conjuntos de datos
El segundo metodo, llamado MuestraContenido ( ) , tambien recibe como pariimetro un Data S e t.En este caso lo que se hace es recorrer todas las tablas, y filas
de cada tabla, para mostrar su contenido, indicando el nombre de cada columna.
El c6digo seria el siguiente:
I
&
Tabla.TableNarne
&
'"")
Next
Console.WriteLine
Next
Console.WriteLine ( )
Next
( )
End Sub
mente, en el origen de datos deberia existir exactamente la misma estructura o esquema que hemos definido nosotros en el D a t a S e t.
www.detodoprogramacion.com
9. Conjuntos de datos
Llame a1 final del mdtodo Main ( ) del ejemplo del punto anterior a1 mdtodo
WriteXmlSchema ( ) del DataSet, facilitando como Gnico par6metro el nombre
del archivo en el que se almacenar6 el esquema, por ejemplo EsquemaHospital
xsd.Puede verlo con el Bloc de notas, tendr6 que conocer la sintaxis de 10s esquemas XSD, o bien abrirlo directamente en Visual Studio .NET para ver una representaci6n (vease figura 9.8). Posteriormente, en cualquier otro punto de este mismo
programa o en otra aplicacGn, bastaria una llamada a1 mktodo ReadXmlSchema ( 1
de un DataSet para recuperar toda la informaci6n Be esquema.
Si la informacidn de esquema no va utilizarse nunca de forma independiente,
sin0 asociada siempre a 10s datos que contiene el propio DataSet,podemos almacenar conjuntamente esquema y filas de datos. Para ello utilizariamos el mCtodo
Writexml ( ) facilitando dos par6metros: el nombre del archivo donde va a escribirse y el indicador XmlWri teMode .Wri teSchema.El resultado seria un archivo
XML conteniendo el esquema XSD, a1 principio, y 10s datos, detrds. Si no entrega-
www.detodoprogramacion.com
mos el segundo parimetro, el archivo contendria s610 10s datos como puede apreciarse en la figura 9.9.
A1 recuperar el archivo de datos, mediante el metodo ReadXml ( ) ,tambien tendriamos que indicar si queremos leer la informaci6n de esquema o s610 10s datos.
Figura 9.8. Podemos usar Visual Studio .NET para obtener una representacion
del esquerna
DiffCrams
A medida que se efectuan cambios en las tablas de un Data s e t, las colecciones
DataRow de cada DataTable alojan no s610 la nueva informaci6n, sin0 tambien el
estado y 10s datos que contenian previamente. Esta informaci6n, relativa a 10s cambios producidos desde que se cre6 o recuper6 el contenido del D a t a S e t , permanece ahi hasta que se llama a1 m6todoAcceptChanges ( ) del D a t a S e t que, como
sabe, invoca a1 metodo homdnimo de cada DataTable.
Cuando se almacena la informaci6n en un archivo XML, mediante el metodo
W r i t e x m l ( ) , lo que se almacena son 10s valores actuales de las filas, tras efectuar
todos 10s cambios, a pesar de que no se haya invocado a A c c e p t c h a n g e s ( ) . A1
recuperar el archivo, por tanto, tendriamos un Data s e t con datos per0 sin informaci6n de c6mo se oper6 sobre estos. La perdida del estado de las filas, y la informaci6n previa a la modificacibn, no seri importante si la aplicaci6n esti diseiiada
para trabajar siempre localmente.
www.detodoprogramacion.com
9. Conjuntos de datos
.-.
.............
f .\\Ek400\SiitansC\
. . . . . . . .
._
. . . .
....
"_\C?:
r--;,.gt;;s
>"'
..v'-F--.
...............................
Figura 9.9. Estructura del archivo XML conteniendo solo 10s datos, sin informacion
de esquema
Suponga, por el contrario, que la aplicaci6n que esth disefiando obtiene el esquema y 10s datos a partir de una conexi6n con un origen de datos. A partir de ahi,
sin embargo, tiene que trabajar sin conexi6n porque el programa, pongamos pol
caso, se ejecuta en un portitil y el usuario viaja de un punto a otro sin posibilidad
de conexi6n permanente con el servidor de datos.
Todas las ediciones, por lo tanto, deberhn almacenarse localmente a fin de quc
puedan posteriormente, en alg6n momento en que se tenga conexibn, resolverse
con el origen de datos.
En un caso asi es imprescindible conservar no s610 10s datos nuevos, sin0 1:
propia informacih de 10s cambios que han ido efectuindose. Estos pueden alma.
cenarse en un documento XML con formato DiffGrarn, una estructura en la que sc
determina el estado de cada fila y, ademis, se indica cud1 era el estado anterior i
www.detodoprogramacion.com
Al guardar el estado de un DataSet en formato DiffGrarn no se guarda la information de esquema, por lo que esta deberia mantenerse separadamente,
con una llamada aWriteXmlSchema ( ) , recuperandose posteriormente, en el
momento de volver a crear el conjunto de datos, antes de recuperar 10s datos
propiamente dichos.
Puede efectuar una prueba, partiendo del c6digo del ejemplo anterior, a fin de
ver la estructura del DiffGvarn.
Dk 10s pasos siguientes:
0
Despuks de aiiadir 10s dos pacientes a la tabla paciente, invoque a1 mktodo Acceptchanges ( ) del DataSet. De esta forma 10s cambios quedarbn
consolidados y las filas no mantendrbn estado ni valores previos.
Modifique el telkfono del segundo de 10s pacientes, simplemente por modificar un dato que ya estaba aceptado para ver c6mo lo refleja el DiffGrarn.
Puede hacerlo con una sentencia como la siguiente:
P a c i e n t e s . S e l e c t ( " N o m b r e = ' F i l i p i n o Fino"')
( 0 )( " T e l e f o n o " )
Llame a1 final del ddigo, tras aiiadir las entradas del historial del segundo
paciente, a1 mktodo Wri teXml ( ) pasando el indicador XmlWriteMode .
Di f fGram como segundo parbmetro.
Haga doble clic sobre el archivo generado para abrirlo en Internet Explorer
y poder apreciar, como en la figura 9.10, la descripci6n del estado y datos
del DataSet.
www.detodoprogramacion.com
Cornentarlo
Auto
Readschema
Inferschema
Ignoreschema
DiffGram
Fragment
Como puede ver, ReadXml ( ) siempre puede obtener el esquema, si 4ste se encuentra embebido en el documento XML, o bien deducirlo a partir de la estructura
de 10s datos. La Onica excepci6n se produce cuando va a recuperarse un DiffGram,
ya que 4ste no incorpora el esquema en el documento y tampoco es posible deducirlo a partir de 10s datos. Si vamos a recuperar un documento de tip0 DffGrarn,
por tanto, es imprescindible que antes hayamos obtenido el esquema con una llamada a ReadXmlSchema ( ) .
En el ejemplo desarrollado antes, en el que se definia un Data Se t y se aiiadian
datos a dos tablas, aiiada las sentencias siguientes a1 final:
Datos.WriteXrnlSchema i"EsquernaHospital.xsd")
D a t o s . W r i t e X r n 1 ("Hospital.rm1")
Datos.WriteXml("HospitalCor~Esquema.xrnl", X r n 1 W r i t e M o d e . W r i t e S c h e r n a )
Datos .WriteXml ("HnspitalCarnbios.xml", X r n l W r i t e M o d e . D i f f G r a m )
De esta forma tendrd cuatro archivos diferentes con informacih del DataSet:
0
9. Conjuntos de datos
En un programa distinto, tras ejecutar el anterior, podriamos recuperar el contenido del DataSet usando diversas variaciones del metodo ReadXml ( ) , utilizando 10s mismos metodos InformacionEsquerna ( ) y MuestraContenido ( )
del ejemplo anterior para apreciar el esquema y 10s datos.
Si lee el archivo Hospital . xml,sin m&, ver5 que obtiene el nombre y tipos de
las columnas, per0 no la informaci6n de claves primarias ni externas, ni tampoco
las restricciones. gstos son elementos que ReadXml ( ) no puede deducir a partir
de la informaci6n.
Pruebe a leer el archivo HospitalConEsquema. xml, o bien a recuperar el esquema EsquemaHospital. xsd con una llamada a ReadXmlSchema ( ) y luego
recuperar el mismo Hospital. xml anterior. En este caso si se cuenta con toda la
informaci6n de esquema, ya que &a se almacen6, en el mismo archivo y de manera independiente, a fin de poder recuperarla.
Por ultimo, recupere la informaci6n del DiffGram almacenada en el archivo
HospitalCambios . xml, tal y como se hace en el siguiente fragment0 de c6digo.
Observe que antes recuperamos el esquema ya que, de lo contrario, obtendriamos
una excepci6n.
Sub M a i n ( )
Di
Datos.Rea
HospitalCarnbios.xm1")
I n f o r m a c i o n E s q u e r n a ( Datos)
M u e s t r a C o n t e n i d o (Datos)
End Sub
A fin de poder apreciar la informaci6n recuperada por el ReadXml ( ) , podemos modificar el bucle final del mdtodo MuestraContenido ( ) dejhdolo asi:
For Each F i l a In Tabla.Rows
For Each Colurnna In Tabla . C o l u m n s
C o n s o l e . W r i t e ( F i l a (Columns) )
Console.Write(vbTab)
Next
Console.WriteLine("<
"
&
Fila.RowState.ToString
&
"
>")
Next
De esta forma, a1 ejecutar cualquiera de las variaciones veria si las filas mantienen su estado 0, por el contrario, lo han perdido. En la parte inferior de la figura 9.11
puede ver c6mo se indica que la segunda fila de la tabla Pacientes est6 modificada, y las dos ultimas de la tabla His torial son nuevas. Estos datos no 10s veria
www.detodoprogramacion.com
9. Conjuntos de datos
www.detodoprogramacion.com
www.detodoprogramacion.com
usando el entorno de Visual Studio .NET como tendri ocasi6n de ver en capitulos
posteriores.
Added
CurrentRows
Todas las filas que componen actualmente la tabla a excepcion de las elirninadas
Deleted
www.detodoprogramacion.com
ModifiedCurrent
ModifiedOriginal
OriginalRows
Unchanged
None
Ninguna fila
Puede comprobar el funcionamiento del metodo Select ( ) partiendo de cualquiera de 10s ejemplos del capitulo previo, accediendo a una tabla del DataSet
para recuperar tan s610 ciertas filas, segun criterio o estado, o bien las filas en un
cierto orden. Recuerde que el resultado obtenido por una llamada a Select ( )
siempre es un arreglo de DataRow que, dependiendo de 10s criterios de seleccidn,
podria estar vacio. En el ejemplo siguiente puede ver c6mo, partiendo de la tabla
Libros de SQL Server, se muestran diversos resultados: todas las filas, s610 aquellas en las que el titulo del libro comienza con la palabra Programacion y s610 las
que corresponde a la primera editorial orden6ndolas, adem&, por la columna
Precio. La figura 10.1es una muestra del resultado que se obtendria.
Imports S 7 s t ii rn . Da t a . S '3 1 T 1 i i: rl t
Module M o d u l e 1
Sub Ma1 1 1
( )
Ad apt a d o rL 1 b ro s . Fi 1 1 ( Da to s ,
"
L 1 b ro s " )
Filas)
www.detodoprogramacion.com
"
&
Filas)
Filas
"
Fllas)
End Sub
su
Console.WriteLine ( T i t u l o
&
vbCrLf
&
New String("-", 7 0 ) )
C o n s o 1e W r 1 t e L i n e (
" [ 0 ,- 50 )
( 1,6)
( 2 , 3) ' I ,
Fila("Titulo"), Fila("Precio"), Fila("Editoria1")
~
Next
End Module
El m6todo Select ( ) de la clase DataTable tiene ciertas hmitaciones, especialmente cuando no se controla el acceso a datos mediante c6digo sin0 que se
pretenden utilizar componentes de interfaz de usuario. El resultado devuelto por
este mgtodo, un arreglo de DataRow, no puede vincularse directamente con una
rejilla u otros controles de datos.
La clase DataView ofrece un mecanismo mds flexible para obtener subconjuntos
de 10s datos alojados en un DataTable, facilitando la vinculaci6n directa con
componentes de interfaz. Podemos usar un DataView para obtener parte de las
filas de un DataTable, sobre la base de un criterio de selecci6n o estado, en el orden que nos interese. Es posible crear mCiltiples DataView sobre un mismo DataTable,recuperando diferentes conjuntos filas y en diferentes brdenes, sin por ello
duplicar la informaci6n.
www.detodoprogramacion.com
IBindingList
www.detodoprogramacion.com
Funcionamiento de un DataView
Los objetos DataView se asocian con objetos DataTable, ya sea facilitando la
referencia a este ultimo a1 constructor de la clase DataView o usando la propiedad Table del DataView para vincularlo a1 DataTable. En cualquier caso, a
partir de ese momento podemos usar la propiedad Item del DataView para acceder a las filas de la vista, que ser4n todas o parte de las existentes en la tabla.
Cada uno de 10s elementos de la propiedad I tem, que actua como indexadora de
la clase, es un objeto de la clase DataRowView. Los objetos de esta clase ofrecen
una vista de un DataRow en un estado en particular, es decir, no mantienen 10s diversos estados que puede tener una fila de datos durante la edici6n.
El conjunto de filas que forman la vista dependerii del valor que tenga la propiedad RowFil t er. gste puede facilitarse como segundo partimetro del constructor de DataView o bien establecerse posteriormente mediante una asignaci6n a
dicha propiedad. El filtro se define como una cadena de caracteres en cuyo interior
se introducen 10s pariimetros de seleccibn, con la misma sintaxis empleada con el
metodo Select ( ) de la clase DataTable.
Si no deseamos que las filas aparezcan en la vista con el orden por defecto, no
tenemos m4s que indicar en la propiedad Sort el nombre de la columna o columnas por las que deben ordenarse. Esa columna se convertir4 en clave de un indice,
facilitando las operaciones de busqueda. Opcionalmente, puede indicar tras cada
nombre de columna si el orden debe ser ascendente o descendente. Esta cadena,
indicando las columnas por las que se ordenari, tambibn puede facilitarse como
pariimetro a1 constructor de Da t aVi ew, concretamente como tercer argumento.
Por ultimo, en lo que respecta a las propiedades de selecci6n de filas, podemos
asignar un estado a ROWS t a t e Fi 1t e r a fin de obtener s610 las filas que se encuentren en el estado indicado. Como se decia antes, 10s objetos DataRowView representan el valor de un DataRow en un cierto estado, por defecto el valor actual,
pudiendose indicar otro estado diferente mediante una asignaci6n a RowStateFilter o entregando el mismo valor como ultimo argumento del constructor.
Adem4s de acceder a 10s datos, mediante la citada propiedad I t e m , tambien
podemos efectuar operaciones de edici6n sobre las filas, utilizando para ello 10s
metodos AddNew ( ) y Delete ( ) del DataView y BeginEdit ( ) , EndEdit ( ) y
CancelEdit ( ) de cada DataRowView. Que estas operaciones Sean posibles, o
no, dependerii de 10s valores que mantengan las propiedades A11owNew, A 1 1owDelete y AllowEdit del propio Dataview.
www.detodoprogramacion.com
Todos 10s DataTable cuentan con una vista por defecto, a la que puede accederse mediante la propiedad Defaultview,que puede modificarse mediante
las propiedades RowFilter, Sort y RowState. De esta forma podriamos
modificar la vista por defecto que nos ofrece el propio DataTable, en lugar
de crear un DataView nuevo.
Funcionamiento de un DataViewManager
A diferencia de Da t aVi ew, 10s objetos Da t aVi ewManage r se enlazan directamente con un DataSet y no con un DataTable. Su finalidad es facilitar una vista
global de todas las tablas que forman el conjunto de datos, respetando las relaciones que pudieran existir entre ellas. Podemos vincular el DataViewManager con
el DataSet facilitando una referencia a este ultimo a1 constructor del primero, o
bien sirviendonos de la propiedad DataSet con que cuenta la clase DataviewManager.
En lugar de crear un nuevo DataViewManager, tambien podemos obtener el
que tiene por defecto el conjunto de datos mediante la propiedad DefaultviewManager de la clase DataSet.
Los dos miembros de m5s inter& para nosotros, en la clase DataViewManager,
serdn Dataviewsettings y CreateDataView ( ) . El primero, una propiedad,
nos permite acceder a la colecci6n de objetos DataViewSet ting que establecen
las propiedades de la vista de cada tabla, mientras que el segundo, un metodo, es
el encargado de crear nuevas vistas asociadas a tablas.
Cada elemento de Ia colecci6n DataViewSet tings mantiene 10s atributos de
la vista aplicada a cada tabla. Para ello, la clase Dataviewsettings cuenta con
las mismas propiedades RowFilter, Sort y RowStateFilter explicadas en el
punto anterior, junto con la propiedad Table que vincula la configuraci6n con
una cierta tabla.
www.detodoprogramacion.com
Como siempre, en la documentaci6n de Visual Studio .NET encontrarh la informaci6n de referencia relativa a cada uno de 10s miembros de las clases mencionadas, Da taView,Da taVi ewMana ge r, Data RowView y Da t aVi ewS e tting.A partir
de este punto nos centraremos en ver c6mo utilizarlas en la przictica, con algunos
ejemplos sencillos per0 demostrativos.
Partimos, como en todos 10s ejemplos previos, de un nuevo proyecto de tip0
Aplicacion de consola usando el lenguaje Visual Basic .NET. Posteriormente, en
10s capitulos dedicados a1 us0 de las herramientas de Visual Studio .NET, aprenderzi a crear vistas y enlazarlas con componentes de interfaz sin necesidad de escribir codigo alguno.
___
( )
Di
.,
" U S C . ~ID=sa;
ect i o n ! itial C a t a l i
E'asswcxd=" )
D i m AdaptddorLibros AS New S q l D a t a A d a p t e L (
" S E L E C T A FROM L i b r o s " , CIr l e x i b r l ,
AdaptadorLibriJs.F i l l (Datos,
"Libros")
D i m VistaTotal A s New -
DataView(Datos.Tahlrr ("Libras"))
D i m V i r t a E r o g r a r a c i o n A s New
DataView(Dator.Tdblesi"llbros"),
" T i t u l c L I K E ' P r o g r a r n a c i o r l * "I,
~
"Titulo",
DataViewRowState.CurrentRows)
www.detodoprogramacion.com
>
'
Hemos optado por establecer 10s criterios de selecci6n y ordenaci6n en el mismo momento en que se crea cada Dataview, facilitando 10s m6todos apropiados
a1 constructor de dicha clase. A1 final tenemos tres objetos que ofrecen vistas diferentes de la misma tabla de datos. Para trabajar con estos objetos tendremos, asimismo, que hacer algunos cambios en el m6todo Mues t ra Fi1as ( ) . Este quedaria
como se muestra a continuacih:
,c
su
trin
Ti
Console.WriteLine(Titulo
&
vbCrLf
&
Vista
As Dataview)
D i m Fila As DataRowView
Console.WriteLine (vbCrLf
C o n s o l e . Readi 1 ne ( )
End Sub
&
Cada DataTable cuenta con una vista por defecto, un objeto DataView a1 que
hace referencia la propiedad Def aultview. Esta vista, inicialmente, hace referencia a todas las filas de la tabla. Utilizando las propiedades RowFilter, Sort y
Rows t ate Fi1te r, sin embargo, podemos configurarla para que nos facilite 10s
datos que nos interesen en cada momento.
www.detodoprogramacion.com
0 C:\P&MVisualBasicNmCap_lO\VariasVistas\bin\VariasVistas.ere
-10
Figura 10.3. Conjuntos de filas ofrecidos por las distintas vistas creadas
__
I
:,
,
- ...~
L i ~ i . i i . L.A,2 ~ . : c : ~ c . ~ i ~ ~ ~ :
Dim Conexion As New SqlConnection( "Data Source=inspiron; Initial Catalog=Libros;
"User ID=sa; Password=")
~
i.
il,,~
www.detodoprogramacion.com
"
&
--
L - L t
_,
Datos.Tables("Libros")
L -
MiTabla.DefaultView.RowFi1ter =
"Titulo LIKE ' Proqramacion* "'
Wi
. RowFilter
"Editorial=l"
. S o r t = "Precio DESC"
.RowStateFilter
End With
'
DataViewRowState.Currer1tRows
Imports S y s t e m . D a t a . S q l C l i e n t
Module M o d u l e 1
Sub M a i r J ( )
"
&
D i m A d a p t a d o r L i b r o s As New S q l D a t a A d a p t e r (
"SELECT * FROM L i b r o s " , C o n e x i o n )
r
D i m D a t o s As New D a t a S e t ("MisDatos")
D i m M i T a b l a As D a t a T a b l e
Datos.Tables("Libros")
D i m Columna As DataColumn
D i m NornbreColumna As String
D i m ValorBuscado As String
MiTabla.DefaultView.S3rt
"
&
NombreCclumna
")
{2,61",
"Titulo"), "Editorial"),
"Precio") 1
End If
End Sub
www.detodoprogramacion.com
Console.WriteLine(Titulo
Dim F i l a As DataRowView
&
vbCrLf
&
New String("-", 7 0 ))
Fo
i4,31
" I
End Sub
End Module
Usamos una vez mAs la tabla L i b r o s de Sc Server, aunque podriamos utilizar cualquier otro origen de datos. Tras crear el adaptador de datos y generar el
D a t a S e t , enumeramos las columnas de la tabla para que, a traves de la consola, el
usuario del programa pueda seleccionar una de ellas para ordenar las filas. Asignamos el nombre de columna introducido a la propiedad S o r t del DataView y,
act0 seguido, mostramos el contenido de la vista. AparecerAn, como puede verse
en la figura 10.4, las filas ordenadas por esa columna.
A continuaci6n solicitamos un valor a buscar, mostrando algunos datos de la
primera fila que lo contenga en la columna clave. Puede modificar esta parte final
para, en h g a r de llamar a F i n d ( ) , emplear el metodo FindRows ( ) y enumerar
todas las filas que coinciden.
www.detodoprogramacion.com
Editar una fila existente: Localizado el objeto DataRowView que corresponda, llamariamos a1 metodo BeginEdit ( ) para iniciar 10s cambios, tras lo
cual modificariamos el valor de las columnas que deseemos. El proceso terminaria con una llamada a EndEdit ( ) , para confirmar 10s cambios, o bien
CancelEdit ( para deshacerlos.
0
Aiiadir una nueva fila: Invocamos a1 metodo AddNew ( ) del DataView para
asi obtener un nuevo DataRowView,asignando a continuaci6n 10s valores
de todas sus columnas y, como en el caso anterior, confirmando 10s cambios
o descartindolos mediante 10s metodos EndEdit ( ) y CancelEdit ( ) .
Eliminar una fila: Basta con llamar a1 metodo Delete ( ) del DataRowView
a eliminar. En realidad la fila no se elimina en ese instante, sino que se modifica su estado para que aparezca como candidata a ser eliminada.
Cualquier modificaci6n de las filas causari que en el DataTable del que depende la vista se aiiadan nuevas filas o cambie el estado de 10s asistentes. En cualquier
caso, esos cambios no son en firme hasta en tanto no se llame a1 metodo AcceptChanged ( ) del DataSet 0,en caso de que deseemos transferirlos a un origen de
datos, se utilice el metodo Update ( ) del adaptador de datos.
Manteniendo el metodo Mue s tr a Fi1as ( ) de 10s ejemplos previos, cambie el
metodo Main ( ) para que quede tal y como se muestra a continuaci6n:
Sub Main( )
r
* I
. t z * + 4 ,
iP
# ?
, >
www.detodoprogramacion.com
"
&
, -,:'+
&
r::
&
vbCrLf)
_ %
Vista.AddNew()
'
AdaptadorLibros.Update(Datos.Tables("Libros")
End Sub
Ademris del conjunto de datos y el adaptador, ahora creamos tambien un CommandBuilder que se encarga de generar las sentencias de actualizacibn, inserci6n
y borrado del origen de datos. Act0 seguido creamos una vista y mostramos las filas que la componen, tras lo cual aiiadimos una nueva fila y confirmamos 10s cambios, tanto en el DataRowView,con la llamada a EndEdit ( ) , como en el propio
origen de datos, llamando a Update ( ) .
Si todo va bien, la ejecuci6n de este programa deberia generar el resultado que
puede verse en la figura 10.5. Tras ejecutarlo, puede comprobar el contenido de la
tabla L i b r o s , por ejemplo desde el Administrador corporativo de SQL Server, para
ver la nueva fila insertada. Como en casos anteriores, y por mantener la simplicidad del cbdigo, no se han controlado las posibles excepciones de ejecuci6n que podrian generarse.
Aunque en este ejemplo tan s610 se inserta una fila, igualmente podrian haberse
modificado datos de las existentes o haberlas eliminado. El proceso es exactamente
el mismo, cambiando s610 la llamada a AddNew ( ) por la acci6n que corresponda.
www.detodoprogramacion.com
Figura 10.5. La vista de datos antes y despues de aiiadir una nueva fila
i,! .-c
iJ
:
,:iii.i
'- ", .,
uI2-i
L
j~
-
L : . : ~ . q ~
511
~ ~ L:,:~~:;c?.5
~
www.detodoprogramacion.com
"
&
AdaptadorEditoria1es.MissingSchemaAction
M i s s i n g Sc h e ma Ac t i on . A d d W 1 t h Ke y
AdaptadorLibros.MissingSchemaActior1 = Mi s s i ng SchemaAc t i o rl .Add Wi t h Ke y
Adapt
11 (Datos, "Editoriales")
AdaptadorLibros. F i l l (Datos, "Libros")
,
Dato?.Relations.Add(New DataRelation ("Libros d e l a editorial",
Datos.Tables ("Editoriales"). C o l u m n s ("IDEditorial"),
Datos.Tables ("Libros"). C o l u m n s ("Editorial")) )
~
DataGridl. Datasource
Data Gr i d 1 . Da t aMembe r
=
=
Datos
" Edit or i a 1es "
A1 ejecutar el programa, la cuadricula mostrari un aspect0 similar a1 de la figura 10.6. A1 pulsar en el nombre de la relacidn, la editorial seleccionada se indicarg
en la parte superior de la cuadricula y aparecerin 10s datos de todos sus titulos.
Con esto, las editoriales tan sdlo deberian mostrar 10s libros cuyo titulo comenzase con 10s caracteres P rog rama cion A1 ejecutar el programa, sin embargo,
veri que el resultado es exactamente el mismo que obtenia antes. Con la sentencia
I'
www.detodoprogramacion.com
Datos.Tables("Editoriales"].DefaultView
-.__-_______-.__
~
ultimedia
Telemaco. 43
EdificioValreaiW,l'phnta
901 Grsiscn Street
605 Thtrd Avenue New Ywk
=
=
= -
ViewManager
" Ed i to r i a 1e s "
Creamos un nuevo DataViewManager asocihdolo con el DataSet. A continuaci6n usamos la colecci6n DataViewSettings para establecer el filtro de la
selecci6n sobre la tabla Libros. Por ultimo, enlazamos el DataViewManager directamente con el DataGrid. Ahora, al ejecutar el programa, podrti seguir seleccionando cada editorial por separado, per0 s610 aparecer6n 10s libros cuyo titulo
comience por el prefijo indicado, como se aprecia en la figura 10.7.
www.detodoprogramacion.com
ie
W i15-1392
?A 415-13'5N 4151351
54-4151261
ProgmmaclonconMs~alCP N E I
Prcgranucioncon\,isual Stvdio N E T
Prcgramaaonoon\Asual Basic NET
Prcqramanoncon k l p k i 6 ) Kylix
FraroscoCb
FranciscoCh
FrancisaJCh
Francisco Ch
1
1
1
1
35
A0
39
33 25
La selecci6n de parte de las filas de un conjunto de datos, obtenido previamente mediante una consulta, o la elecci6n de un orden distinto, tradicionalmente ha
requerido una comunicaci6n con el servidor para facilitar el nuevo resultado. Gracias a la clase Dataview, s e g ~ ha
n podido verse en este capitulo, con ADO.NET es
posible conseguir esas operaciones de manera mucho m6s r6pida y sin establecer
una conexi6n con el origen de datos.
En realidad, programando el acceso a datos desde c6digo tal y como estamos
haciendo en 10s ejemplos de 6ste y 10s capitulos previos, las vistas no son muy necesarias puesto que podemos conseguir resultados similares mediante el m6todo
Select ( ) con el que cuentan 10s DataTable.A la hora de enlazar las filas con un
componente de interfaz, un tema del que nos ocuparemos en un capitulo posterior, las cosas cambian, ya que no es posible vincular con un arreglo de DataRow,
pero si con un DataView o un DataViewManager.
www.detodoprogramacion.com
.. .
www.detodoprogramacion.com
En el capitulo dedicado a1 estudio de 10s conjuntos de datos y clases relacionadas, DataSet, DataTable, DataRow, Datacolumn, etc., se introdujeron algunos
temas relativos a1 almacenamiento y recuperacibn de 10s datos, y su informacih
de esquema, en forma de documentos XML y esquemas XSD. '3610 esa posibilidad
nos permite, como se vio en dicho capitulo, trabajar con datos en una aplicacih almacen6ndolos localmente, sin necesidad de ninguna base de datos ni servidor.
La integracion entre ADO.NET y XML, sin embargo, puede llegar a ser mucho
mds estrecha como se veri en este capitulo, haciendo posible el acceso sincronizado
a 10s mismos datos desde un DataSet y en forma de documento XML. Esto posibilita, por ejemplo, la transformacih de 10s datos mediante XSLT o b&quedas m6s
elaboradas que las que permite el metodo Select ( ) de un DataTable.
Tambien existe la posibilidad de tratar como un Data S e t informacih alojada
en un documento XML, sin que necesariamente tenga el formato propio de ADO.NET.
Esto abre las puertas a la integraci6n entre aplicaciones a1 ser XML un lenguaje
adoptado como estgndar mundial.
11. XML
Ante todo, tenga en cuenta que este libro se centra en el tema del acceso a datos
desde Visual Basic .NET usando principalmente ADO.NET, por lo que no se aporta un estudio detallado de XML como el que podria encontrar en un titulo m i s especifico sobre este tema. Tambikn puede encontrar abundante informaci6n sobre
XMLen http://MSDN.Microsoft.com/xml.
El entorno de Visual Studio .NET cuenta con diseiiadores y asistentes que facilitan la mayoria de las tareas que implica el trabajo con XML, como la edici6n de
10s documentos, creaci6n de esquemas XSD u hojas de estilo XSL. Algunas de estas herramientas las conoci6 en el tercer capitulo, a1 crear 10s archivos Libros xsd
y Libros .x m l .
www.detodoprogramacion.com
</Editoriales>
</Libras>
Working Drafts
Follow the links above for details about the drafts issued by the XML Query. XML Schema, and XML Linlang WGs The
documents listed below are the working drafts issued by the YML Core working group
..
.lSSUeS
..
.
www.detodoprogramacion.com
11. X M L
Los documentos XML deben estar bien formados y ser viilidos. Un documento
est6 bien formado si todas las marcas de apertura cuentan con sus respectivas marcas de cierre, todos 10s atributos se introducen entre comillas dobles y el documento cuenta con un solo elemento raiz en el que estan incluidos todos 10s demas. El
fragment0 anterior, por ejemplo, es un documento bien formado, por lo que un
analizador XML podria leerlo y extraer datos sin mayores problemas. fistas son
normas del propio lenguaje XML y que, por tanto, debe cumplir cualquier documento XML.
Que un documento XML sea o no viilido dependerii, primero, de que este bien
formado y, segundo, que su estructura concuerde con la definida en una DTD o esquema XSD. Estos elementos, las DTD y 10s esquemas XSD, se utilizan para validar documentos XML y verificar que son apropiados para la aplicaci6n que debe
procesarlos.
A pesar de que a partir del contenido de un documento XML, como el mostrado en el punto anterior, es relativamente fiicil deducir su estructura, si deseamos
estar seguros de que 10s datos introducidos tienen 10s tipos adecuados y que la estructura es siempre la correcta, tendremos que servirnos de un documento de definici6n de tipos, conocido como DTD, o bien un esquema XSD.
Una DTD es un documento, no basado en XML, en el que se describe la estructura de 10s elementos de un documento XML, asi como su tipo, si bien en este aspecto las limitaciones son bastante importantes. Un ejemplo de DTD, definiendo una
estructura similar a la del documento XML previo, seria el siguiente:
<!ELEMENT L i b r e r i a ( L i b r o s , E d i t o r i a l e s ) >
< ! E L E M E N T L i b r o s (Libra+)>
< ! E:LEMENT L i h r o ( I D L i b r o , ISBN, T i t - i r l o , A u t o r , E d i t o r i a l ,
<:!f<LEMENT I D L i b r r ,
( # P C D A T A ) :'
< ! ELEI'IENT 1 S H N j #PCDATA)>
I!ELEMF:NT T I t i i l o ( # P C D A T A ) >
<!ELEMENT P l ~ t o r(#PCDA'I'A)>
<'ELEMENT E d i t o r i a l [ #PCbA?'Ai >
<!ELEMENT P r e c i o (#PCDATAj>
c ! ELEMENT E d i t c r i a 1es ( E \ J i t (c,ria It ) >
< ! KLEMENT E d I t (3r i a 1 ( I DEdi t o r i a 1, Norrtbr e , D i L e c c i o r l j >
<!ELEMENT I D E d i t o r i a l ( # P C D A T A ) >
< ! ELEMENT Nc-,mbrc ( # P C D A T A ) >
< !ELEMENT Direction ( # P C D A T A ) >
P r e c i o )>
Esta definici6n puede colocarse a1 inicio del propio documento XML o bien almacenarse separadamente, en un archivo con extensi6n d t d , haciendose referencia a el desde el documento XML mediante la marca < ! DOCTYPE>.El inconveniente
de las DTD es que no siguen la sintaxis propia de XML y no son demasiado flexibles, por ejemplo a1 no contar con tipos de datos mas especificos ya que en #PCDATA
entra cualquier secuencia de caracteres, sin importar cuiiles Sean ni su longitud.
www.detodoprogramacion.com
11. X M L
Visual Studio .NET, a1 producir nuevos documentos XML, emplea por defect0
el U R L h t t p : / / t e m p u r i . o r g asociado a 10s ambitos con nombre. Este URL
debe modificarse por uno que identifique de manera unica a ese Ambito, generalmente con el nombre de dominio de nuestra empresa y algun identificador
adicional, dando lugar a un URI unico.
A pesar de que 10s documentos XML, y 10s esquemas XSD, son relativamente
fdciles de comprender y pueden ser editados manualmente, incluso con herramientas tan sencillas como el Bloc de notas de Windows, lo cierto es que estin pensados
para que Sean aplicaciones a medida las que 10s manipulen. Estas aplicaciones
podrian, ya que son archivos de texto simples, leerlos e intentar analizarlos por si
mismas, per0 no es necesario gracias a la existencia de estandares como DOM y
SAX.
SAX, como su propio nombre indica, es un conjunto simple de funciones que
facilitan la extracci6n de datos a partir de un documento XML generando eventos
a medida que lo lee, de tal forma que la aplicacibn, en cierta forma, es participe del
analisis del documento. DOM es una alternativa m i s compleja, si bien tambidn
mas flexible, que recupera un documento completo y nos ofrece la posibilidad de
navegar por sus nodos, leyendo y modificando informacion. Para ello, a partir de
la informacih leida del documento se genera un irbol jerirquico con todos 10s
elementos.
En Visual Basic .NET, afortunadamente, no tenemos por qu6 utilizar mdtodos
de relativo bajo nivel para operar sobre documentos XML, aunque realmente nada
nos impide hacerlo. Por una parte disponemos de la clase X m l R e a d e r que, de
www.detodoprogramacion.com
www.detodoprogramacion.com
11. X M L
Desde Visual Basic .NET puede utilizar XSLT a traves de la clase XslTransform,aplicando una hoja de estilo XSL a cualquier documento XML que tenga alojado en un XmlDocument, o derivado, para el que exista un XPathNavigator.
Svstem .Xml.Schema
XmlSchema
XmlSerializer
II
Svstem.Xml
XmlDocumen t
XmlDataDocument
XmlReade r
XmlElement
XmlNode
XmlWri ter
XslTransfo m
XPathNavigator
II
Microsoft.Xml.XPath
proveedores ADO.NET, si bien sus metodos y propiedades son otros. Este metodo
para acceder a un documento XML seria similar a1 us0 de SAX, per0 en lugar de
responder a eventos que se generan a medida que se encuentran 10s diversos elementos, como ocurre con SAX, disponemos de un cursor solo de lectura y unidireccional, so10 puede avanzar, para recuperar esos elementos.
En la figura 11.3 puede ver la clase XmlReader y sus derivadas, asi como la
interfaz que implementan dos de ellas y cuyo objetivo es facilitar informacion de
posicih de 10s elementos en el documento. XmlTextReader es el medio mds
rdpido para leer un documento XML, a1 no efectuarse validacion alguna respecto a
una DTD o esquema XSD. Estas funciones si las tiene XmlValidatingReader.
Object
41
XmlReader
XmlTextReader
t
IXmlLineInfo
XmlValidatingReader
XmlNodeReader
Figura 11.3. Clases derivadas de X m l R e a d e r
www.detodoprogramacion.com
22. X M L
Module Module1
Sub M a i n ( )
D i m L e c t c r As New XmlTextReader("Libros.xrn1")
While L e c t c r . h e a d
"
t OI-",
( )
L e c t o r .Name)
. N a r r i e - " L i h r c ~ " Or L e r t
lc.FJritcLinc() '
Then
End I f
End Select
End While
Li
L.C1
End Sub
End Module
validacibn a efectuar y adadiendo el esquema a Schemas o facilitando la informacibn necesaria en XmlResolver para acceder a la DTD.
IC:\P&lctVisuatBasicN~Cap-l
I\LecturaXMLWn\kturaXML.exe
ri
Las clases derivadas de XmlReader est6n dirigidas, tal como indica su propio
nombre, a la lectura de informacibn, per0 en ningdn caso facilitan mecanismos
www.detodoprogramacion.com
11. X M L
X P a thNa vig a b 1 e
XmlDocument
XmlDataDocument
Figura 11.5. La clase XmlDocument y relacionadas
Appendchild
( ) : Afiade
InsertBefore ( ) /InsertAfter ( ) : Inserta un nuevo nodo antes o despu&, respectivamente, del indicado.
( ) : Elimina
Removechild
Replacechild
( ) : Sustituye
s New XmlDocurnent
Dim Nodo As XrnlNode '
I'
[ )
D o c u m e n t o . L o a d ("libros.xml" 1
v
For Each
. D o c u m e n t E l e m ~ n tChildNodes
.
www.detodoprogramacion.com
11. X M L
Titulo
Precio
=
=
Nodo.ChildNodes(2).InnerText
Nodo.ChildNodesi5).InnerText
l l r 5 i ->
Nodo.ChildNodes(5).InnerText
End If
12r51"r
Precio
Next
1
I_
End Sub
End Module
www.detodoprogramacion.com
www.detodoprogramacion.com
( )
Dim R e s u l t a d o As X P a t h N n d e I t e r a t o r =
N a v e g a d o r . Select ( " / I , i b r ' r / L i b r o [ E d i t o r i a l = l ]/ T I t u l o " )
~
CrL f , Re c u 1t a d o . C o u n t 1
teLi
While R e ; u l t a d o . M c v e N e X t i )
Con sole . Writ e L i r ~ ie" i 0 J " , Rei 1 1 1t 41,.
C u r r e r l t . Va 1ue )
End While
End Sub
End Module
__
__
-I_^_
__- -
--
11. X M L
cuenta con sentencias condicionales y de repeticibn, como 10s lenguajes de programaci6n. El documento mostrado a continuaci6n es una plantilla XSLT para transformaci6n de documentos, concretamente para generar una tabla HTML con el
nombre y precio de 10s libros del documento XML de ejemplos previos:
Las dos primeras lineas son las que identifican a1 documento como una plantilla XSLT u hoja de estilo XSL. Todas las instrucciones XSLT van precedidas con el
prefijo xsl, como puede apreciarse. La marca <template> aplica la plantilla que
hay a continuaci6n, hasta la etiqueta de cierre </template>,a todos 10s datos del
documento, ya que la expresi6n XPath del atributo match selecciona todo su contenido. A continuaci6n encontramos marcas HTML corrientes para la creaci6n de
una tabla. La etiqueta <for-each> es equivalente a un bucle For/Next de Visual
Basic, repitiendose tantas veces como elementos Libro existan en la rama Libros. Ya sabe que esta expresion puede cambiarla para seleccionar cualquier otro
conjunto de datos, por ejemplo 10s titulos de una cierta editorial, segun se vio antes. Finalmente, en el interior de las celdillas de la tabla HTML se introduce el valor de dos elementos de cada libro, leidos con <value-of>.
Aunque podriamos asociar esta plantilla de transformacibn directamente a1
documento XML, viendo el resultado en Internet Explorer dado que este es capaz
de analizar y ejecutar la transformacibn, lo que nos interesa es ver como podemos
hacerlo desde un programa propio. El unico elemento adicional que precisamos,
aparte de 10s que ya conocemos, es la clase XslTransform. Esta deriva directamente de O b j ect y no implementa interfaz alguna. El metodo de mayor inter& es
Trans form ( ) ,encargado de aplicar la transformaci6n a1 documento. Previamente, sin embargo, es precis0 recuperar la plantilla XSLT mediante el metodo Load ( ) ,
equivalente a1 hom6nimo de la clase Xml D o cument.
www.detodoprogramacion.com
End Module
Las clases que acabamos de conocer tienen utilidad por si mismas, ya que hacen posible la lectura y manipulaci6n de documentos XML desde cualquier aplicaci6n desarrollada con Visual Basic .NET, sin importar su finalidad. Muchas de las
operaciones descritas, no obstante, encuentran su mayor aplicaci6n en nuestro caso, centrados en el tema de acceso a datos, a1 sincronizar un documento XML con
un DataSet o viceversa.
Suponga que ha creado un DataSet,mediante 10s adaptadores de datos adecuados, y tras tener 10s DataTable con las filas de datos quiere obtener s610 aquellas
que cumplan una cierta condicibn, o bien generar una pdgina HTML a partir del
www.detodoprogramacion.com
11. X M L
DataSet para su presentacion a traves de la Web. Podriamos usar vistas, consultas SQL y generar 10s documentos mediante ASF'.NET pero, en ciertos casos, el us0
de XPath o XSLT pueden ser mejores opciones.
El caso inverso tambien puede darse. Podemos obtener un documento XML
desde una aplicacion externa, por ejemplo a traves de Internet, y, mediante la sincronizacion con un DataSet, manipular su contenido como si se tratase de un
conjunto de tablas de datos.
&rihiio
Edcian
yer
Faioitos
!erramentar
a/&
Burqueda
Fa,
I
_
IL--------LItO
___-
~~~
1____
HPC
_ _ _ ~
Segun se aprecia en la figura 11.5, Xml DataDo cument es una clase derivada de
XmlDocument por lo que, en principio, ya contamos con todos 10s miembros de
&a y sabemos, bfisicamente, como recuperar un documento XML y recorrerlo. A
10s miembros heredados, XmlDataDocument afiade un propiedad, DataSet, y
algunos metodos, como GetElementFromRow ( ) o GetRowFromElement ( ) , que
facilitan la obtencion de un elemento XML perteneciente a una cierta fila del Dataset o viceversa. El constructor de la clase tambien puede tomar como parfimetro
un Data S et, crefindose la vinculacion entre conjunto de datos y documento XML
de manera inmediata.
www.detodoprogramacion.com
Vamos a ver 10s dos procedimientos con un breve ejemplo en 10s dos puntos siguientes.
Module Module1
Sub M a i n ( )
D i m Docurnento As New X r n l D a t a D o c u r n e n t i D a t o s )
.r
Datos. E n f o r c e C o n s t r a i n t s
False
www.detodoprogramacion.com
11. XML
D i m Tabla As DataTable
D i m F i l a As DataRow, c o l u r n n a As D a t a C o l u r n n
End Sub
End Module
Tras crear el Data S e t vacio, recuperamos la informacih de esquema del archivo L i b r o s . x s d creado en el tercer capitulo. De no disponer de este archivo tendriamos que obtener la estructura de algun otro modo, ya sea definiendolo mediante
cddigo, porque lo conozcamos de antemano, o bien deduciendolo del contenido
del propio documento XML.
A continuacih creamos el XmlDataDocument.Observe c6mo se pasa a1 constructor el DataSet r e c i h creado. Acto seguido damos a la propiedad EnforceConstraints del DataSet el valor False,ya que durante la lectura del documento,
que se efectua en la sentencia siguiente, las restricciones de las columnas podrian
no ser vdidas y generar excepciones.
Finalmente, se lee el documento XML y muestra por consola el contenido del
DataSet.El resultado serd similar a1 de la figura 11.10. En vez de escribir 10s datos, como en este ejemplo, podriamos modificar, insertar, aiiadir, etc., y despues
devolver la informacih a1 documento XML con el metodo Save ( ) de la clase
XmlDataDocument.
-~
Este proceso es acin mfis simple si cabe, ya que basta con crear el XmlDataDocument vinculado a1 DataSet,entregando este como argument0 a1 constructor
del primero, para tener autom6ticamente el documento XML que representa a1
contenido del conjunto de datos. LPara que puede servirnos esto? Como se decia
antes, podemos efectuar seleccionados de datos XPath sobre un DataSet, o aplicar una transformacih a 10s datos para generar un nuevo documento. Son posibilidades que ha conocido brevemente en puntos anteriores.
www.detodoprogramacion.com
System.Xm1
System.Xml.XPath
System. Data
System.Data.SqlC1ient
Module Module1
Sub Main()
'
Jr!il;il;lG.,:
li;!a
cznl;.XIL7li
D i m Conexion As N e w SqlConnection(
I
,-.
- ,j,, ..., l , , L % s .
:
1 p3t_.s::.it
D i m Datos As N e w DataSet("MisDatos")
I._i
www.detodoprogramacion.com
"
& -
11. X M L
Dlm N a v e g a d )r As XPathNavlgatoL
Dacumeritr X r e a t e N a v i g a t o r [ )
Di
~
[ E j i t o r i d 1= 1 ]
Console.WriteLine("Hay { O } t i t u l h s "
&
/ T 1t ul o " 1
vbCrLf, Resultado.Count)
E n d While
E n d Sub
E n d Module
remoto. En casos asi el conjunto de datos se convierte en XML para ser transmitido
por la red, invirtihdose el proceso en el destino.
www.detodoprogramacion.com
11. X M L
www.detodoprogramacion.com
www.detodoprogramacion.com
www.detodoprogramacion.com
Los capitulos de la segunda parte, que acaba de finalizar, le han servido para
conocer un gran numero de clases de ADO.NET, aprendiendo a utilizarlas en el
codigo de sus programas sin recurrir a asistente o herramienta de diseiio alguna.
Saber qu4 clases son las que se emplean y c6mo funcionan es importante, cuando
surgen problemas imprescindible para resolverlos, per0 tambien es cierto que las
herramientas de disefio de Visual Studio .NET pueden ahorrarnos gran parte del
trabajo que, hasta ahora, ha efectuando escribiendo c6digo.
El objetivo de esta tercera parte del libro es mostrarle c6mo usar el entorno de
Visual Studio .NET, del cual forma parte Visual Basic .NET, para definir conexih,
crear conjuntos de datos con comprobaci6n de tipos, generar adaptadores de datos, acceder a la informaci6n desde el propio entorno, etc. Ser6 el tema de 4ste y
10s pr6ximos tres capitulos.
Las posibilidades o capacidades que encontraremos en el entorno, relativas a1
trabajo con datos, ser6n unas u otras dependiendo de la edicion con la que contemos. Ese ser6 el aspect0 que tratemos en este capitulo, de tal forma que sepa cu6les de 10s elementos explicados en 10s capitulos siguientes tiene o no a su disposici6n.
Como probablemente sabr6, Visual Basic .NET es un product0 que puede adquirirse por separado en su propia caja, y en cualquier comercio especializado, o
www.detodoprogramacion.com
bien como parte de una suscripcion a alguna de las ediciones de Visual Studio .NET,
que es lo m & habitual. A pesar de corresponder todos 10s productos a una misma
version, la primera de Visual Studio .NET presentada en febrero de 2002, existen
varias ediciones distintas. Todas ellas comparten un mismo entorno, la plataforma
.NET y la misma biblioteca de clases, per0 difieren en ciertas caracteristicas como
10s servidores integrados en el paquete o la funcionalidad de ciertos elementos de
diseiio. Visual Basic .NET, como lenguaje, podemos encontrarlo en una de las ediciones siguientes:
Visual Basic .NET Standard: Es la edicion m6s simple y unica que puede adquirirse sin una suscripcion de servicio. Incluye el entorno de Visual Studio
.NET per0 solo con 10s diseiiadores y elementos de Visual Basic .NET.
Visual Studio .NET Professional: Aparte de Visual Basic .NET, tambikn incluye 10s lenguajes Visual C# .NET, Visual C++ .NET y Visual J# .NET, asi como
capacidades inexistentes en la edicion anterior: Crystal Reports, herramientas visuales de bases de datos, herramientas de diseiio para el servidor que
facilitan el acceso a servicios, bases de datos, etc. Puede obtenerse una version de prueba de esta edicion, limitada a 60 dias, solicitiindola en la Web de
Microsoft.
Visual Studio .NET Enterprise Developer: Seguramente la edicion m6s apropiada para el desarrollo de aplicaciones con necesidades de acceso a bases
de datos, ya que incorpora todas las herramientas de diseiio necesarias y algunos servidores fundamentales, como SQL Server, donde la anterior solo
facilita MSDE. Tambikn se diferencia de la anterior en la incorporation de
Visual Sourcesafe, Visual Studio Analyzer y Application Center Test.
Visual Studio .NET Enterprise Architect: Es la edicion superior del producto,
en la que, aparte de todo lo indicado en la anterior, encontraremos una version especifica de Visio para el modelado de bases de datos y aplicaciones y
el producto Microsoft BizTalk Server para la construccion de procesos de integracion con aplicaciones de clientes, proveedores o socios.
Adem6s de &as, que podriamos calificar de ediciones comerciales, tambien
existe un Visual Studio .NET Academia dirigido a estudiantes y profesores. Sus caracteristicas son similares a las de la edici6n Professional, si bien incorpora algunos
elementos adicionales y especificos para la audiencia a la que se dirige.
Puede encontrar una comparativa completa entre las tres ediciones de Visual
Studio .NET, asi como enlaces a comparativas individuales entre Visual Studio
.NET y las ediciones Standard de 10s lenguajes, en http: //msdn.microsoft.com/vstudio/howtobuy/choosing.asp.
www.detodoprogramacion.com
MlCmsofr
Visual
Basicnet
Standard
Figura 12.1. Caja de Visual Basic .NET Standard
Algunas ediciones de Visual Studio .NET ofrecen, aparte del propio entorno de
diseiio, 10s compiladores y la plataforma .NET, otros productos que podriamos
necesitar para el desarrollo, comprobaci6n y depuraci6n de nuestros proyectos.
En el campo que nos interesa especialmente, el de tratamiento de datos, esos productos son MSDE, Microsoft SQL Server 2000 y Microsoft Visio.
Con la edici6n m6s baja, la Professional, disponemos de MSDE que, como se indic6 en su momento, es, bisicamente, el motor de SQL Server per0 sin herramientas de administraci6n y capacidades reducidas en cuanto a numero de conexiones
y tamafio de las bases de datos. El us0 de MSDE, respecto a productos como Microsoft Access, es que estaremos empleando el controlador S qlC1i e n t y todas las
posibilidades de SQL Server, aunque con MSDE. Evolucionar, cuando las necesidades lo requieran, a SQL Server ser6 mucho m i s ficil.
Las ediciones Enteprise, tanto Developer como Architect, vienen acompaiiadas de
varios servidores de Microsoft, entre ellos SQL Server 2000. La licencia del producto nos permite utilizarlo durante el desarrollo y comprobaci6n, no en explotaci6n.
En cualquier caso, es una buena posibilidad ya que podemos operar sobre uno de
10s RDBMS mds potentes y populares.
Finalmente, la edici6n Enterprise Architect tambien se entrega junto a la edici6n
hom6nima de Microsoft Visio, un product0 que nos permitird usar tecnicas de modelado basadas en est6ndares para construir nuestros modelos de bases de datos y
negocio.
Para facilitar el trabajo con bases de datos, en el sentido m i s amplio de la palabra, Visual Studio .NET integra una serie de herramientas que son conocidas genericamente como Visual Database Tools. La mayor parte de ellas son accesibles desde
el Explorador de servidores que, como puede verse en la figura 12.3, nos permite
definir conexiones con origenes de datos y acceder directamente a estos, asi como
conectar con servidores para ver qu6 servicios tienen disponibles.
www.detodoprogramacion.com
insplron pubs.dbo2
17 CS-SRS(MDSYS)
0
MDDICWER (MDSYS)
0 OGIS-SPATIAL-REFEFENCE-SYSTEMS
17 ME-PROYYINFO
+
(MDSYS)
[MTSSYS)
0 DEPT
0
0
EDITORIALES
EMp
0 LIBROS
+
+
0 RECEIPT
0 SALGRADE
r
b Sinonimos
ntos almacenados
E# Caias de mensajes
UContadores de rendmiento
RegistTas de eventor
- @W
a d w & serndores
1 f f Cuadro
___
___
dc heiramtentas
Dependiendo de la edici6n de Visual Studio .NET con que contemos, las capacidades de estas herramientas visuales serin unas u otras. Resumidamente podriamos decir que:
0
En las ediciones Standard podemos explorar las conexiones para ver el contenido de las tablas de bases de datos Access y MSDE.
La edici6n Professional tambien nos permite explorar servidores SQL Server
y cualquier origen con un controlador ODCB u OLE DB, asi como diseiiar tablas y vistas sobre MSDE.
Las dos ediciones Enterprise permiten explorar cualquier servidor para el
que exista un controlador OLE DB u ODBC, asi como SQL Server de forma
nativa. Tambien facilitan el diseiio de tablas, procedimientos almacenados,
vistas, desencadenadores y, en general, cualquier elemento que pueda existir en un RDBMS como SQL Server u Oracle.
www.detodoprogramacion.com
I
Asumiendo que estamos trabajando con una de las ediciones Enterprise de Visual Studio .NET, en 10s capitulos siguientes se abordard el us0 de las herramientas visuales de datos y muchos de 10s componentes que pueden vincularse con un
D a t a S e t, D a t a V i e w 0 similar para facilitar la presentaci6n y manipulacih por
parte del usuario final. Los puntos siguientes le ofrecen una visi6n general de 10s
temas que podri encontrar en dichos capitulos:
Us0 del Explorador de servidores para definir una conexi6n y acceder a 10s
elementos de un origen de datos.
de datos, ahora se genera de forma automQtica,de tal forma que tan s610 tenemos
que usar 10s componentes creados mediante operaciones de arrastrar y soltar.
esurnen
Con este breve capitulo se han situado, en cuanto a caracteristicas de acceso a
datos se refiere, las diferentes capacidades de las ediciones existentes de Visual
Studio .NET. Ahora ya sabe lo que podr6 hacer, o no, segun la edicidn que tenga
instalada en su sistema.
Tambien se han avanzado, en una visidn rQpida, algunos de 10s temas que se
van a tratar en 10s capitulos de esta tercera parte del libro, a partir del capitulo siguiente.
www.detodoprogramacion.com
www.detodoprogramacion.com
En 10s ejemplos desarrollados en 10s capitulos de la segunda parte hemos conectad0 con diferentes origenes de datos, recuperado informaci6n mediante objetos
DataReader, ejecutado comandos, llenado DataSe t con informaci6n de esos origenes a traves de adaptadores de datos, generado automAticamente 10s comandos
de actualizacibn, etc. Todas esas acciones las hemos implementado escribiendo c6digo, lo cual nos ha servido para conocer muchos de 10s detalles de las clases implicadas, sabiendo c6mo emplearlas sin necesidad de asistentes ni un entorno de
disefio.
No obstante, ese entorno de disefio existe en Visual Studio .NET, y podemos
aprovecharlo con el fin de ahorrar una cantidad importante de trabajo, produciendo automiiticamente, mediante operaciones de arrastrar y soltar, 10s componentes
que son necesarios para comunicarse con un origen de datos, extraer y devolver
informaci6n.
El objetivo de este capitulo es mostrarle c6mo puede servirse de esas herramientas de disefio para efectuar tareas como la edici6n directa de datos, definici6n de
estructuras y otros elementos, creaci6n automiitica de componentes de conexibn,
adaptadores y conjuntos de datos, etc.
Tal y como podrii observar, el contenido de este capitulo es mucho menos te6rico que el de 10s capitulos de la segunda parte y va a indicarle directamente c6mo
efectuar cada tarea, por lo que es casi imprescindible que se encuentre delante de
su ordenador con Visual Studio .NET abierto para poder ir siguiendo las explicaciones.
www.detodoprogramacion.com
www.detodoprogramacion.com
vinculo de datos, mostrado en la figura 13.3, que ya conoce por haberlo usado en
capitulos previos, concretamente a1 tratar 10s archivos UDL. Seleccione el proveedor OLE DB que desea utilizar e introduzca 10s datos necesarios para identificar el
origen de datos y facilitar cualquier parimetro adicional que pudiera necesitarse.
onemnes de datos
e mensaws
+
+
@j
Regirbos de eientos
% Servlclor
I.
+
+
Serviuos de Crystal
If
1
----
www.detodoprogramacion.com
El nombre con el que aparecerd la nueva conexi6n, en el Explorador de servidores, ser6 una combinaci6n del identificador de servicio y el nombre del usuario,
como se aprecia en la figura 13.4. A1 desplegarla ya tenemos acceso a todo el contenido de la base de datos desde el propio entdrno de Visual Studio .NET, sin necesidad de usar el software cliente de Oracle.
Usando el menu emergente asociado a una conexion, tras crearla, podra tanto
modificar sus parametros como eliminarla, en caso de que ya no le sirva.
www.detodoprogramacion.com
+
+
+
+
+
& smonimos
i& v1stas
Procedtmientos ahacenados
+
b Funomes
+
Espafieoones del paquete
+
@ Cuerpos de paquete
Servidores
@ dimension
+ & Colas de mensajes
+
Contadores de rendimiento
+ @, Regirbos de eientos
+
Sermos
+
f.Sermos de Crystal
+
9 Sei.idores SQL Server
a
%
Figura 13.4. Al desplegar la conexion aparece una lista de carpetas con objetos
existentes en el origen de datos
Si el origen de datos sobre el que vamos a trabajar es SQL Server, no necesitamos definir una conexi6n para acceder a 61. Los servidores SQL Server aparecen
como elementos en el nodo Servidores SQL Server del equipo donde se encuentren. Si tenemos nuestro servidor ejecutandose en el mismo equipo donde estamos
usando Visual Studio .NET, no tenemos m6s que desplegar dicho nodo para acceder a las bases de datos. En caso contrario, si SQL Server se encuentra en una maquina distinta, tendremos que registrarla como un nuevo servidor.
El proceso es realmente sencillo: haga clic con el boton secundario del raton
sobre el elemento Servidores del Explorador de servidores y elija la opci6nAgregar
servidor. En la ventana que aparece, similar a la mostrada en la figura 13.5, simplemente introduzca el nombre de la maquina 0, si lo prefiere y la conoce, directamente su direcci6n IP. A partir de ese momento, siempre que en dicha otra maquina
tenga las credenciales apropiadas, podr6 operar sobre el nuevo servidor de forma
remota, aunque se encuentre a miles de kil6metros.
En mi configuraci6n particular, Visual Studio .NET se ejecuta en un ordenador
llamado Dimension, mientras que SQL Server lo hace en otro llamado Inspiron. Por
ello, para usar desde Visual Studio .NET las posibilidades de diseiio que me ofrece
el Explorador de servidores, he de registrar lnspiron como servidor adicional. Hecho esto tengo un acceso completo al servidor SQL Server que se encuentra en esa
otra maquina, segun puede verse en la figura 13.6. En ella se aprecia c6mo se ha
conectado con el servidor y desplegado la base de datos L i b r o s , en la que aparecen varias carpetas.
www.detodoprogramacion.com
Ep$o
&e
& senidor
r@ Conemones de dabs
+
f*
LlbrOS.SC0Tr
0 Servidwes
as de base de datos
dmentor almacenados
Figura 13.6. Acceso desde Visual Studio .NET a un servidor SQL Server que se ejecuta
en otra maquina
~ l _ ~ l _ _ ( ~ l _ _ _ l _ . ~ - ~ ~ . - l _ l l _ _
L-.-_^_(
nexi6n mediante OLE DB, es necesario establecer una conexi6n. Esta se abre, normalmente, de forma automdtica cuando es necesario, por ejemplo a1 ir a acceder a
las tablas de una base de datos. Dependiendo de las operaciones que efectuemos,
esa conexi6n se mantendr6 abierta durante mds o menos tiempo.
iC6mo saber si una cierta conexi6n est6 o no abierta? Tan s610 tiene que fijarse
en el icono que precede a1 nombre de la conexibn, o la base de datos en caso de SQL
Server. Si dicho icono tiene en la parte inferior derecha un pequeiio enchufe es que
hay abierta una conexi6n. En caso de que lo que aparezca sea una cruz en rojo, no
hay conexi6n activa. En la figura 13.7 puede observar, ampliado, un detalle de dicho icono, con una conexi6n activa, a la izquierda, y cerrada, a la derecha.
Para cerrar una conexi6n explicitamente, cuando le interese, no tiene mds que
abrir el menu emergente de la conexi6n y seleccionar la opci6n Cerrar conexion.
__I I ____
- ___-
Conemones de datos
La integraci6n de Visual Studio .NET con SQL Server es superior a la que tiene
con el resto de origenes de datos, existiendo opciones especificas para este RDBMS
que nos estdn disponibles para 10s demas. Una de esas opciones es la que nos permite crear una nueva base de datos desde el propio Visual Studio .NET, sin necesidad de recurrir a1 Administrador corporativo. Puede hacerse de dos maneras:
1. Seleccionando la opci6n Crear nueva base de datos SQL Server del menu
emergente asociado a1 elemento Conexiones de datos, en la ventana Explorador de servidores.
2. Seleccionando la opci6n Nueva base de datos del menu emergente asociado
a una instancia de servidor de SQL Server, como se aprecia en la figura 13.8.
Conexiones de dams
dimenson
Inrpron
Contadores de rendimiento
Reqissos de evenbs
+
f* Serviaos de Crvstal
19 Seruidorer SQl Server
IB
Propedades
Figura 13.8. Opcion para crear una nueva base de datos SQL Server
A partir de la creacih, la nueva base de datos queda en el Explorador de servidores como una nueva conexi6n o una nueva base de datos, segtin el caso, tratindose desde ese momento como cualquier otro de 10s elementos que ya existiesen
con anterioridad. Los procesos descritos en 10s puntos previos, por tanto, son aplicables de manera indistinta.
Durante el desarrollo de una aplicaci6n es habitual la necesidad de editar directamente 10s datos alojados en el origen, ya sea para preparar un bloque de datos
de prueba, simular posibles fallos o corregir 10s que pudieran generarse. En cualquier caso, casi siempre se recurre a una herramienta especifica del origen para efectuar ese trabajo. Asi lo hicimos en el tercer capitulo, a1 emplear Microsoft Access
para introducir informaci6n en una base de datos Access o las herramientas de administracibn de SQL Server y Oracle para hacer lo propio sobre esos RDBMS.
En realidad, una vez definida la estructura de la base de datos, no necesitibamos emplear ninguna de esas herramientas para editar la informacih puesto que,
como va a ver de inmediato, es algo que puede hacerse directamente desde el entorno de Visual Studio .NET. En realidad, tampoco para definir la estructura precisamos m i s que este entorno si tenemos una de las ediciones superiores de Visual
Studio .NET.
Si tiene acceso a un servidor SQL Server, registre el equipo en la rama Servidores del Explorador de servidores, despliegue el servidor de datos y seleccione, de
www.detodoprogramacion.com
la carpeta Tablas de la base de datos que prefiera, una tabla cualquiera, haciendo
doble clic sobre ella. Si el origen de datos no es SQL Server primer0 tendri que definir una conexih, s e g ~ n
10s pasos explicados antes, tras lo cual el proceso seria
idhtico.
Tras hacer doble clic, y siempre que la conexi6n con el origen sea satisfactoria,
veri aparecer en el entorno de Visual Studio .NET una cuadricula con 10s datos actuales de la tabla, siendo posible la eliminacihn, modificaci6n e insercidn de datos.
En la figura 13.9 puede ver como se editan dos tablas de manera simultinea. La de
la parte superior corresponde a una base de datos de ejemplo instalada con Oracle
8i, mientras que la inferior es la tabla L i b r o s que creamos con Microsoft Excel en
10s ejemplos del tercer capitulo. En ambos casos se ha definido una conexion mediante el proveedor OLE DB.
CESS C VBddviwaiBaxNEl
I
$VStaS
@ Procedimientor aimacenado
)biibroi5cm
+
hagramas de bare de datw
ACCOUhTNG
NEW YORK
SALES
OPERATIOFIS
CHICAGO
BOSTCA
I1
I
+
+
+
+
BONUS
c ] D m
EDIIORIKES
MP
LlBRO
10.75
10.71
39
n
-
.10
39
10.75
10 52
37.24
10.52
21.04
10.52
1U,52
24,04
LlBROS
RECEIPT
.10
Observe que siempre que defina una conexion utilizando el proveedor Microsoft
JET, por ejemplo para acceder al libro de Excel en este caso, en el Explorador
de servidores siempre aparece el prefijo ACCESS. Si se fija, no obstante, Vera
que el nombre del archivo es L i b r o s . x l s y no L i b r o s . m d b .
www.detodoprogramacion.com
~._____II_
x l_
_
__..____-....
---I.____.____._-.-..-.----
A1 abrir una tabla con el sistema anterior, haciendo doble clic sobre ella, obtendremos todo el contenido, lo cual puede significar tan s610 unas decenas de filas,
como ocurre con la base de datos creada a mod0 de ejemplo para este libro, o bien
miles de ellas, en caso de que conectemos con una base de datos en explotaci6n
real u obtenida como copia de una que se encuentre en explotacih.
Usando las habituales teclas de desplazamiento del cursor, o bien el puntero
del rat6n para actuar sobre la barra de desplazamiento, nos podremos desplazar
de un punto a otro fila a fila. Tambikn pueden emplearse ciertas combinaciones,
como Control-Inicio y Control-Fin, para ir ripidamente a la primera de las filas o a
la ultima, respectivamente.
Para insertar una nueva fila no tenemos mAs que desplazarnos debajo de la u1tima que tiene datos, apareciendo automiticamente una fila vacia en la que podemos introducir 10s nuevos datos. De forma similar, podemos modificar el contenido
de cualquiera de las filas mostradas. Si deseamos eliminar una de ellas tendremos
que seleccionarla completa, haciendo clic en el selector que aparece a la izquierda
de la primera columna, y pulsar a continuacion la tecla Supr.
Debe tener en cuenta que ciertas columnas de datos pueden no ser editables.
No podra, por ejemplo, modificar la columna I D L i b r o de la tabla L i b r o s de
la base de datos SQL Server, puesto que su valor se genera automaticamente.
Si aiiade una nueva fila, el valor de dicha columna sera insertado automaticamente. Tampoco podra editar aquellas columnas cuya precision exceda unos
ciertos limites.
A1 abrir una tabla, como hemos hecho en el punto previo, no s610 aparece una
cuadricula con las filas y columnas de datos sin0 que, ademis, se activa una paleta
de herramientas que por defect0 no esti visible. En ella, segun puede verse en la figura 13.11, existen multiples botones con 10s que podemos ocultar y mostrar distintos paneles, ejecutar una sentencia SQL, afiadir otras tablas, agrupar datos, etc.
www.detodoprogramacion.com
Simplemente situe el punter0 del rat6n sobre cada b o t h para obtener una indicaci6n de su finalidad.
1x
a 4 4 1 5 1136 S
3.1-115 1324 4
Franuaco Charte
R a n o x n Charte
Franuscn Charte/lnrge Seriano
Francisco Charte
Franuzco Charte
Franosco Charte
Franosco Charte
FrancEcn Charte
Franorco Charte
Franosm Chartem Jesus Luque
Franorcn Chatte
Franosco Charte
Chris ti Pappas&WiliiamH Murray, I11
l e f f Duntemann
Oscar Gonzak:
8 W 1 5 1392 9
84415 1376 7
34415-1351-1
34415 1290 6
84415-1B1-1
84-115 1261 2
84 415 12558
84415 1230 2
8.1415 1202 7
84-115-1132-2
84 415 11454
847615 234 5
0-171 37523 3
34415 1402 X
10,75
1
1
10.75
39
w
39
10,75
1
1
1
1
1
1
1
1
1
1
2
nsz
37.26
10.52
21.04
10.52
10,52
24,04
40
m.5
10.75
_
__
k a ~QI -.__-
gavharbpo-
%L
'_
EZ
I)
,%to
de nuevo la consulta
Si no pretendemos editar 10s datos, sin0 simplemente efectuar alguna comprobacidn, posiblemente no necesitemos tener visibles todas las columnas. Puede pulsar
el b o t h Mostrar panel de diagrama, el primer0 contando desde la izquierda, para
abrir un esquema visual en el que se aprecia la relacidn entre ambas tablas y, ademAs, puede marcar y desmarcar las columnas que desea tener visibles. Una alternativa es pulsar el b o t h Mostrar panel SQL y editar directamente la sentencia
SQL que se desea ejecutar. Para ver el resultado, como en el caso anterior, tendri
www.detodoprogramacion.com
que pulsar el b o t h Ejecutar consulta. En la figura 13.14 puede ver el Panel de diagrama, en la parte superior; el Panel SQL, en el drea central, y el Panel de resultados en la secci6n inferior. Ldgicamente, puede afiadir a la consulta SQL cl6usulas
de selecci6n de filas, ordenacibn, agrupamiento, etc.
Otra forma de establecer criterios de selecci6n y ordenaci6n consiste en abrir el
Panel de cuadricula (segundo de 10s botones de la barra) e introducir directamente
las opciones deseadas. En la figura 13.15 se ve c6mo se ha asignado a la columna
N o m b r e de la tabla Editoriales el alias Editorial, titulo que aparece en el panel de resultados. Ademds se ha ordenado ascendentemente por el titulo del libro,
aparte de seleccionarse s61o aquellos cuyo precio esti por debajo de 10s 40 euros.
l@
SELECT
15 1136 5
? $15 13241
4-41: 1392 9
$415 1170 7
1415 1351 1
-!-+I5 1290 6
SQL Server 20
Gum prarbca para USUailOs JBulder 7
Programaoon con lisual C 2 NET
Programaoon con visual Studio NET
Frugrmaoon con visual Basic NET
G m paCbca wra U S U ~ ~ ~de
D SI wal Bavc NET
4115 120 1 2
Frogiamaclon i o n Delphi 6
4 4 1 5 1230 2
? 115 l2n2 7
4-315 11'2 2
4415 1115 4
I7615 23+5
471 37523 3
39
40
39
1G.75
10 52
37 26
10 52
21 04
10 5 2
10 52
2.) 04
40
6iJ 5
m a y a Mulbmeda
Anaya Mulbmedia
Anaw Multimedia
maya Mulbmedia
Anam Mulbmedia
Anaya Mulbmedia
Ana,a Mulbmedia
Anaya Mulemedia
AnajaMulbmcda
Anwa Mulemedia
M a y a Multimedia
McGran+ll
Anma Multimedia
Nota
Si mantiene abierto el Panel SQL, a medida que haga cambios en el Panel de
diagrama y Panel de cuadricula podra ir viendo como se reestructura la sentencia SQL que ejecutara a1 pulsar el boton Ejecutar consulta.
www.detodoprogramacion.com
lReaa
1 8 484415
4 1 5 1132
1202 27
,I
;I
uj
84415 1290 6
84415 12914
84415 13244
84415 1145-4
84415 1230 2
84415 1261 2
84415 1351 1
84415-13924
84415 1136 5
1893115 94 1
NET
SQLferier 2000
User Interface k s g n for Programmers
lEditmd
10.52
10,52
10,52
10 75
10.52
10 75
24,04
21,04
37,Z
39
39
10,75
h y a Mulhmedla
Anaya Mulbmedia
Anaya Mulbrnedra
Anaya Mulbmedia
Anaya Mulbmeh
Anaya Mulbmedia
Anaya Mulbmeda
Anaya Mulbmeha
Anaya Mulbmedia
Anaya Mulbmedia
Anaya Mdbmedia
Anaya Mulbmedia
31
np-ess
A1 abrir una tabla desde Visual Studio .NET, haciendo doble clic sobre ella en el
Explorador de servidores, se genera automiticamente una sentencia SQL de consulta para recuperar todas las filas y columnas de la tabla. Con 10s elementos indicados en el punto previo, 10s distintos paneles inicialmente ocultos, es posible
seleccionar columnas y filas. La sentencia, no obstante, seguir5 siendo de consulta.
Si tras abrir una tabla despliega la lista adjunta a1 b o t h Cambiar tipo, como se
ha hecho en la figura 13.16, podri cambiar la sentencia SQL para que en vez de ser
de consulta sea de inserci6n de resultados, de valores, de actualizacidn o de eliminaci6n. Segun la opci6n que elija, en el Panel SQL veri aparecer una sentencia
I N S E R T INTO, UPDATE 0 DELETE.
A partir del momento en que se modifique el tip0 de sentencia, las acciones que
llevemos a cab0 en 10s paneles de diagrama y cuadricula, eligiendo columnas o
estableciendo criterios de selecci6n de filas, se aplicarin a la nueva sentencia SQL.
Puede hacer pruebas manteniendo abierto el Panel SQL para ver las sentencias gewww.detodoprogramacion.com
neradas, per0 sin llegar a pulsar el b o t h Ejecutar consulta para evitar, por ejemplo, la eliminacih de 10s datos.
I
INTO Editonales
Editonales =
__
Edtoriales
M
I
El resultado obtenido deberia ser similar a1 de la figura 13.17. La primera columna de resultados es el numero de titulos que tiene cada una de las editoriales,
cuyo c6digo aparece en la segunda columna. Puede usar el Panel de cuadricula para asociar alias a estas columnas, asi como para cambiar el orden en que aparecen
en la cuadricula de resultados simplemente arrastrando y soltando.
Nota
Como en 10s demas casos, tambien puede acceder a la consulta SQL y modificarla directamente, prescindiendo de 10s demas paneles de diseAo. Si conoce
el lenguaje SQL muchas veces le resultara mas rapido.
www.detodoprogramacion.com
I
~
_
l
_
I______
"-____I
Para crear una nueva tabla, abra el menu emergente de la carpeta Tablas de la
base de datos sobre la que vaya a trabajar, eligiendo la opcion Nueva tabla. Si lo
que necesita es editar la estructura de una tabla existente, pulse el b o t h secundario sobre ella, en el Explorador de servidores, y elija la opci6n Diseiiar tabla.
En cualquier caso, tanto si la tabla es nueva como si ya existia, se encontrarti
con una interfaz similar a la que emple6 en Microsoft Access o SQL Server, en el
tercer capitulo, para crear las tablas de la base de datos de ejemplo. Una cuadricula donde podri ir introduciendo el nombre de cada columna, su tipo de dato, longitud, etc. En la figura 13.18 puede ver, a la izquierda, la edici6n de la estructura
de la tabla L i b r o s de SQL Server, mientras que a la derecha se esti afiadiendo una
nueva tabla a la base de datos Oracle.
Inicialmente, al crear una nueva tabla, Visual Studio .NET le da un nombre provisional del tipo T a b l a l . Cuando se finaliza el diseiio, y se cierra la ventana,
aparecera una pequefia ventana preguntando si desea crear la tabla y solicitando un nombre definitivo para ella.
A1 igual que ocurria a1 abrir una tabla para edicicin de datos, mientras disefiamos su estructura hace su aparici6n una paleta de botones especifica. Esta, como
se aprecia en la figura 13.19, cuenta con cinco botones cuyo nombre y finalidad, de
izquierda a derecha, son 10s siguientes:
0
Generar secuencia de comandos de carnbio:Finalizado el disefio o modificaci6n de la tabla, a1 pulsar este b o t h se generarti la secuencia de comandos
SQL correspondiente. En principio dicha secuencia aparece en una ventana
(vease figura 13.20) desde la que podemos guardarla en un archivo. Si lo
www.detodoprogramacion.com
desea, puede activar la opci6n Generar automaticamente secuencia de comandos de cambio al guardar para que, sin necesidad de volver a pulsar este
b o t h , se genere autom6ticamente esa secuencia de comandos cuando haya
finalizado el diseiio.
Figura 13.19. Barra de botones especifica para el disefio de la estructura de una tabla
0
&sea
CREATE T
Q u a r k esta Eealerw de c a a n d o s de c d w en tm W
de text02
~ W O
F SCOTT TABLA 1
i
DCUENTA CtlAR(14).
m
A
Q
WAR(Zs),
SMDO rwILER(18,2)
k
ALTERTPleLE SCOTT.TABLA1
MODIFY IDCUENTA wAR(1.I)
C D N W M - T A B L A l NOTNULL;
P T E R TABLE XOTT.TAELA1 Aw C C W 5 R A M
K-TABLA1 PRIMARV CY
Y
Administrar indices y claves: Abre la misma ventana que se muestra en la figura 13.21, per0 con la pigina fndices o claves en primer plano. Desde ella
podrin crearse nuevos indices asociados a la tabla, asi como establecer la
clave principal en caso de que no la hubiesemos fijado previamente con el
b o t h Establecer clave principal. No tiene mis que ir pulsando el b o t h
Nuevo de la pigina fndices o claves para ir aiiadiendo indices, seleccionando 10s nombres de las columnas participantes e introduciendo el nombre que
tendr6 el indice.
www.detodoprogramacion.com
Administrar restricciones Check: El 6ltimo de 10s botones nos lleva a la PAgina Restricciones CHECK de la misma ventana de propiedades (vease figura 13.22), en la que podemos definir restricciones adicionales que pudieramos
necesitar.
Creadas las tablas, tras cerrar las ventanas de disefio y responder afirmativamente a la pregunta de si se desean guardar 10s cambios, podemos editar su contenido
como con cualquier otra tabla.
Figura 13.22. Definirnos una restriccion para evitar que el saldo de la cuenta
pueda ser negativo
Los datos obtenidos a partir de una vista pueden abrirse en Visual Studio .NET
como si de una tabla normal se tratase. Puede desplegar la carpeta Vistas de la base de datos SQL Server u Oracle y hacer doble clic sobre la vista LibrosPorEditorial
que se habia creado como ejemplo en un capitulo previo. Verd que el resultado es
una cuadricula de datos, como la de una tabla, per0 mostrando el resultado de la
consulta que define la vista.
Si abrimos el menu emergente asociado a esa vista, o a cualquier otra, veremos
dos opciones especialmente utiles: Diseiiar vista y Nueva vista. La primera permite modificar la definicion de una vista existente, mientras que la segunda crea una
nueva vista. Recuerde que en el tercer capitulo usdbamos herramientas especificas
para efectuar estas tareas, mientras que ahora lo hacemos todo desde el propio entorno de Visual Studio .NET.
www.detodoprogramacion.com
El disefio de una vista se efectua a traves de 10s paneles de diagrama, cuadricula y SQL que conocimos en el punto dedicado a la edici6n de datos. La diferencia
es que la sentencia SQL resultante ser6 asociada a una vista. Seleccione la vista que
teniamos como ejemplo, abra el menu emergente y luego elija la opci6n DiseAar
vista. Deber6 encontrarse con un entorno como el de la figura 13.23. Ya que la vista
existia, aparecen las tablas que la forman, sus relaciones y selecci6n de columnas y
criterios. Podemos introducir modificaciones en cualquiera de esos apartados, por
ejemplo estableciendo un criterio de selecci6n de filas, y luego cerrar la vista respondiendo afirmativamente a la pregunta de si desea guardarla. Con esto habr6
modificado la vista en el servidor de datos. Usando esos mismos elementos puede
crear una nueva vista. Pruebe a afiadir una vista a las bases de datos existentes para familiarizarse con 10s distintos paneles y la barra de herramientas asociada.
IY
/1
'iklSElEcr
WHERE
NOKBRFAS
Edltorld', LIBROS LO ps Tib;lo;
EDITORIALES, LIBROS
EDITOMALES IDEDmORIAL = LIBROS EDITORIAL
EDITOMALES
1Edlond
I_
friar0
men
- hnaya Mulmmeda
Anaya Mulbmedia
nap
1-
1-
itme medial
Anaya Mulhmedla
Anaya Multmmeda
Anaya Muitmedia
Anaya Mulbmeda
Anaya Multmedla
---.ll.'
LiiKOS P c C f i
-__
--
--
--
[PREUO
- _---__
.-"A-r%h.l.L-
31
10.75
10.75
39
40
39
10,75
10,52
373
________
'DEl-
--
---
I7
i r a Procedimiento almacenado
FJuevo procedimento almacenado
Actualizar
I%
...
Propedades
Las operaciones descritas en este punto son aplicables, igualmente, a las funciones, que pueden crearse, editarse y ejecutarse desde el entorno de Visual
Studio .NET.
www.detodoprogramacion.com
Si utiliza la opcion Nuevo procedimiento almacenado para crear nuevos procedimientos, observara que el esqueleto de codigo que aparece en el editor se
ajusta a la sintaxis propia del RDBMS con el que estemos trabajando. Esto es
asi, al menos, con SQL Server y Oracle.
Ahora que ya sabemos c6mo emplear las herramientas visuales de bases de datos de Visual Studio .NET para preparar, o conocer, la informaci6n sobre la que
vamos a trabajar, el paso siguiente seri aprender a usar 10s componentes de acceso
a datos con que contamos. En realidad, esos componentes ya 10s conocemos, la unica novedad es que en lugar de crearlos mediante cbdigo, como en capitulos previos, usaremos operaciones de arrastrar y soltar y la ventana Propiedades.
Si inicia una aplicaci6n tipica Windows, o para la Web, veri que en la Caja de
herramientas existe una secci6n llamada Datos. En ella aparecen, como se aprecia
en la figura 13.27, 10s componentes OleDbConnection, OleDbDataAdapter,
OleDbCommand y 10s equivalentes para el proveedor SqlClient, asi como 10s
componentes genkricos Da taVi ew y Data Se t.
www.detodoprogramacion.com
UOdbcDataAdapter
mOleDbCommand
OleDbCommandBuilder
~OleobComecbon
mOleDboataAdapter
OpenFileDialog
OOradeCommand
DradeCommandBuilder
mOradeConnecbon
OradeDataAdapter
__
Miaosoft.Data.Odbc (1.0.3300.G)
Svrtem.Data (1.0.3M0.0)
System.Data (1.0.3M0.0)
System.Data (1.0.3M0.0)
Svrtem.Data (1.0.3M0.0)
System.Wmdows.Fams (1.0.330.0)
System.Data.OradeClient (1.0.3330.0)
System.Data.OradeCbent (l.G.3M0.0)
System .Data .OradeClient (1 .0 ,3300 .0)
System .Data .OradeClient (1 .0 ,3330 .0)
.
.--. .
. .
fY
. -.. .
. ...I
I/
!.>I
I/
II
re
Dependiendo del proveedor que desee emplear, haga doble clic sobre el componente Connection adecuado del Cuadro de herramientas, consiguiendo asi su
inserci6n en el m6dulo que tenga abierto en ese instante. Suponiendo que desee
acceder a 10s datos alojados en una base de datos Access o un libro de Excel, haria
entonces doble clic sobre el componente OleDbConnection. Este aparecersi en el
Brea de disefio, en la zona inferior, y sus propiedades estarian visibles en la ventana Propiedades.
La unica propiedad que tendremos que editar sersi Connectionstring, a fin
de facilitar la informaci6n de conexi6n necesaria. Esta propiedad cuenta con una
www.detodoprogramacion.com
El componente Sqlconnection se comporta practicamente de forma identica a OleDbConnection,de tal forma que la propiedad connectionstring
tambien muestra la lista desplegable con la opcion Nueva conexion. Los compOnenteS OracleConnection y OdbcConnection, por el contrario, no disponen de esa lista ni asistente alguno, por lo que la cadena de conexion debe
escribirse directamente como valor de la propiedad Connectionstring.
En la figura 13.29 puede ver c6mo se ha insertado un OleDbConnection en
una aplicaci6n Windows y c6mo, abriendo la lista adjunta a la propiedad Connectionst ring, se elige una de las conexiones predeterminadas, concretamente la
de acceso a1 libro Microsoft Excel.
Si nos interesa, podemos cambiar el nombre del componente por otro m i s adecuado. En este ejemplo mantendremos 10s nombres por defect0 que tienen 10s componentes a1 ser insertados.
Tras la inserci6n del componente de conexibn, y asignaci6n de un valor apropiado a Connectionstring, para abrir la conexidn usariamos el componente como si de una variable previamente declarada se tratase, es decir, como hariamos con
cualquier otro componente en Visual Basic .NET. La sentencia siguiente, por tanto,
usaria el componente insertado en la figura 13.29 para abrir la conexi6n con el libro de Microsoft Excel.
OleDbConnectior~l.
Open (
-~
Con 10s componentes Command, por ejemplo OleDbCommand, prepararemos
10s comandos de selecci6n de datos que precisemos. La unica diferencia es que
ahora el componente se crea a1 insertarlo en el disefiador, creandose automaticamente la variable, y las propiedades del comando se establecen visualmente. Nos
encontraremos, no obstante, con exactamente las mismas propiedades que ya conocimos en capitulos previos, lo unico que cambia es la forma de crear el objeto y
personalizarlo.
Asumiendo que tiene en este momento definida la conexi6n del punto previo,
inserte un OleDbCommand, simplemente haciendo doble clic sobre 61 en el Cuadro
de herramientas, y edite en la ventana Propiedades las propiedades siguientes:
www.detodoprogramacion.com
deherrmentas
OradeDataMaptcr
Si no tiene un componente de conexion, porque no lo haya insertado previamente, puede usar la opcion Nueva de la propiedad Connection para definirla en
ese mismo momento, generandose automaticamente el componente OleDbConnection.
0
CommandType: Esta propiedad tambikn tiene asociada una lista de opciones, de la que puede elegir si el comando recuperar6 directamente una tabla,
contiene una sentencia SQL o el nombre de un procedimiento almacenado.
Mantenemos el valor Text que aparece por defecto, indicando que el comando tendri asociada una sentencia SQL.
www.detodoprogramacion.com
>
A
1
>
nulo Aubr Preoo
>
La ventana Generadorde consultas no aparece, en este caso, como un diseiiador de Visual Studio .NET sin0 como una ventana independiente.
Lbgicamente, podemos definir tantos comandos como necesitemos para efectuar nuestro trabajo. En este caso nos quedaremos s610 con el comando que puede
verse en la figura 13.30, introducido en el componente OleDbCommandl.
Figura 13.31. Asociaciones entre tablas de origen y tablas del conjunto de datos
En el mismo cuadro de dialogo Asignaciones de tablas puede tambien establecer una correspondencia entre las columnas del origen de datos y las que existiran en el conjunto, si es que este cuenta con una estructura predefinida.
s
El penultimo paso, en cuanto a tareas de diseiio se refiere en este simple ejemplo, ser6 la creaci6n del conjunto de datos, para lo cual hacemos doble clic sobre el
elemento DataSet que aparece en el Cuadro de herramientas. Como en el caso del
www.detodoprogramacion.com
ai
Para ver el contenido del Data S et en esta ocasi6n no usaremos la consola, sino
que disefiaremos una sencilla interfaz de usuario. Abra la secci6n Windows Forms
www.detodoprogramacion.com
________
0Wndow
Tw, Left
0Wndow
I
Amworkspace
8
M
FixedD
[z1 AcbveCapbon
AcbveCapbanText
Llsto
www.detodoprogramacion.com
No es mucho codigo, especialmente si lo comparamos con algunos de 10s ejemplos de capitulos previos y el resultado obtenido que, en este caso, seria el de la figura 13.34. Una rejilla en la que podemos navegar por 10s datos.
IntrodLccior a la programion
Marual a.anzado Grcel :W2
F,lawal &I microrrocesador 33386
Programaacn C G Oelph
~
6, K , h
P r o g a r x i o r c w t/lsbal b s i c NET
FraTx-iscu'Itsrte
Farcisco Charte
Frapcisco Charte
Ckris H Pappas&'Allialr H Murra, Ill
Frarcisco Charte
Frarcisco Chide
Frsrcisco Chide
12 52
40
No cabe duda, usando 10s componentes de conexi6n a datos como hemos hecho
en 10s puntos previos, insertandolos en un disefiador y personalizandolos mediante el us0 de la ventana Propiedades, ahorramos una cantidad importante de trabajo respecto a la escritura de c6digo para efectuar todo el proceso. Tan s610 hemos
tenido que escribir una sentencia para conseguir una cuadricula de datos que muestra el resultado de una consulta SQL, sin necesidad de recorrer filas, acceder a columnas y acciones similares mediante c6digo.
No obstante, el trabajo puede simplificarse atin mAs mediante la creaci6n automitica de parte de 10s componentes que, en 10s anteriores puntos, hemos ido insertando y personalizando de manera individual. A continuaci6n vamos a tratar de
obtener el mismo resultado, o similar, con menos pasos y en menor tiempo. Puede
partir de un nuevo proyecto o bien eliminar el c6digo y 10s componentes que insert6 en el ejemplo previo.
elemento OleDbDataAdapter del Cuadro de herramientas para poner ese asistente en marcha.
La primera ventana que aparece es simplemente indicativa, bastando con pulsar el b o t h Siguiente > para ir a1 siguiente paso. En 61 deberemos seleccionar la
conexi6n asociada a1 adaptador, ya sea eligiendo una de las existentes, tal y como
se hace en la figura 13.35, o bien pulsando el b o t h Nueva conexidn para definir
una nueva. En este caso nos encontraremos con el cuadro de di6logo que ya conocemos. Para seguir este ejemplo vamos a optar por la conexi6n Libros . d b o del
servidor en el cual se tenga SQL Server en funcionamiento, en mi caso particular
1NSPIRON.Libros.dbo.
Tras pulsar el b o t h Siguiente > nos encontramos con el apartado Elija un tipo
de consulta. En ella, s e g h se ve en la figura 13.36, podemos elegir entre tres opciones distintas:
Usar instrucciones SQL: Para actualizar 10s datos, en caso de ser necesario,
se emplear6n sentencias SQL del tip0 UPDATE, INSERT o DELETE. Estas se
generarin automiticamente para nosotros a partir de la sentencia de selecci6n que facilitemos en el paso siguiente.
0
Si elegimos una de las dos primeras opciones, en nuestro caso nos quedaremos
con la que aparece seleccionada por defecto, en el paso siguiente tendremos que
introducir la sentencia SQL de seleccion de datos. Si 6sta es compleja, no tan sencilla como la de la figura 13.37, puede pulsar el b o t h Generador de consultas para diseiiar visualmente, utilizando la misma interfaz que ya conoce de ejemplos
anteriores.
Pulsando el b o t h Opciones avanzadas de esta ventana, en la parte inferior izquierda, abrir6 entonces la ventana Opciones d e generacion SQL avanzadas (vease figura 13.38). En ella aparecen tres opciones inicialmente activadas. La primera
provoca que el asistente genere, aparte del comando de seleccibn, comandos adicionales para la insercih, actualizacidn y eliminacih. Con la segunda se conseguir5 que las instrucciones de actualizaci6n y eliminaci6n empleen el mecanismo
conocido como concurrencia optirnista, consistente en asumir que 10s datos no van a
cambiar desde que se recuperan hasta que van a modificarse, no bloqueando el
acceso a ellos. Por ultimo, la tercera opci6n provoca que tras cualquier actualizaci6n se efectue una actualizacih inmediata del conjunto de datos, asegurando asi
que este siempre se mantiene en consonancia con el contenido real del origen de
datos.
www.detodoprogramacion.com
1
o m avanzadas
Genera&
de comultas...
Tras pulsar el b o t h Siguiente > una vez mas, accedera a una ultima ventana de
resumen y confirmacibn. En ella se detallan las acciones elegidas, bastando la pulsaci6n del b o t h Finalizar para cerrar el asistente y concluir el proceso. Si no esti
conforme con algo, aun esta a tiempo de pulsar el b o t h < AtrPs y corregir lo que
desee. A1 finalizar, apareceri en el disefiador el componente OleDbDa taAdapter
y un OleDbConnection.No existen, sin embargo, componentes OleDbCommand,
a1 menos aparentemente. Sin embargo, si examina el c6digo generado por el asistente encontrara las siguientes declaraciones justo antes del mktodo 1 nit i a 1i zeComponent ( ) :
www.detodoprogramacion.com
Friend WithEvents O l e D b S e l e c t C o m m a n d l
System.Data.01eDb.OleDbCornrnand
Friend Wi thEvents 01 e Db I n s e r t C o m m a nd 1
System.Data.01eDb.01eDbCommand
Friend WithEvents OleDbUpdateCornrnandl
System. D a t a . Ole Db. 0 1 e D b C o m m a n d
Friend WithEvents O l e D b D e l e t e C o m m a n d l
S y s t e m . Data. O l e D b . O l e D b C o r n r n a n d
As
As
As
As
Existe, por tanto, un OleDbCommand para s e l e c c h , otro para insercion, un tercero para actualizaci6n y uno mds para eliminaci6n de filas.
Busque m6s adelante la asignaci6n a la propiedad CommandText de cada uno
de 10s OleDbCommand y examine las sentencias SQL, especialmente las utilizadas
para actualizar y eliminar filas existentes.
. "
Puede cambiar la configuracion de un adaptador de datos en cualquier momento, mediante el mismo asistente empleado para crearlo, usando el enlace
Configurar adaptador de datos que aparece en la parte inferior de la ventana
Propiedades mientras tiene seleccionado el adaptador, o bien eligiendo la opcion homonima del menu emergente del OleDbAdapter.
Acabamos de configurar nuestro adaptador de datos que, una vez lo conectemos con un DataSet,suponemos nos facilitar6 la visualizaci6n y edici6n de todas
las filas de la tabla Libros. Esta suposicidn puede convertirse en seguridad de
forma muy sencilla: seleccionando la opci6n Vista previa de datos del menu emergente asociado a1 adaptador.
En principio se encontrard con un cuadro de didlogo en el que aparece el nombre del adaptador de datos, en la parte superior izquierda, y varias Areas vacias en
el resto de la ventana.
Pulse el b o t h Llenar conjunto de datos. De inmediato Vera c6mo aparece el
conjunto de filas resultante, asi como el nombre de las tablas de datos, en este caso
s610 una, y el tamafio global del conjunto de datos. La figura 13.39 muestra la vista
previa del adaptador definido en el punto previo.
Puede cerrar la ventana, volviendo de nuevo a1 entorno de disefio a fin de proceder a la creaci6n del conjunto de datos.
Partiendo del adaptador de datos, que ya tenemos definido y comprobado, generar el Data S e t es un juego de nifios. Bastard con abrir el menu emergente del
www.detodoprogramacion.com
www.detodoprogramacion.com
Aunque en principio parece que tan s610 se ha aiiadido el esquema XSD, si pulsa el b o t h Mostrar todos 10s archivos del Explorador de soluciones verd aparecer,
asimismo, un m6dulo llamado D a t a S e t 1.vb. Abralo y eche un vistazo a su contenido. En el encontrard una clase llamada Data S e t 1 derivada de Data S e t . Esta
clase cuenta conuna propiedad s610 de lectura, llamada L i b r o s , de tip0 L i b r o s D a t a T a b l e , una clase definida mds adelante en la que encontrard objetos DataC o l u m n con nombres que le resultardn familiares, a1 coincidir con 10s nombres de
las columnas de la tabla L i b r o s .
Lo que ha hecho el asistente anterior es generar un conjunto de datos con t i p , una
clase que, derivada de Data Se t, implementa 10s elementos necesarios para facilitar el acceso a las tablas y columnas, asegurando a1 tiempo la validez de 10s tipos.
La existencia de este conjunto de datos con tip0 hace que sentencias como &ta:
DataSetll.Tables(1,ibros) .Rows ( 0 )( E d i t o r i a l ) = 3
Los conjuntos de datos con tip0 evitan ciertos errores, como la asignacion de
valores de tipos incorrectos, produciendo 10s avisos durante la compilacion,
cuando es facil corregirlos, en lugar de en ejecucion.
....
.-
-"_
".-.l_l___.~.-^".-ll_---~..~-~~
_____l___~~~.l__
___-_^_
En 10s dos ultimos puntos, utilizando el asistente de configuracion de adaptadores de datos y el generador de conjuntos de datos, ha efectuado el mismo proceso y creado 10s mismos componentes que en 10s apartados anteriores, en mucho
menos tiempo y con menos operaciones manuales. iEs posible hacerlo con aun menos trabajo? Pues si, es posible.
Los elementos que aparecen en el Explorador de servidores pueden arrastrarse
hasta un diseiiador, y las tablas, vistas y procedimientos almacenados no son una
excepcih. ~ Q u ocurre
e
si toma, por ejemplo, la tabla Editoriales desde la base
www.detodoprogramacion.com
de datos SQL Server y la suelta sobre el formulario Windows? HAgalo y compruebe como se configura automAticamente el adaptador de datos y la conexi6n. Lo
unico que tiene que hacer es abrir el menu emergente del adaptador y elegir la opcion Generar conjunto de datos. Ya tiene todo el trabajo anterior hecho en dos operaciones de raton.
En lugar de una tabla puede arrastrar una vista, obteniendo el mismo resultado, e incluso un procedimiento almacenado, caso en el que se crea un SqlCommand,
o equivalente, que facilita su ejecuci6n.
. .~....._.I....__.....
..~.....I__......__' . -.....~__.I_....
_.
.
..
....
...
._. .
Como ha podido ver en este capitulo, el entorno de Visual Studio .NET cuenta
con potentes herramientas para el trabajo con bases de datos, simplificando tareas
como la edici6n local de datos o informacion de esquema, incluso cuando se opera
sobre un origen de datos remoto. Visual Studio .NET facilita, asimismo, la depuracion de procedimientos almacenados SQL Server desde el propio entorno, lo que
nos ahorra cambiar del entorno de desarrollo a1 de la base de datos a1 depurar una
aplicacion que tenga embebidas parte de las reglas de negocio en el servidor de
datos.
Los componentes que en capitulos previos creAbamos mediante codigo, como
10s adaptadores de datos, comandos y conjuntos de datos, pueden tomarse desde
el Cuadro de herramientas, insertarse en un diseiiador y personalizarse mediante
la ventana Propiedades. En ocasiones, tal como se ha visto en 10s ultimos puntos,
la mayor parte del proceso de configuracih puede efectuarse automAticamente,
gracias a las opciones, asistentes y la posibilidad de arrastrar elementos, como las
tablas y vistas, directamente desde el Explorador de servidores hasta un diseiiador.
Una vez que sabemos c6mo conectar con 10s origenes de datos y definir adaptadores, comandos y conjuntos de datos, en el capitulo proximo veremos c6mo conectar esos elementos con controles de interfaz, incluido el control DataGrid que
hemos usado en el ejemplo de este capitulo.
www.detodoprogramacion.com
www.detodoprogramacion.com
La presentaci6n y solicitud de datos a travks de la consola, empleada en 10s ejemplos de 10s capitulos de la segunda parte del libro, no es precisamente el mecanismo m i s flexible ni amigable para comunicarse con 10s usuarios de sus aplicaciones.
Es mucho m6s habitual la elaboracion de interfaces de usuario basadas en ventanas, ejecut6ndose por ejemplo sobre Windows, o bien las interfaces Web, accesibles desde un cliente como Internet Explorer. Aunque podriamos, mediante cbdigo,
obtener 10s datos para presentarlos a1 usuario en componentes propios y, tambikn
mediante ccidigo, recuperar 10s cambios efectuados por el usuario para transmitir10s a1 origen de datos, lo cierto es que la mayor parte de ese proceso puede automatizarse gracias a la existencia de la vinculaci6n a datos en ciertos componentes.
Mediante la vinculaci6n a datos, o data-binding, es posible enlazar una vista, tabla o conjunto de datos con uno o varios controles de interfaz, ya Sean Windows o
Web, automatizando la presentacih y recuperaci6n de cambios. De esta forma
nuestro trabajo se reduce en gran medida.
El objetivo de este capitulo es introducir 10s conceptos de vinculacih a datos,
asi como 10s controles m6s interesantes en este aspecto. En el capitulo siguiente
nos centraremos en el disefio de formularios de datos empleando estos controles.
La vinculaci6n entre 10s origenes de datos y 10s controles puede ser de varios
tipos, segun que el control sea Windows o Web y tambien dependiendo de que
www.detodoprogramacion.com
pueda mostrar una sola columna de una fila o bien multiples filas o columnas. En
realidad, la vinculaci6n puede efectuarse no solo con una vista, una tabla o un conjunto de datos, sin0 tambikn con una lista, un arreglo y, en general, con cualquier
componente que implemente la interfaz I Li s t.
Los controles que se utilizan habitualmente para disefiar interfaces de usuario,
independientemente de que Sean nativas Windows o de tip0 Web, pueden clasificarse, en cuanto a su vinculaci6n a datos, en las tres categorias siguientes:
0
Controles que tan solo precisan el contenido de una columna de una cierta
fila, por ejemplo 10s TextBox y similares.
Controles capaces de mostrar el valor que tiene una cierta columna en multiples fhas, por ejemplo un ListBox o ComboBox.
Controles tip0 cuadricula en 10s que aparecen multiples filas con multiples
columnas, como el DataGrid que usibamos en uno de 10s ejemplos del capitulo previo.
En realidad, usando el diseiiador de formularios de Visual Studio .NET raramente tendremos que escribir sentencias de este tip0 ya que, como otras, la propiedad DataBindings puede ser editada en la ventana Propiedades. Esta propiedad
se encuentra en el apartado Datos, si tenemos las propiedades agrupadas por categorias, o bien como una de las primeras propiedades, si usamos el orden alfabktico.
A1 desplegar DataBindings nos encontramos con tres elementos, siendo dos
de ellos las propiedades Text y Tag.Son las que se suelen vincular con datos. Para conseguir el mismo efecto que la sentencia anterior, por tanto, seleccionariamos
el control TextBoxl y hariamos lo que puede verse en la figura 14.1, desplegar la
lista adjunta a la propiedad Text y seleccionar la columna de origen.
En caso de que la propiedad que deseemos vincular no sea una de las que nos
ofrece por defect0 la propiedad DataBindings, podemos pulsar el b o t h asociado a la entrada (Avanzado) para abrir la ventana Enlace de datos avanzado (vkase
figura 14.2). En ella se enumeran todas las propiedades del control que pueden ser
vinculadas, pudiendo seleccionar distintos origenes para cada una de ellas.
Los controles ASP.NET, a pesar de que en la fase de disefio parecen idknticos a
sus equivalentes para Windows, cuentan con un mecanismo de enlace a datos diferente. Si inserta un TextBox en un formulario Web y, en la ventana Propiedades, accede a su propiedad DataBindings, se encontrar6 con una ventana como
la que muestra la figura 14.3. Su funcionamiento es similar a lo explicado en el parrafo anterior, pudiendo seleccionar para cada propiedad una vinculacih de acceso a datos.
Si tras establecer el vinculo examina el c6digo HTML del documento, sin embargo, ver6 queTextBoxl en realidad no dispone de la propiedad DataBindings,
sin0 que se ha asignado a su propiedad Text lo que se conoce como una expresidn
de vinculacidn.
En este caso dicha expresi6n es la siguiente:
T ex t = ' < % # Da t a B i ride r . Eva 1 ( Ds L i b r o s 1 ,
" T a b l e s [ L i b r o s ] .Defaultview. [ 01 . T i tulo") % >
www.detodoprogramacion.com
Las expresiones de enlace se delimitan entre 10s caracteres < % #y %>, marcas
que provocan la resoluci6n en el servidor y no en el cliente. DataBinder es una
clase con la que cuentan las paginas ASP.NET, cuyo objetivo es facilitar el enlace
con origenes de datos tipicos, como conjuntos de datos y vistas. Lo unico que hay
que hacer es facilitar a su metodo Eva1 ( ) la referencia a1 origen, en este caso un
DataSet, y una cadena para seleccionar de 61 una cierta columna.
False
Top, Left
TWt
Rindow
FixedD
True
Normal
(ningunoi
IBearn
ilD"e
True
Microsoii Sans Serif, 3 25pt
NindowText
True
EiKrnboi
www.detodoprogramacion.com
terativo, puede invocarse a1 mismo metodo de la ptigina, encargkdose 6sta de todos 10s controles hijo que contiene.
(Nmsuno)
(Nmguno)
[Nmguno)
(Nwno)
Wmguno)
@nguno:
pimguno)
(Nmguno)
(Niguno)
(Nmguno)
WrnSUnQ!
(Nmguno)
(Nmguno)
(Nmguno)
(Nmguno)
iblinguno)
DsLibrosl Libios Tltulo
(Nmguno)
mguno)
INnauno)
....a+&.y,T.. ..............................
. . . . . . . -.
......................
. . . . . . . . . . . . . . . . . . . . . . ... .
fti
BackCdor
BorderColM
I BwderSMe
Borderwidth
Columns
I CssClasr
Enabled
Font
0 Editorial
0 IDLibro
+
+
U Preoo
Y
www.detodoprogramacion.com
s+(eccl;re
~a
m e s t o r de enlace
Son varios 10s componentes capaces de mostrar el valor que una cierta columna
tiene en multiples filas, siendo 10s mas habituales ListBox y ComboBox. Cualquiera de estos dos componentes puede ser usado para ofrecer a1 usuario una lista
de valores a elegir, tornados de una columna de una tabla, asociando dichos elementos con el valor que tenga, en la misma fila, cualquier otra columna. El usuario
podria, por ejemplo, elegir el nombre de una editorial de un ComboBox y el programa obtener el identificador de dicha editorial.
Aunque estos controles t a m b i h disponen de la propiedad DataBindings,
cuentan, ademfis, con propiedades especificas para el comportamiento especifico
que tienen. En el caso de 10s controles para formularios Windows dichas propiedades son:
Datasource: Contendra una referencia a la tabla, vista u objeto que vaya a
actuar como origen de datos.
DisplayMember: Alojara el nombre de la columna cuyo contenido se mostrar6 en la lista.
ValueMember: Indica la columna cuyo contenido se obtendrfi como valor
asociado a cada uno de 10s elementos de la lista.
Suponiendo que deseasemos mostrar en un control ListBox 10s titulos de todos 10s libros y que, a1 elegir cualquiera de ellos, se obtuviese el identificador del
seleccionado, asignariamos entonces el valor Titulo a DisplayMember e I D L i www.detodoprogramacion.com
bro a ValueMember, mientras que Datasource podria ser DsLibrosl. Libros, suponiendo que tenemos un DataSet llamado DsLibros 1 conteniendo la
tabla Libros. En caso de que usemos 10s controles Web equivalentes, las propiedades a utilizar serdn las cuatro siguientes:
0
Puede hacer una prueba simple insertando un ListBox en una p6gina Web
ASP.NET, junto con un TextBox, y enlazando la lista con la columna Titulo de
la tabla Libros. D6 el valor True a la propiedad AutoPostBack del ListBox y,
tras hacer doble clic sobre 61, introduzca la siguiente sentencia:
TcxtBoxl.Text
ListBoxl.SelectedItern.Va1ue
_________
Figura 14.5. Vinculacion de una lista ASP.NET con 10s valores de una columna
www.detodoprogramacion.com
Este mismo ejemplo puede aplicarse con un L i s t B o x en un formulario Windows, tan solo tiene que cambiar las propiedades de vinculacion de la lista,
manteniendo el resto igual.
La tercera categoria de componentes estd compuesta exclusivamente por el control D a t a G r i d que, a diferencia de 10s anteriores, tiene la capacidad de mostrar
multiples filas y columnas, pudiendo facilitar el acceso a tablas completas de information. Estos controles, por tanto, no se enlazan con una columna en particular, sino con una vista o una tabla completa.
Independientemente de que usemos el D a t a G r i d de formularios Windows o
formularios Web, las dos propiedades de enlaces a emplear son las mismas: D a t a S o u r c e y D a t a M e m b e r . La primera hard referencia a1 origen de datos y, en caso
de que &te sea un D a t a S e t , la segunda seleccionar6 entonces una de sus tablas o
vistas.
Aunque el comportamiento de ambos controles D a t a G r i d difiere bastante, visualmente hablando, como se aprecia en las figuras 14.6 y 14.7, son muy similares,
mostrando, como es logico, la misma informacion a1 vincularse a1 mismo origen de
datos.
ISBN
&tor
Mtorial
Precio
3,
PI Spnlik,
10-5
Frarcisco Ctarte
Frarcisco Ctarte
Francisco Charte
Fraruaco Charle-orix Seiiaro
Francisco Charte
Frarcieco Charte
1:.
30
1
1
1
1%
Frarcisco Ctane
1
1
10.52
Francisco Charte
39
10 7
:
3T.26
1352
Francisco Charte
1
1
Frarcisco Charte
1
1
24 9
43
Frar=isco
Ctarte
Francisco Cbarte
Ill
21 34
lC5i
IC 52
mantener una lista de objetos, uno por cada origen de datos que exista, que se encargarin de la sincronizacih de todos 10s componentes vinculados a un mismo
origen. Los elementos de Bindingcontext son de tipo BindingManagerBase,
una clase abstracta que cuenta con dos derivadas: CurrencyManager y Propert yManager.
La clase PropertyManager se usa para mantener la asociaci6n entre la propiedad de un control y un origen cuando no hay necesidad de saber qu6 fila de ese
origen es la actual, caso 6ste en el que se emplearia un CurrencyManager. Siempre que el origen sea un DataTable, DataView o similar, el objeto encargado de
mantener la asociaci6n seri un CurrencyManager.
Como ya sabe, lo ha visto en 10s capitulos de la segunda parte, una vez que se
ha recuperado informacion en un DataTable 6ste contiene todas las filas de datos, a las que puede acceder como si de un arreglo se tratase. No existe una propiedad que indique qu4 fila es la actual, ya que ese concepto, muy habitual en otros
sistemas de acceso a datos, no existe en ADO.NET.
Cuando ese DataTable o DataView se enlaza con controles como TextBox,
CheckBox y RadioButton, sin embargo, existe la necesidad de saber c u d de las
filas de esa lista de datos tiene que mostrarse en 10s controles, es decir, cu6l de las
filas es la posicion actual dentro de la lista. Como ADO.NET no ofrece esa funcionalidad, lo que hacen 10s formularios Windows es crear un CurrencyManager
para cada origen que mantiene una lista de datos, como 10s mencionados DataTable y Dataview.
Dado que en un mismo formulario podrian existir multiples CurrencyManager,
bien porque existan varios origenes de datos o un mismo origen con enlaces no
homog6neos a varios controles, para mantenerlos todos ellos se emplea un objeto
Bindingcontext.
Conociendo el nombre del origen de datos, es ficil recuperar el CurrencyManager asociado:
B i n d i n g C n r ~ t e x (t D s L i b r o s l ,
"Libros" )
datos, contando con propiedades que nos permiten conocer y modificar dicha POsicion. La mayor parte de 10s miembros de esta clase son heredados de BindingManagerBase, si bien CurrencyManager sustituye algunas implementaciones
por otras mds especificas.
En cuanto a posicion se refiere, las dos propiedades de mayor inter& que tiene
esta clase son Count y Position. Como puede suponer, la primera indica el numero de filas existentes en el conjunto, mientras que la segunda es un indice con
base 0, por lo que el valor mdximo serd el indicado por Count menos 1.
Conociendo tan s610 estas dos propiedades, es fdcil afiadir a un formulario 10s
controles de navegacion cl6sicos para que el usuario pueda ir fila a fila por el conjunto de datos.
. .-..._(^._.-.....__I.--..
_^__I
I.-.-.,
.
x
_
....-
_.___^__I__x.
____^._
.__.
ll_ll
_ _ _ ~ _ ^ _
Controles como ListBox, ComboBox y DataGrid tambien cuentan con la propiedad DataBindings, a1 fin y a1 cab0 son clases derivadas de Control, per0
cuentan con propiedades m6s especificas ya explicadas en 10s apartados del primer punto de este capitulo.
S
La vinculacion a datos de las aplicaciones Web es muy distinta a la de las aplicaciones Windows, a1 ejecutarse en un entorno que, por naturaleza, es desconectado, es decir, 10s clientes no mantienen una conexi6n continua con el servidor. Los
formularios ASI'.NET no disponen de la propiedad Bindingcontext ni 10s objetos derivados de BindingManagerBase, y 10s controles no facilitan la navegac i h , edici6n y actualizaci6n directa de 10s datos como si lo hacen en 10s formularios
Windows.
En muchas ocasiones la vinculaci6n a datos en una pdgina Web se emplea para
mostrar informaci6n s610 de lectura, por ejemplo generando un informe. En otros,
por el contrario, si es precisa la edicibn, para lo cual ser6 necesario controlar parte
de las acciones mediante c6digo.
. ,,
. .'
. ..
.
. . .' '.
..
Debe tenerse en cuenta que 10s clientes que vayan a usar una aplicacion Web
en la que se utiliza vinculacion a datos, tienen que instalar en su sistema 10s
MDAC: Puede aiiadir a 10s propios formularios ASP.NET la informacion necesaria para que 10s obtenga e instale.
A cambio, en ASI'.NET existen m6s componentes capaces de presentar una lista
de datos que en 10s formularios Windows. Ademis del conocido DataGrid y el
control ListBox,tambikn tenemos a nuestra disposici6n 10s controles CheckBoxList, RadioButtonList, DataList y Repeater, siendo estos dos dtimos especialmente interesantes. Con Da taLis t es posible crear listas de datos basadas
en una plantilla de apariencia definida por nosotros, mientras que Repeater es
un contenedor en el que es posible insertar otros controles que serdn repetidos por
la piigina Web. Tanto DataList como Repeater se basan en el us0 de plantillas
que hay que definir directamente en el m6dulo HTML, con etiquetas tales como
<ItemTemplate> 0 <HeaderTemplate>.
En caso de que vaya a diseiiar una pdgina ASI'.NET con vinculaci6n a datos,
por ejemplo para mostrar las editoriales o libros existentes en nuestra base de dawww.detodoprogramacion.com
Inserci6n en la pagina ASI'.NET de un componente DataList, seleccionando alguno de 10s estilos predefinidos para 41.
Edici6n de la plantilla correspondiente a1 cuerpo, insertando en dl un componente que se enlazaria con la cohmna Titulo.
Codificacibn, en el evento Load, de la apertura de la conexi6n y obtenci6n
del DataReader, asignandolo a la propiedad Datasource del DataList.
En la figura 14.8 puede ver c6mo se ha insertado un control Label en el ItemTemplate del componente DataList, y c6mo se utiliza la propiedad DataBindings de la etiqueta de texto para vincularla con la columna Titulo. Se asume,
por supuesto, que hemos insertado y configurado la conexi6n y el comando.
A continuacicjn, tras hacer doble clic sobre el fondo de la pdgina, introduciriamos el c6digo siguiente:
sq
Da
DataBind ( )
'
SylConnectionl. C use
( )
s
Si a pesar de la existencia de componentes como DataList y Repeater, que
pueden enlazarse a una lista de datos, decide emplear componentes con vinculaci6n simple, seguramente precisara un medio de navegaci6n por la lista de datos,
de tal forma que 10s controles muestren en cada momento la informaci6n de la fila
actual.
www.detodoprogramacion.com
5eleccime la propiedad we derea enbzar A conbnuaci6nn.Ubltce el enlace simple para enlazar con un
dab5 y establecer el forrnato o &re el enlace persoMflzado para e s a w ma eqxeu6n
elernento de
ropedades enkables
AccessKey
Backcolor
BotderColw
Borderswle
BordeiWidh
cssc1ass
Enabled
Font
Forecolor
Height
ToolTip
Visible
Width
Eapresdn de e n k e p s r m l ~ z a d a :
DataBinder Eval(Contamer DataItern, "TlbAo")
NET
NET
Guiapr&&apaia
Intr&&
a la programackjn
d del rmaoprocesador60386
www.detodoprogramacion.com
Sessicrl ("Cirunt" 1
D s L i b ~ u . ~L li b r u s . r o i i r ~ t
Se-sion("Position")
I)
DataBind ( )
End If
End Sub
Priva
S e s i i o n ( C o u n t ) - 1 Then
P o s i t i o n += 1 '
Sessi ~ n ( " P o s i t i o r ~ " =
) Poiition
DataBind ( ) '
End I f
End Sub
Priva
C l i c k (B
e r l d c r As S y s t e m . Obi e c t ,
ByVal e As S y s t e m . E v e n t A r g s ) Handles B u t t o n 2 . C l i c k
Dim P o s i t
"Prrsltlori")
P o s i t i o n -= 1
Session ( " P o s i t i o n " )
DataBind ( )
tosition
'
End If
End Sub
TextBoxl.Text
TextBox2.Text
End Sub
&dwo
Eddiom
4er
Favoritor
flwramientas
Amda
sy
- - + I 2
llek~O$BDD~aual6a~1d.l~/l4~a.egarASP/WebForm1
awx
Francisco Charte
Figura 14.10.
La pagina con las dos cajas de texto y 10s botones que permiten
avanzar y retroceder entre filas de datos
Los controles ASI'.NET tampoco disponen de un sistema de edici6n y actualizaci6n autom6tica de 10s datos. Los cambios en la informaci6n mostrada por 10s
controles deben detectarse, facilitando, en caso de ser necesario, 10s elementos para efectuar dicha edici6n. El componente D a t a G r i d , por ejemplo, puede mostrar
una serie de enlaces como columnas de la rejilla, haciendo posible la edici6n y eliminaci6n de datos.
En cuanto a la actualizacion de 10s datos en el origen, necesitar6 disponer en el
formulario algun boton o enlace que, a1 ser pulsado, ejecute el c6digo de sincronizaci6n de 10s cambios con el servidor del que procede la informaci6n. Esto significa, por regla general, o utilizar un objeto Command con la sentencia SQL a ejecutar
0, si estamos usando un adaptador de datos y un D a t a S e t , servirnos del mecanismo habitual de actualizacibn que ya conocemos.
www.detodoprogramacion.com
www.detodoprogramacion.com
www.detodoprogramacion.com
Usando 10s controles de las secciones Web Forms o Windows Forms, segun el tide aplicaci6n que se trate, pueden disefiarse formularios que permitan a1 usuario ver 10s datos, navegar por ellos, editarlos, afiadir y eliminar datos. Para ello
necesitard combinar gran parte de 10s conocimientos que ha adquirido desde el
principio de este libro, desde la definici6n de la conexi6n con el origen de datos hasta la vinculaci6n de 10s controles, pasando por la creaci6n de adaptadores y conjuntos de datos o la codificacih de las sentencias necesarias para actualizar el origen.
Visual Studio .NET dispone de sendos asistentes que facilitan el disefio de estos
formularios, ahorrdndonos gran parte del trabajo que, de otra forma, tendriamos
que efectuar manualmente. El objetivo de este capitulo es mostrarle c6mo servirse
de estos asistentes para disefiar sus propios formularios, usando, como en 10s demds capitulos, alguna de las bases de datos creadas en el tercer capitulo.
PO
DataSet
Arthivo XML
Archivo XSLT
As[stente p a
famukbs
Esquema XML
Y oat95
2 Web
a Utilidad
...
Nuestro objetivo es crear un formulario con una relacibn maestro/ detalle entre
las tablas E d i t o r i a l e s y L i h r o s , usando para ello dos controles D a t a G r i d , de
tal forma que, a1 seleccionar una editorial en el primero, aparezcan automdticamente en la rejilla de detalle 10s titulos que correspondan. No necesitamos definir una
conexibn, ni tomar las tablas desde el Explorador de servidores y arrastrarlas sobre un formulario, ya que todo ese trabajo lo efectuard el asistente.
La primera pdgina del asistente es tan s610 informativa, indicdndonos cud1 es
su finalidad, bastando con pulsar el b o t h Siguiente > para dar el primer paso.
Seleccicin del
En nuestro caso partimos de un proyecto inicialmente vacio, per0 igualmente
podriamos haber invocado a1 asistente tras definir un D a t a S e t a partir del origen
de datos que nos interesase. El primer paso del asistente nos permite, tal como se
aprecia en la figura 15.2, tanto crear un nuevo conjunto de datos como w a r uno
que ya existiese en el proyecto.
Deje elegida la primera opcibn, en realidad no puede activar la segunda ya que
el asistente ha detectado que no hay n i n g h D a t a S e t existente disponible, e introduzca el nombre que desea dar a1 conjunto de datos, por ejemplo d s l i b r o s .
En este conjunto de datos, tal como veremos despuks, se introducirdn las tablas
E d i t o r i a l e s y L i b r o s , asi como un objeto D a t a R e l a t i o n para relacionarlas.
Todo ese trabajo, que en 10s capitulos de la segunda parte efectudbamos mediante
cbdigo, ser5 ejecutado por el asistente.
www.detodoprogramacion.com
E l m te ayuda acrearun w e y o
de dates. De forma dhzmathra,
proyecto un conju&o de dabs ya defintdo o uno propt~dwradopos un mwcio Web.
ZQu6 conjunto de dabs derea utitizar?
F pear
INI
ldsLlbrosl
xi6
El DataSet tiene que recuperar la informaci6n de un origen de datos, para lo
cual es precis0 facilitar una conexion. Esta puede encontrarse predefinida, en el
Explorador de servidores, o bien crearse a prop6sito en ese mismo momento. Es la
tarea del paso siguiente del asistente, cuya ventana se muestra en la figura 15.3.
Si tenemos una conexion definida que nos sea util, no tenemos m6s que desplegar la lista que aparece a la izquierda para elegirla. De no ser dse el caso, pulsariamos el b o t h Nueva conexidn y definiriamos la nueva conexion con el cuadro de
didlogo que ya conocemos de capitulos previos.
En este caso hemos elegido la conexi6n que teniamos definida para acceder a la
base de datos SQL Server que se encuentra en el servidor Inspiron. En su caso, como es logico, la conexi6n seri otra diferente dependiendo de d6nde estd ejecutdndose SQL Server o bien MSDE. Tambidn puede optar por conectar con un origen de
datos distinto, cualquiera de 10s que cre6 en el tercer capitulo.
Nueva L o n e ~ ...
n
Como puede verse en la figura 15.4, hemos elegido del origen las tablas Edit o r i a l e s y Libros, que ahora aparecen en el panel de la derecha en lugar de ha-
cerlo en el de la izquierda. Pulse el b o t h Siguiente > una vez m& para continuar
en el punto siguiente.
Ciertos pasos del asistente dependen de 10s elementos que se elijan aqui. Al
haber seleccionado dos tablas, por ejemplo, deberemos definir una relacion
entre ellas, algo que no seria preciso si hubiesemos seleccionado una vista o
un procedimiento almacenado. A cambio, sin embargo, podria ser necesario facilitar una lista de parametros de entrada.
Cuando creAbamos, mediante cddigo, un D a t a S e t a partir de sendos comandos para obtener el contenido de dos tablas, un paso imprescindible era el establewww.detodoprogramacion.com
El asistente crea un adaptador de dam5 para rdlenar el conjunto de datos de las CaMas o las
wstas dlsponibles. SIsekccrona mis de un elemento, puede estaMecer una rela& enbe ellos
en el squiente paso.
Oementos disponibles:
+
Bementos sekcionados:
Tablas
vistas
I-,
_1_1
Tablas
Editoriales
Llbros
vistas
Figura 15.4. Seleccionamos las tablas con las que va a generarse el formulario
En este paso del asistente, dado que en el anterior hemos elegido como elementos dos tablas, tendremos que establecer esa relacidn, per0 sin necesidad de crear
de manera explicita el objeto D a t a R e l a t i o n . En su lugar (vkase figura 15.5) bastar6 con indicar cud1 es la tabla maestra y la de detalle, seleccionando las columnas
de enlace. Hay que pulsar el b o t h > para crear efectivamente la relacidn, momento en que aparecera en la lista Relaciones.
La existencia de esta relaci6n es fundamental a la hora de crear una relaci6n
maestro/detalle, ya que sin ella no se sabria qu6 libros corresponden a la editorial
seleccionada en cada momento.
Que tomemos datos de dos tablas no implica que deban mostrarse todas sus columnas, aunque quiz2 sea 6ste el caso que nos interese. En cualquier caso, el paso
siguiente del asistente nos permitird elegir las columnas que deseamos tener en el
formulario. Tenemos nuevamente dos paneles bien diferenciados, segun se aprecia en la figura 15.6. En el de la izquierda elegimos la tabla maestra de la lista desplegable, marcando a continuaci6n las columnas que deseamos tomar de ella. De la
misma forma, en el panel derecho seleccionamos la tabla de detalle y sus columnas.
www.detodoprogramacion.com
&elaoones:
IFKLibrosEditorial
Tabla primaria:
TaMa s e c & a n a :
Editor ia les
ILibros
paves:
IDEditorial
Figura 15.5. Definimos la relacion que existe entre las dos tablas
i=
W ptinopal-detdfe
i l-,l
ILibros
CQ!UKWW:
____
El tiltimo paso del asistente nos permite elegir el disefio que deseamos darle a1
formulario, existiendo dos opciones:
0
$re.ssrzP
I
lo5 relpsbos d d
conjunto de datos
r
r
r
Ahwa el asistente bene la informauon necesaria Haga dic en Fmakar para salir y generar el nwvo
formulano
Figura 15.7. Optamos por usar controles D a t a G r i d para mOStrar 10s datos
de las tablas
___
- -_________
- -__-A1 pulsar el b o t h Finalizar del asistente 6ste se cerrar6 y nos encontraremos
con nuestro formulario, con su aspect0 por defecto. L6gicamente puede personalizar dicho disefio, modificando titulos y disposicih de 10s botones o 10s DataGrid,
aiiadiendo nuevos elementos para realzar la interfaz, etc. En nuestro caso nos hemos limitado a modificar el ancho del segundo DataGrid, cambiando tambidn la
propiedad D o c k de ambas cuadriculas para que se adapten automdticamente en
caso de que se ajusten las dimensiones del formulario. En la figura 15.8 puede ver
el formulario en el entorno de Visual Basic .NET tras 10s cambios.
*
___-I_
-__.
ForrnularloAsstpnte (1
FmdabAsiotente
References
Assernblylnfc vb
dstibras nsd
hnhbrm rb
IUClOn
.r
ob)diiibras
% OlrDbConnemonl
boleDbDataAdaprer1
b OleDbDataAdapter2
Nota
Observe, en la parte inferior del area de diseiio, 10s componentes de acceso
a datos que ha generado el asistente: uno para la conexion, dos adaptadores
de datos y el D a t a S e t .
www.detodoprogramacion.com
- __
-_I__
- - -
_ _ _ - ~
Ademas de todos 10s controles que pueden verse en el formulario, con sus
propiedades debidamente establecidas, el asistente tambien ha generado el c6digo
necesario para recuperar 10s datos, actualizarlos y cancelar 10s cambios efectuados. Analicemos brevemente ese c6digo para saber exactamente qu4 ocurrir6 a1 ejecutar el programa.
'.
Tras abrirse el formulario este permanecerti vacio esperando una acci6n por
parte del usuario. Lo habitual es que se pulse el boton Cargar que provoca la ejecuci6n del c6digo siguiente:
Private Sub k t r l l i j a d C l i c k ( B y V a 1 s e r i d e r As System.Ob]ect,
~
B y V a l e As S y s t e r n . E v r n t A r g s 1
H a n d l e s b t r l L o a d . r1ic-C
T rY
C y s t em. hi r1j J w c
. F Jim'.
End T r y
End Sub
Lo unico que se hace es invocar a1 metodo LoadDataSet ( ) del propio formulario, controlando una posible excepcion. El bloque de c6digo que hay detr5s del
C a t c h est6 diseiiado para que introduzcamos nuestro control de errores personalizado, ya que el asistente lo que hace es mostrar el posible error en una ventana.
El c6digo del metodo LoadDataSet ( ) es el mostrado a continuacih:
P u b l i c Sub L ( arjIiataSet! )
Dim 3biDataSetTernp As F o r m u l a r i u A s i ? t e n t e . d s L 1 b r c r s
o b i D a t a S e t T e m p = N e w Furmulari~,A-lstente.dsLlbros(
T rY
Me.FillP3taSet (ob]DdtaSetTemp)
Catch e Fi 11 Dd t aSet As Sys t e m . E x c e p t i u r i
www.detodoprogramacion.com
www.detodoprogramacion.com
Una vez introducidas en el Data S et todas las filas de las dos tablas, se devuelve el conjunto de datos de nuevo a1 metodo LoadDataSet ( ) . fistelirnpia el DataSet
existente en el formulario, llamado ob jdslibros, e introduce en 61 las filas obtenidas por la llamada a Fi 11Data Set ( ) . En ese momento el formulario ya apareceria con la lista de editoriales en el primer DataGrid y la de libros en el segundo,
como se aprecia en la figura 15.9. Podemos cambiar de editorial para ver sus libros,
aiiadir entradas, eliminarlas y modificarlas.
Anaya Multimedia
McGrawHiII
Telemaco 43
Editicio Valrealv 1' planta
901 Grayson Street
605Third Avenue NewYork
1 IDLibro 1 ISBN
4
5
6
7
8
9
10
84-415-1324-4
84-415-1392-9
84-41 5-1 376-7
84-41 5-1 351-1
84-415-1290-6
84-41 5-1 291-4
84-415-1 261-2
- _ IAutor
Guiapradicaparausuarios JBuilder 7
Programacion con Visual C# NET
Programacion con Visual Studio NET
Programacion con Visual Basic NET
Guia practicapara usuarios de Visual Basic NET
Guia pradica para usuarios de Visual Studio NET
Programacion con Delphi 6 y Kylix
Guia pradica para usuarios de Delphi 6
Manual avanzado Excel 2002
Guia practica para usuarios de Excel 2002
Francisco Charte
Francisco Charte
Francisco ChartefJorge Ser 1
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte
www.detodoprogramacion.com
oblDataSetChdnyes
CType[objJrLibr b . b e t C h a r ~ g e s ,
Fo L mi 1 1a L 1oA. 1 it F rl t e . d c I, I b L
o b l 3 s L i b r o s . M e r g e [ o b jD a t a S e t r h a n y e s )
o b ] d ~ L i b r o s. A c c e p t C t i a n g e c . ( )
Catch e U p d a t e As S y s t e r n . E x c e ~ t i o n
Throw eUpdat e
End Try
End If
End Sub
En principio se llama a1 metodo EndcurrentEdit ( ) del objeto BindingManagerBase de cada tabla, finalizando asi cualquier operaci6n de edici6n que pudiese haber en curso. Observe c6mo se utiliza la propiedad Bindingcontext del
formulario explicada en el capitulo previo.
A continuaci6n se recuperan, en un DataSet temporal, 10s cambios que se han
efectuado en el formulario, usando para ello el metodo Getchanges ( ) del dsLib r o s . Tras comprobar que, efectivamente, hay cambios pendientes de consolidar,
se llama a1 mbtodo UpdateDataSource ( ) y combinan 10s cambios en el conjunto
de datos a1 que estdn vinculados 10s controles.
El metodo UpdateDataSource ( ) , recibiendo como pardmetro la lista de cambios, se encarga de abrir de nuevo la conexi6n e invocar a1 metodo Update ( ) de
cada adaptador, facilitando la informaci6n a1 origen de datos.
Public Sub U p d a t e D a t a S o u r c e (ByVal C h a n g e d R o w s As
Fo rmu 1 a r 1 o A s 1s t e n t e . is L 1b rrr s )
T rY
www.detodoprogramacion.com
End I f
Catch u p d a t e E x c e p t i i n As Sy-tern.E x c e p t i o n
Throw npziat rl A i,pt
Finally
I )ri
End Try
End Sub
Nota
En lugar de recuperar 10s cambios en un D a t a S e t temporal, tambien podria
haberse empleado el original como parametro para el metodo U p d a t e ( ) de
10s adaptadores. Sin embargo, en caso de que la actualizacion devolviese algun error este se veria reflejado en las filas del conjunto de datos que hay vinculado con 10s controles.
hlostrar
hlostrx
Mostrar
Mostrar
detalles
detalles
detdles
detdles
IDEditorhl
Nombre
0
1
2
3
abC
abC
abC
abC
abC
abC
abC
abC
DireccIon
abC
~
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
?&OleDbDataAdapterZ
DataBound
DataBound
DataBound
DataBound
DataBound
& OleDbDataAdapterl
DataBound
DataBound
DataBound
DataBound
DataBound
t% OleDbCannecbonl
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
DataBound
& objdsiibros
x_II.--
www.detodoprogramacion.com
Me.detailDataGrid.Visible = F a l s e
Application ["objdslibros") = Me.objdsLibros
Catch eLoad As System.Exception
Me.Response.Write(eLoad.Message)
End Try
E n d Sub
\Iostra detallss
h a 1 a \luttnueda
SIcGran Hd
Telemaco 43
Edmcto V&e&
.4presc
\Ioctrar d e t d r c
\forttar
4
<
6
dctdcb
SQL S m a 2000
Gua prachca pma usuarios Budder Progamacion con Visual C= M T
Progamacion con 'iisual Studm 'iTT
Francisco Charte
Francisco Charte
Francisco Chate
Francisco C hate Jorpe Smano
Frannsco Chmte
Frannsco Chmte
Franasco Chart?
Frmcisco Charte
Frannctsco Chme
10
11
I?
17
11
15
1-
l'planta
Francisco Chmte
Frannsco Chmte \I Jesus Luque
Francisco Charte
Francisco Chme
JeffDuntemann
1
1
1
10 - 4
10
39
40
-'
39
10 ' 5
10 '1
3' 26
10 ' 2
1
1
21 01
10 52
10 ' 2
24 0 1
60 5
bri1.s
E d i t o r i a 1" )
A pesar de la extensih, en cuanto a numero de sentencias, el proceso que ejecutado es relativamente simple, lo que ocurre es que se efectua paso a paso. Se utiliza una vista, p a r e n t R o w s , para obtener una referencia a la fila que esta elegida
actualmente en el D a t a G r i d maestro. Con esta informaci6n se utiliza el metodo
C r e a t e C h i l d V i e w ( ) de la fila para obtener el conjunto de filas de detalle, enlazandolo con el segundo D a t a g r i d y haciendo este visible.
\
.......
1.:
.........................
.....................
......
para abrir el menu emergente, y luego seleccione la opcion Generador de propiedades. Se abrira un cuadro de didogo con multiples apartados a 10s que puede acceder con 10s botones que aparecen a la izquierda. Pulse el boton Columnas (vease
figura 15.12) para acceder a la lista de columnas de la cuadricula.
1General
J Columnas
3 Paginacmn
d Formato
3 Bordes
Lrsta de ED
Columnas disponrbles:
Columnasselecaonadas
0 C o b m enlazada
Columna Hipervinculo
W Columna Plantilla
Propiedadesde EdKommandC&mn
Texto del mcabezado:
...
.
.
......- _.
I
Expresih de _wdem&n:
r] p yisibb
.
I
Ayuda
Figura 15.12. Aiiadimos a la rejilla una nueva columna para el boton de edicion
Elija en el apartado Columnas disponibles la secci6nColumna de boton, aiiadiendo a Columnas seleccionadas un elemento Editar, Actualizar, Cancelar. Coloquelo
como primer elemento, para que aparezca como la columna m6s a la izquierda de
la cuadricula. Si quiere puede personalizar el texto de 10s enlaces, asi como cambiar el Tip0 de boton que, por defecto, es LinkButton.
Cierre el cuadro de didogo pulsando el b o t h Aceptar. VerA que el D a t a G r i d
ya muestra el enlace o b o t h para editar cada fila, pero si ejecuta el programa no
obtendr6 respuesta alguna a la pulsation sobre 61.
,- \
I.1
I
www.detodoprogramacion.com
-1
Dim F l L d AS dsLibros.LibrosRow =
obldslibros. Libros. FindByIDLibro (
CType(e.Item.Cells(l).Controls(O),TextBox).Text)
~
LOlS(O),
.Titulo = CType(e.Item.Cells(3).Controls(O),TertBox).Text
.Autor = CType(e.Item.Cells(4).Controls(O), TextBox).Text
. E d i t o ~ i a l CType(e.tem.Cells(S).Cor~trols(O),
TextBox).Text
.Precio = CType(e.Item.Cells(G).Controls(O),TertBox).Text
End With
End If
~
de
d.Ed
ShowDetailGrid() '
End Sub
Tras recuperar la referencia a1 DataSet, almacenada como variable en la propiedad Application de la pAgina, buscamos en 41 la fila que corresponde a1 libro
que estQeditiindose. Se obtiene un objeto LibrosRow, que no es mAs que un derivado de DataRow en el que existen propiedades especificas para el acceso a las columnas de esta tabla.
Observe c6mo se recupera el control que hay en cada celdilla, mediante la expresi6n Cells (n). Controls (O), convirtiendolo en un TextBox para poder
leer el texto que contiene. La primera celdilla, a la que corresponde el indice 0, es
www.detodoprogramacion.com
la que contiene 10s enlaces de edition, asi que el identificador del libro se encuentra en la segunda y 10s demiis datos en las siguientes. Los recuperamos asignando10s a las columnas de la fila en el Data S e t.
Si ejecuta el programa en este momento, verii que puede efectuar cambios y
que, tras pulsar el enlace Actualizar, &tos permanecen ahi, en el DataSet,per0 si
comprueba el origen de datos, o simplemente sale del programa y vuelve a ejecutarlo, comprobara que esos cambios se pierden. Tenemos que actualizar el origen
de datos.
2
ii
811
___
-__-_
No tiene sentido actualizar la informaci6n con el origen cada vez que se modifique una columna, asi que necesitaremos aiiadir un b o t h o enlace para que dicha
actualizacion se efectue a demanda. Como se aprecia en la figura 15.13, insertaremos ese b o t h a la derecha del que ya existia en la parte superior de la pagina
www.detodoprogramacion.com
Podriamos haber dado todos 10s pasos que se ejecutaban en el c6digo generado
por el asistente de formularios Windows para efectuar la actualizacih, per0 hemos optado por algo mucho m6s directo. Recuperamos la referencia al DataSet y
lo usamos directamente como parhmetro del mktodo Update ( ) del segundo adaptador de datos.
El efecto, si lo comprueba, es el mismo, se escriben 10s cambios en el origen de
datos complethdose el ciclo que le permitir6 editar la informacih desde un navegador Web.
www.detodoprogramacion.com
Este ultimo capitulo dedicado a1 estudio de 10s elementos de Visual Studio .NET
relacionados con el acceso a datos, le ha servido para conocer dos de 10s asistentes
m&spotentes con que cuenta el entorno, mediante 10s cuales pueden generarse formularios con controles vinculados a datos tanto en aplicaciones Windows como en
aplicaciones Web.
Ha podido ver que el asistente para formularios Web genera menos funcionalidad que el equivalente para Windows, y t a m b i h c6mo suplir dicha deficiencia
con la personalization de las columnas del D a t a G r i d y la escritura de algunas
sentencias.
En resumen, 10s capitulos de esta tercera parte le han facilitado gran parte de la
informaci6n que necesitari para crear interfaces de usuario, Windows o Web, con
controles vinculados a 10s elementos que conoci6 en la segunda parte, principalmente conjuntos de datos, tablas y vistas.
www.detodoprogramacion.com
www.detodoprogramacion.com
www.detodoprogramacion.com
Los capitulos de esta ultima parte del libro, en general mucho m6s breves que
10s anteriores, le explican c6mo abordar casos concretos, generalmente de forma directa mediante algun ejemplo.
En algunos de ellos se resume informaci6n vertida en capitulos previos, o bien
se profundiza en temas que, a pesar de haberse tratado anteriormente, no se ha hecho con detalle.
En este decimosexto capitulo, que es el primer0 de la cuarta parte, el objetivo es
codificar un ejemplo en el que se conecta con un origen de datos y se recupera informacibn, como en 10s capitulos previos, per0 sin emplear directamente las clases especificas de cada proveedor a lo largo de todo el ddigo, sino tan s610 en un
punto.
De esta forma conseguiremos una conexi6n gen6rica muy fiicil de modificar,
incluso en ejecuci6n a demanda del usuario.
En el quinto capitulo, dedicado a1 estudio del modelo de objetos ADO.NET, conocio multiples interfaces que eran implementadas por clases de cada proveedor
de datos.
A mod0 de recordatorio, las interfaces que podriamos considerar miis interesantes son las siguientes:
www.detodoprogramacion.com
IDbCommand:Esta interfaz, implementada por las clases SqlCommand, OleDbCommand, OracleCommand y OdbcCommand, establece el conjunto de
miembros necesario para definir un comando y ejecutarlo, ya sea obteniendo a cambio un lector de datos o no.
IDataAdapter e IDbDataAdapter:La primera define 10s mktodos Fill ( )
y Update ( ) que hemos empleado repetidamente para llenar un DataSet o
actualizar el origen, mientras que la segunda declara las propiedades SelectCommand,InsertCommand,UpdateCommandy DeleteCommand.La
clase Da taAdap te r, tambien generics, se encarga de implementar 10s dos
primeros metodos y servir como base de DbDataAdapter que, a su vez, es
la base comun de SqlDa taAdap ter, OleDbDa taAdap ter, OracleDa taAdapter y OdbcDataAdapter. Estas implementan directamente la interfaz
IDbDataAdapter.
IDataReader:Interfaz implementada por las clases SqlDataReader, OleDbDataReader, OracleDataReader y OdbcDataReader, que facilitan la
lectura unidireccional de conjuntos de datos sin posibilidades de edici6n.
Si necesita refrescar m i s la memoria observe las figuras 5.2, 5.3 y 5.4, en las
cuales se representaban esquemiticamente las relaciones entre estas interfaces y
las clases que las implementan. En el punto siguiente las usaremos para escribir un
ejemplo que pueda operar indistintamente sobre una base de datos Access, SQL
Server u Oracle.
(
I
-
e funciones
El paso siguiente ser6 la codificaci6n de 10s procedimientos y funciones necesarios para abrir la conexi6n y recuperar 10s datos a partir del comando de seleccibn
que se haya introducido.
Comenzaremos escribiendo la declaraci6n de las cuatro variables siguientes a1
inicio del m6dulo:
Dim
Dim
Dim
Dim
Coriexion As I D b C o n n e c t i o n
Comando As IDbCommand
A d a p t a d o r As I D b D a t a A d a p t e r
d s D a t o s As D a t a S e t
www.detodoprogramacion.com
www.detodoprogramacion.com
C'onarldb
C o r e ~ i o nC. r e a t e C o m m a r d ( )
R e t u r n t b r i m a n d o . T e x t <>
End Function
""
MesqageBox.Show(Excepclori.Message)
End Try
E n d Sub
Simplemente se usa el metodo Open ( ) de IDbConnection para abrir la conexidn, notificando un posible fallo que pudiera producirse.
Despues se ejecutar6 el metodo RecuperarDatos ( ) que, tal y como se puede
ver a continuaci6n, prepara el comando, lo enlaza con el adaptador y crea el conjunto de datos:
P r i v a t e Sub RecuperarDatosO
Comando.CornrnandText
tbComando. T e x t
www.detodoprogramacion.com
mand
C o n e x i o n . Close ( )
E n d Sub
Observe que el DataSet se crea nuevo cada vez que se ejecuta el metodo
RecuperarDatos, de no hacerse asi, dos llamadas consecutivas al metodo,
con comandos identicos o diferentes, causarian que el conjunto de datos fuese
una combinacion de ambos resultados.
Por ultimo tenemos el m6todo VincularRejilla ( ) en el que, con dos simples asignaciones, se enlaza el DataGrid con la tabla creada en el DataSet. h a ,
a1 no haberse facilitado ningun nombre a1 llamar a1 m6todo Fill ( ) del adaptador, siempre se llama Table.
P r i v a t e Sub VincularRe]illa
DataGrid1.DataSource
Da t a G r 1 d 1 . D a t aM emb e r
End Sub
=
=
( )
dsDatos
" T ab 1 e "
No necesita ninguna preparacih adicional para ejecutar este proyecto, asumiendo que tiene instalado el proveedor para Oracle y que ha afiadido la correspondiente referencia a su ensamblado en el proyecto. De no ser asi, elimine el c6digo
que hace us0 de 10s objetos OracleXXX.
A1 ejecutar el programa tendri el formulario vacio, tal y como aparecia en la figura 16.1, debiendo seleccionarse una de las tres conexiones disponibles e introducirse un comando de seleccih. En la figura 16.2 puede ver el resultado de una
sentencia en la que se combinan las tablas de editoriales y libros. Una vez introducida la consulta, no hay m6s que cambiar de proveedor y volver a pulsar el b o t h
Recuperar para obtener 10s datos de otro origen.
De no existir las interfaces gen6ricas indicadas en el primer punto del capitulo,
la creaci6n de un programa como 6ste hubiese requerido mucho m i s cbdigo, pricticamente el triple, a1 tener que codificar la apertura y el resto de acciones de manera especifica para cada proveedor.
www.detodoprogramacion.com
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
McGrawHiII
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Anaya Multimedia
Apress
Jeff Duntemann
Francisco Charte
Francisco Charte/M Jesus Luque
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte
Chris H Pappas&William H Murr
Francisco Charte
Francisco Charte
Francisco Charte Ojeda
Francisco Charte/Jorge Serrano
Francisco Charte Oleda
Joel Spolsky
www.detodoprogramacion.com
60.5
10.52
10.52
10.52
10.75
10.52
10.75
24.04
21.04
40
37.26
39
39
40
10.75
31
www.detodoprogramacion.com
El RDBMS de Oracle es el miis utilizado a escala mundial, especialmente en sistemas de tamafio medio y grande, lo cual no es de extrafiar pues se trata de una de
las empresas con m6s experiencia en el sector, una empresa que ha hecho de su
producto de base de datos el centro de todo su negocio.
A pesar de las mejoras introducidas en las versiones 8i y 9i, lo cierto es que Oracle no resulta un RDBMS fiicil de instalar ni administrar, tarea que suele quedar
encomendada a administradores de bases de datos especializados en este producto. No obstante, como programadores acostumbrados a utilizar herramientas de
distinta naturaleza, nos debe resultar mds fiicil usar Oracle que a un usuario que
tan s610 tenga conocimientos biisicos.
En 10s capitulos de la primera y segunda parte se han dado varios pasos para, a1
final, llegar a usar una base de datos Oracle desde una aplicaci6n Visual Basic
.NET. El objetivo de este capitulo es mostrarle, de forma resumida y riipida, cu61
seria todo el proceso de configuracih necesario.
De partida, como es 16gic0, deber5 contar con un servidor en el que est6 ejecutindose el RDBMS de Oracle, conociendo el servicio a1 que quiere conectar, el nombre
del esquema y la clave de acceso. Seguramente la empresa para la que vaya a trabajar ya tenga el RDBMS instalado y en funcionamiento, per0 tambi6n es seguro que
www.detodoprogramacion.com
www.detodoprogramacion.com
El proceso de instalaci6n de Oracle9i es bastante largo, si bien nuestras intervenciones en el proceso se limitarh, en la mayoria de casos, a elegir una opci6n y
pulsar el b o t h Siguiente para ir avanzando.
En este punto puede ver un resumen del proceso y ver, paso a paso, las p6ginas
que deberia mostrarle el asistente.
Tras iniciar el instalador, ejecutando el archivo s e t u p . exe del primer CD, deber5 aparecer el Instalador universal de Oracle. Este le permite, como se aprecia
en la figura 17.2, tanto instalar nuevos productos como ver 10s que tiene instalados
o desinstalar aquellos en 10s que ya no est6 interesado. En este caso, puesto que queremos instalar el RDBMS y 10s productos de que depende, pulsariamos el citado
b o t h Siguiente.
OrklTe.""ine;;al
.
. ..
. .
. .,...
.-,- .,.
. ..
"
," - .
- .. -.- .....-
. . ..
,.%.
~.
.;--. *..,. .
.... .... .
-.
cia
_.
.- .
.-.. ..-
Bienvenido
Oracte universal Installer le guiarh en la instalacion y confuuracdn
Haga clic en "Productos lnstalados '' para ver todos los productos
Lo primer0 que tenemos que hacer, antes incluso de elegir el product0 que queremos instalar, es facilitar un nombre para el directorio raiz donde se efectuarri la
instalacih, junto con el camino completo en el que se crearri dicho directorio. De
ser necesario, facilitariamos en el apartado Origen el camino y nombre del archivo
j a r donde se encuentra el indice de productos que hay en 10s CD. Esto habitualmente no es necesario.
El instalador propone un directorio raiz por defect0 que es el que puede verse
en la figura 17.3. Lo aceptamos y pulsamos de nuevo el b o t h Siguiente.
www.detodoprogramacion.com
Ruta de ACC~SO
Finalizada la lectura del archivo j a r, el instalador nos mostrara la lista de opciones que tenemos a nuestra disposicih. En este caso son tres (vease figura 17.4),
de las cuales nos interesa, en principio, la primera, instalando la base de datos
completa en el sistema. La dejamos marcada y luego pulsamos nuevamente el bot6n Siguiente.
El paso siguiente nos permitir6 elegir una de las ediciones de Oracle9i, Enterprise,
Esta'ndar o Personal. Dependiendo de la edicidn se instalarin mas o menos servicios
y herramientas. Para el objetivo que perseguimos es indistinta la edici6n por la
que optemos, puede ser cualquiera de las tres disponibles.
A1 tiempo que se instala el RDBMS, el asistente de instalacion tambien puede
crear una base de datos evitandonos ese trabajo posterior. En la ventana que aparece en la figura 17.5 puede ver que aparecen distintas opciones. Si no quiere crear
una base de datos, sin0 instalar el software sin mis, elija So10 Software. Las demis
opciones crean una base de datos, optimizindola para el procesamiento masivo de
transacciones, el almacenamiento de datos para analisis o un us0 general. Dejamos
marcada la primera option, que aparece elegida por defecto, y pulsamos el b o t h
Siguiente.
Las bases de datos Oracle se identifican con un nombre global y un SID o identificador simple dentro del servidor. Es la information que tenemos que facilitar
en el paso siguiente. A medida que introduzcamos el nombre global veremos que
el mismo asistente propone un SID que, normalmente, aceptaremos. En este caso
(vease figura 17.6) asignamos el nombre global Libros .AnayaMultimedia.e s a
la base de datos, con el SID Libros.
www.detodoprogramacion.com
Productos Disponibles
Seleccione el product0 que dosea InStrlar.
5 Oracle91 Database 9 0 1 1 1
lndsia uoa base de dabs Masi DpCmnal prrconfQur& la% OpUDnw
Iss ufildadea y el scftwsre basrco 6el clente w e un
S ~ N ~ C Dde
D Sred
r Oracle91 Clent 9 0 1 1 1
degeslandcEatarpnse hbrsemmsdered
Us0 General
hstsia U M bage de dstos confqurada prwlamte @madswfa Mo
r Procesamlentode Transacctones
Figura 17.5. Optamos por crear una base de datos para us0 general
La ubicaci6n de las bases de datos que vayan cre6ndose suele ser el directorio
o r a c l e \ o r a d a t a de la unidad donde se haya instalado Oracle. El siguiente paso
www.detodoprogramacion.com
del asistente, no obstante, nos permite especificar el directorio que deseamos emplear, pudiendo dejar el indicado por defecto o cambiarlo.
...
'
__
. . . . .'2-s
...
kill
de 3315s
.... - ..
._I_. .
.
__ I . r o m n ~ e a e l a B 3 s e a e D a l o s G ~ aL ~t ar ~x -111 x l - i r w ~3 E i j
...
....
I/
Libros
El paso siguiente serfi la elecci6n del conjunto de caracteres que se utilizara para almacenar la informacih en la base de datos. Tendremos tres opciones: el juego
de caracteres por defecto del sistema, el juego de caracteres Unicote o bien cualquier otro que nos interese seleccionfindolo de una lista.
Llegamos a la ventana resumen de la instalacih, mostrada en la figura 17.7. Es
el punto en el que debemos revisar todos 10s parhmetros y a continuacih pulsar el
b o t h Instalar, si todo es correcto, o bien retroceder y cambiar aquellas opciones
que deseemos.
Tras pulsar el b o t h Instalar nos limitaremos a ir cambiando el CD-ROM del
producto, a medida que lo solicite el instalador, o bien indicar el directorio donde
se encuentra el contenido de cada uno de ellos, en caso de que hayamos dejado 10s
paquetes descomprimidos en directorios individuales.
A1 final de la copia de archivos se pondrh en marcha la configuracih de las distintas herramientas. Se iniciarfi el servidor HTTP de Oracle (una versi6n personalizada de Apache), el agente inteligente de Oracle y, como se aprecia en la figura 17.9,
se invocarfi a1 asistente de configuracih de bases de datos.
El proceso de generacih de la base de datos, en el que prhcticamente no tendremos que intervenir, irh abriendo algunas ventanas de consola que se cerrarhn
automfiticamente, no tiene que actuar sobre ellas. El proceso de creaci6n de la base
de datos quedar6 reflejado en una pequeiia ventana (vease figura 17.10). Se copiawww.detodoprogramacion.com
r6n del CD-ROM 10s archivos de una base de datos tipo, poniendo en marcha un
servicio Windows que ser6 el que atienda las solicitudes de conexi6n.
Requutos de Espaclo
L401urnen C\Necesarios 1 U l G B Disponibies 28 42GB
+?@dancedReplication 9 0 1 1 1
www.detodoprogramacion.com
Herramientas de Configuracion
r3ce
Oracle Intelligent agent
en curso
pendiente
fl
fl
Tennban&Creaci&tUeBasede~os
Creaaon 6e ba3e de datos donica en curso
___
I____
_____I
__
___-
__
---
I~
PonerChute pius
Enterpire ManagementP ~ d s
'!Mhale
:W;inRAP
i
~
__
__
___
Para poder conectar con una cierta base de datos Oracle, es indispensable conocer el nombre del servicio. Este se define en el momento de la creacion en el servidor, siendo necesaria tambien una definici6n en 10s clientes. Nuestra base de datos
www.detodoprogramacion.com
inicial, generada por el asistente, es reconocida en el propio servidor con el nombre de servicio L i b r o s
] M&va
__
proon
-- __ --
Yec
Eavontos
Ven_tana
-~
A&
08
del Ststema O p r a b v o
Cada base de datos cuenta con una serie de esquemas en 10s que se alojan 10s
distintos elementos, como tablas, vistas o procedimientos almacenados. Existe un
esquema por defecto, scott, que hemos usado en todos 10s ejemplos de 10s capitulos previos en 10s que se utilizaba la base de datos Oracle creada en el tercer capitulo. Puede crear su propio esquema y personalizarlo, si no quiere emplear 4ste.
Desde un sistema en el que se instale la plataforma Microsoft .NET, indispensable para ejecutar cualquier aplicaci6n creada con Visual Basic .NET, es posible acceder a multiples origenes de datos sin necesidades adicionales, ya que t a m b i h se
instalan 10s MDAC. Esto significa que podemos usar una base de datos Access,
una hoja de cdculo Excel o comunicarnos con un servidor SQL Server sin necesitar
ningun software adicional.
No es posible, sin embargo, una comunicacion directa con todos 10s productos
RDBMS disponibles en el mercado, especialmente cuando son de diversos fabricantes y, por lo tanto, emplean distintos medios de comunicacih entre cliente y
www.detodoprogramacion.com
servidor. Por ello es necesario instalar en cada ordenador cliente el software que
facilite el fabricante del RDBMS, en este caso el software cliente de Oracle9i.
La instalaci6n de dicho software cliente se inicia con el mismo proceso explicad0 en el punto dedicado a la instalaci6n de Oracle9i, simplemente eligiendo la
opci6n OracleSi Client en lugar de OracleSi Database en el paso del asistente que
aparece en la figura 17.4. A1 finalizar el proceso, tendri en el ordenador 10s elementos necesarios para comunicarse con el RDBMS Oracle9i remoto.
Con algunos RDBMS, como es el caso de SQL Server, basta con instalar el software cliente para, desde una aplicacGn, conectar con una base de datos que se encuentra en el servidor. Para ello ese cliente debe indicar el nombre o direcci6n del
ordenador que actua como servidor, asi como la base de datos que se desea abrir.
Estos datos corresponden con 10s parimetros Data Source e Inicial Catalog
de la cadena de conexi6n.
Sin embargo, a1 usar Oracle el cliente no tiene porque conocer ni el servidor
donde se ejecuta el RDBMS ni la base de datos, el valor asignado a1 parimetro Data Source es el nombre de servicio local con el que se conoce a la base de datos.
Ese nombre de servicio hay que definirlo, usando para ello el Asistente de Configuracion de Red de Oracle que se instala como parte del software cliente. Este proceso se describi6 en el sexto capitulo, puede recurrir a 61 para recordarlo.
cuando haga falta. Nuestra aplicaci6n usaria 10s objetos de este proveedor, segun
se ha descrito en 10s capitulos de la segunda parte, facilitando en la cadena de COnexi6n no el nombre del servidor RDBMS O del servicio remoto, sin0 el nombre de
servicio local que ha sido definido para acceder a esa base de datos. Adem6s puede ser necesario facilitar el nombre de esquema/usuario, por ejemplo S c o t t , y la
clave de acceso correspondiente.
Con esto ya tendria su aplicaci6n Visual Basic .NET, funcionando sobre Windows
y accediendo a un RDBMS Oracle9i, sin importar que 6ste se ejecute tambi6n sobre
Windows o cualquier otro sistema operativo. Como puede ver, el proceso para acceder a la base de datos mas usada desde el lenguaje de programaci6n m6s popular no es demasiado complejo.
www.detodoprogramacion.com
www.detodoprogramacion.com
A1 operar sobre sistemas RDBMS, una parte de 10s origenes de datos que hemos
usado en capitulos previos lo son, es habitual utilizar transacciones que aseguren
la integridad de 10s datos, especialmente cuando se actua sobre multiples tablas.
En ninguno de 10s ejemplos propuestos hasta ahora nos hemos ocupado de las
transacciones, dejando el aseguramiento de esa integridad en manos de ADO.NET
y el RDBMS con el que se conectaba. En ocasiones, sin embargo, puede ser precis0
un control explicito del inicio y fin de la transaccibn, momento en el cual necesitaremos emplear el objeto Transaction del proveedor adecuado tal y como se explica en 10s puntos siguientes.
Todos 10s sistemas RDBMS considerados como tales, Oracle y SQL Server son
dos ejemplos, conternplan el us0 explicito de transacciones. Una transacci6n asegura que todas las operaciones efectuadas en su bmbito, desde que se inicia hasta que
se cierra, se ejecutan de forma satisfactoria o no se ejecuta ninguna de ellas. Esto nos
garantiza la integridad de la informacih almacenada en la base de datos.
Imagine que, en una aplicaci6n Visual Basic .NET, codifica una serie de adaptadores de datos y DataSet para actuar sobre dos tablas: una que contiene encabezados de factura y otra que almacena las filas de detalle. A1 efectuar parte de la
actualizacih, luego de ejecutar el m6todo Update ( ) del primer adaptador que,
www.detodoprogramacion.com
pongamos por caso, es el de las lineas de detalle, se produce un fallo de alimentaci6n o una interrupci6n en las comunicaciones, de tal forma que se han enviado a1
servidor las lineas de detalle per0 a1 intentar el Update ( ) para enviar la cabecera
se produce un error. En este momento en la base de datos existe una inconsistencia
patente, dado que no es posible encontrar 10s datos del cliente y la factura a la que
pertenecen las lineas. Para evitar esta situaci6n debe utilizarse una transacci6n.
Esta se iniciaria antes de la prirnera actualizacih y terminaria tras la ultima. En
ese ambito las operaciones se registran de forma temporal, confirmandose si todas
se reciben satisfactoriamente o descartandose si se produce cualquier evento que
impida mantener la integridad.
Una forma de asegurar la integridad de 10s datos en operaciones como la descrita, y que se dan constantemente en la mayoria de aplicaciones, consiste en emplear
el sistema de transacciones de la propiedad base de datos. Para ello lo habitual es
codificar procedimientos almacenados en la base de datos, de tal forma que las
aplicaciones, cuando necesitan efectuar alguna operacih, invocan a1 procedimiento
almacenado facilitandole 10s parametros necesarios, ocupandose 6ste de realizar
la manipulacion de las tablas.
El control de transacciones en la base de datos se efectuard con las sentencias
propias del lenguaje de cada RDBMS, por ejemplo PL/SQL en Oracle o T-SQL en
SQL Server. En el caso de T-SQL las sentencias a conocer son estas tres: BEGIN
TRANSACTI ON, COMMIT TRANSACT ION, ROLLBACK TRANSACT I ON. La primera
inicia una nueva transaccih, la segunda la confirma y la tercera la revoca. Dado
que en SQL Server las transacciones pueden anidarse, cada una de estas sentencias
ira seguida de un identificador propio.
Suponga que quiere tener en la base de datos SQL Server creada como ejemplo
en el tercer capitulo, un procedimiento almacenado a1 que facilitandole el c6digo
de una editorial elimine todos 10s libros que le pertenecen y la propia editorial. Esto requiere dos sentencias DELETE y, para evitar que la operacih pudiese interrumpirse entre ellas, las introducimos en una transacci6n. El procedimiento almacenado
podria ser el siguiente:
Observe que a1 final del m6todo no se utiliza una sentencia COMMIT, que seria
lo habitual para confirmar la operacion, sino ROLLBACK, de tal manera que las dos
www.detodoprogramacion.com
>
Cwndetado el proceso wr lotes de la conwlta
0 00 00
0 Rlas
i n 1, Col 28
.........____....... _.__
.
......._
~ . _ _..-.._t.,_...I_._
.^__...
. ......._..._
~
dos m6todos:
www.detodoprogramacion.com
Rollback
( ) : Revoca
la transacci6n.
Para crear una transaccion asociada a una cierta conexion, como puede deducirse de 10s miembros existentes en la interfaz IDbTransaction, bastaria con
asignar a la propiedad Connection la referencia a la conexi6n. Una alternativa es
emplear el metodo BeginTransaction ( ) de la interfaz IDbConnection, implementado en el objeto Connection de cada proveedor.
Ese objeto tiene que asociarse tambien con cada uno de 10s comandos que vayan a ser ejecutados y que se desea que queden bajo el dmbito de la transaccion.
Con este fin, en la interfaz IDbConnection hay definida una propiedad llamada
Transaction.
Creada la transaccion y enlazada tanto con la conexion como con 10s comandos,
usariamos el metodo Commit ( ) o Rollback ( 1, tras ejecutar todas las operaciones de actualizacion, para confirmar o revocar la transaccion y, por tanto, todas
las operaciones ejecutadas durante su tiempo de vida.
Veamos en la practica como crear y controlar una transaccion desde un programa Visual Basic .NET, empleando para ello el proveedor de SQL Server.
El metodo BeginTransaction ( ) de Sqlconnection, asi como 10s metodos
Commit ( ) y Rollback ( ) de SqlTransaction, en realidad hacen us0 de la gestion de transacciones propia del RDBMS, mediante las sentencias comentadas anteriormente.
Comenzaremos insertando en un formulario 10s componentes que pueden verse en la figura 18.2. Hemos arrastrado la tabla Libros de la base de datos SQL
Server desde el Explorador de servidores hasta el diseiiador, utilizando el menu
emergente de SqlDataAdapterl para generar el conjunto de datos DsLibrosl.
Los principales elementos de interfaz son un cuadro de texto para introducir el
c6digo de una editorial, un b o t h para seleccionar las filas, que aparecerdn en el
DataGrid que hay debajo, y un segundo boton que eliminaria esas filas del origen
de datos.
www.detodoprogramacion.com
Dates
Format0
Herramlentas
p Debug
'3@*33-.
1 :
En principio no existe ningun vinculo entre 10s elementos de interfaz y 10s componentes de acceso a datos, vinculo que se establecer6 a1 pulsar el b o t h Seleccionar. Este ejecuta el c6digo siguiente:
.(ByVal s e n d e r As System.Ob]ect,
Priva
ByVal e As Systern.EventArgs) Handles btnSelecc1onar.Click
~
&
DataViewRowState.CurrentRows)
www.detodoprogramacion.com
I g L i b r o s . Datasource = V i s t a
E n d Sub
P r i v a t e Sub b t n E l i m i n a r ~ C l i c k ( B y V a 1s e n d e r As S y s t e r n . O b ] e c t ,
B y V a l e As S y ~ t e m . E v t ? n t A r g s ) H a n d l e s b t n E l i m i n a r . C l i c k
Dim I n d F i l a As I n t e g e r
While V i s t d . C o u n t
> 0
Virta(O).Delete()
End W h i l e
sq
De
DsLibrosl.Clear()
www.detodoprogramacion.com
Sqlconnectionl .Close i )
End Sub
17
11
13
14
4
15
12
10
0 471 37523 3
84 415 1255 8
84 415 1202 7
84 415 1132 2
84 415 1230 6
84 415 1291 4
84 415 1324 4
84 41 5 1145 4
84 41 5 1230 2
84 415 1261 2
84 415 1351 1
84 415 1392 3
84 41 5 1376 7
8441511365
SQLServer2000
Jeff Duntemann
Francisco Chaite
Francisco Charte/
Francisco Charte
Francisco Charte
Fiancisco Charte
F ~ a n c ~ Charle
co
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte
Fiancisco Chaite
Francisco Chartet
Francisco Charte
1
1
1
1
1
1
1
1
1
1
1
1
1
1
60 5
1052
1052
1052
10 75
1052
1075
24 04
21 04
37 26
33
39
40
10 75
..* A
www.detodoprogramacion.com
e bloqueo y actualizacion
A la hora de codificar una aplicacidn en la que van a obtenerse datos que, posteriormente, deben ser actualizados, hay que elegir una politica de bloqueo y de
www.detodoprogramacion.com
actualizacion. Bisicamente existen dos opciones: bloqueo optimista y bloqueo pesimista. Hay una tercera, aunque generalmente no es aceptable en la mayoria de
aplicaciones, a la que se hace referencia como el u'ltimo gana.
El bloqueo pesimista consiste en bloquear las filas que presumiblemente van a
actualizarse desde el mismo momento en que leen de la base de datos, lo cual significa que ningun otro cliente puede tener acceso a ellas hasta que el proceso de
modificacibn y actualizaci6n termine. Es una politica que requiere mantener una
conexi6n abierta con el servidor todo el tiempo que dure ese proceso, porque de lo
contrario no podria mantenerse el bloqueo sobre las filas. Sus inconvenientes son
muchos, siendo el m6s importante que s610 un usuario puede tener acceso a las filas en cada momento, lo cual no suele ser aceptable en aplicaciones que se ejecutan
en multitud de clientes contra una misma base de datos.
La politica de bloqueo optimista s610 bloquea las filas que van a ser modificadas o eliminadas y s610 en el momento de la actualizaci6n. Asi, en caso de que un
programa, como 10s usados a mod0 de ejemplo en capitulos previos, recupere una
lista de 10s titulos existentes en la tabla L i b r o s , esto no implicar6 que ningun otro
cliente pueda obtener esos mismos datos. No es necesario mantener una conexi6n
continua con el servidor, ya que el bloqueo se estableceria s610 en el momento de
ejecutar la sentencia UPDATE, no a1 seleccionar datos. El bloqueo optimista tiene el
problema antes planteado: ya que varios usuarios pueden acceder a las mismas filas, hay que controlar la posibilidad de que dos o m6s de ellos efectuen cambios en
la misma fila. ADO.NET nos facilita 10s eventos y excepciones necesarias para ello.
En cuanto a la politica de el ultimo gana, es tan simple como asumir que en la base de datos s610 permanecer6n 10s datos que se escriban en ultimo lugar, es decir,
si varios usuarios modifican una misma fila, se perderAn todos 10s cambios excepto 10s del ultimo en enviarlos a1 RDBMS. Como se decia antes, suele ser una opci6n
inaceptable en la mayoria de 10s casos.
Cuando se crea un adaptador de datos, ya sea directamente a1 arrastrar una tabla desde el Explorador de servidores o tal y como se describi6 en 10s capitulos de
www.detodoprogramacion.com
I_
Veamos c6mo aprovechar el evento RowUpda ted para ofrecer informacih sobre el proceso de actualizaci6n, aunque sin resolver el problema puesto que los
cambios efectuados por el usuario que no se hayan podido escribir en el origen se
perderan, a1 menos en este primer acercamiento a la soluci6n final.
Partimos disefiando un formulario como el que aparece en la figura 19.1, con un
DataGrid y un b o t h como unicos elementos de interfaz. En la parte inferior del
diseiiador puede ver la conexibn, adaptador y conjunto de datos, generados con el
Explorador de servidores. Vinculamos el DataGrid con la unica tabla del DataSet.
A1 abrirse el formulario se ejecutara la sentencia SqlDataAdapterl. Fill (dsLibrosl, "Libros"),mostrando asi las filas de la tabla en la cuadricula desde
un primer momento.
Cuando se pulse el bot6nActualizar procederemos a llamar a1 metodo Update ( )
del adaptador, refrescando el contenido del DataSet para obtener 10s cambios
que pudiesen haberse ejecutado desde otros puestos:
I
I _
www.detodoprogramacion.com
s1.L
nrchivo
Edition
Yer
Proyecto
enmar
- _
t1rto-
Depurar
Datos
Herrarmentas
I/
Ventana
Aygda
-.-
__
I
Si no hemos cambiado ning6n dato, 10s datos de la cuadricula mostrarin cambios que otros clientes puedan haber efectuado, per0 no se desencadenarfi en ning6n momento el evento RowUpdated.Esto tan s610 ocurriri una vez por cada fila
modificada, ejecutfindose el c6digo siguiente:
Pr
lDat
ed(ByVa1 serider A s O b j e c t ,
ByVal e A s System.Data.SqlClient.SqlRowUpdatedEventArgs)
Handles SqlDataAdapter1.RowUpdated
~
I f e.Status
UpdateStatus.ErrorsOccurred Then
MessageBox.Show(e.Errors.Message & vbCrLf & e. Row. Item("Autor", DataRowVersion. Original) & vbCrLf & e.Row. Item("Autor", DataRowVersion.Current) )
www.detodoprogramacion.com
e.Status
End I f
End Sub
UpdateStatus.SKipCurrentRow
Como puede ver, comprobamos si el estado indica la existencia de un error, caso en el que mostramos por la consola el mensaje, el valor original que tenia la fila
y el que nosotros pretendiamos darle en una de las columnas, que es la que pretendemos modificar a mod0 de ejemplo. Por ultimo asignamos el valor Updates tat u s . SkipCurrentRow a la propiedad Status, impidiendo la generaci6n de la
excepci6n DBConcurrencyException a1 tiempo que se ignoran 10s cambios de la
fila.
Si ejecuta el programa, efectcia cualquier cambio y pulsa el b o t h Actualizar
todo ir6 bien. Para provocar un error tendr6 que ejecutar dos copias del programa
y cambiar la misma fila, o bien hacer alguna modificaci6n desde el Administrador
corporativo. En esos casos nos encontraremos con una situaci6n como la de la figura 19.2. Observe el mensaje de error.
1 89311534 1
84 415 1136 5
84 415 1324 4
84 4151332 9
84 415 1376 7
84 415 1351 1
84 415 1290 6
84 415 1231 4
84 41 5 1261 2
84 415 1255 8
84 415 1230 2
84 415 1202 7
8441511322
84 41 5 1145 4
SOLserver 2000
Guia ptactica para usuaiiosJBuilder 7
PiogramacionconVisual C# NET
Ptogiamacion con Visual Studio NET
ProgramacionconVisual Basic NET
Gum practica paia U Q U ~ ~ I OdeVisual
S
Basic
Guia practica paia wuarios de Visual Studio
Piogiamacion con Delphi 6 y Kylix
Guia piactica pata usuams de Delphi 6
Manual avanzado Excel 2002
Gum practica paia U S U ~ ~ ~deO Excel
S
2002
JoelSpolsky
Francisco Charte
Francisco Charle
Francisco Charle
Fiancisco Chaite/Jorge Seriano
Francisco Chaite
Francisco Charte
Francisco Charle
GuiapracticapatausuariordeKylix
lntioduccion a la piogiamacion
El ejemplo anterior es titil porque notifica a1 usuario que ha surgido un problema de concurrencia y, por lo tanto, 10s cambios que ha efectuado se perderdn. No
obstante, se le obliga a, tras haber actualizado 10s datos que tenia en el DataGrid,
www.detodoprogramacion.com
Dim M e n s a j e As String =
String.Forrnat("Va1or actual='{O]', " & "Valor original='{l}', Valor propuesto='t2}'",
FilaOriginal .Autor,
Fils. Item( " A i i t ~ r " , DataRowVerslon.Orlglria1),
Fila. Item("Autor", DataRowVersion.Current 1
~
MessaqeBoxButtons.YesNo)
scribir cambios?",
DialogResult.Yes Then
DsLibrosl.Merge(DatosActuales, True1
SqlDataAdapterl.Update(DsLibrosl.Libros)
www.detodoprogramacion.com
E n d If
E n d Sub
Observe que se muestra tan s610 el valor de la columna Auto r, asumiendo que,
para realizar pruebas, va a modificarse esa columna y no otra. En la prActica, en
lugar de este simple mensaje seria mucho mAs adecuado preparar un formulario
en el que el usuario pudiese ver todos 10s valores que el ha introducido y 10s que
hay en la base de datos actualmente, pudiendo elegir que quiere hacer.
Tambien debe tenerse en cuenta que este metodo, a1 ser invocado desde el metodo RowUpda te, se ejecuta asumiendo que va a pulsarse el b o t h Actualizar tras
modificar cada fila. Esto no tiene necesariamente que ser asi, ya que el usuario podria modificar varias filas. Podria automatizarse la llamada a1 metodo Update ( )
del adaptador cada vez que se detectase un cambio de fila comprobando que en
ella se han efectuado cambios. Otra posibilidad es no usar el evento Rowupdate
sin0 interceptar el evento DBConcurrencyException a1 llamar a1 metodo Update ( ) . Si &te se genera, podriamos recorrer el conjunto de filas que tienen un error
y mostrarlas todas a1 usuario de una sola vez, en lugar de consultar una a una.
I/
Valor actual='Francisco Charte Ojeda', Valor original='FranciscoCharte Ortega', Valor propuesto='Francisco Charte'
/I
I1
www.detodoprogramacion.com
..*..,..,*'
..*.~
.,.
.'.,"~..
..
,*:
a;:?
.
.
x
'~._.
'
~.<
..
'
L
,
'
www.detodoprogramacion.com
.. ' .
Cuando se ejecuta un comando de seleccidn de datos, ya sea obteniendo un Dat a R e a d e r o bien mediante un adaptador para generar un D a t a S e t , siempre obtenemos un conjunto de filas predefinidas en las tablas de la base de datos y con
valores que est6n almacenados en ellas. En ocasiones, sin embargo, pueden ser necesarios datos adicionales que pueden calcularse a partir de 10s datos de las columnas, no siendo 16gico afiadir nuevas columnas en las tablas de la base de datos
para almacenarlos.
Suponga que necesita mostrar en un D a t a G r i d el titulo de cada libro, el autor,
el precio, el IVA y el precio neto. En la tabla L i b r o s tan s610 existen las tres primeras columnas, per0 no el IVA o el precio neto. No tiene sentido aiiadir esas columnas a las tablas de la base de datos, ya que ocuparian un espacio innecesario al
poder calcular sus valores.
En este capitulo ver6 c6mo puede definir esas columnas calculadas, ya sea en la
propia sentencia SQL o aiiadiendo una columna a1 D a t a T a b l e , para evitar tener
que calcular y aiiadir esos valores manualmente, mediante c6digo.
operadores aritm&ticosy relacionales y, segun el RDBMS, algunas funciones intrinsecas. En la siguiente sentencia de ejemplo se calcula el IVA creando una nueva columna llamada IVA, tomando como base la columna P r e c i o ya existente:
S E L E C T Titulo, A u t o r ,
Precio,
Precio
0 . 0 4 A S I V A FROM L i b r o s
A1 estar definida en la propia sentencia, la columna aparece a ojos de 10s D a t a y D a t a A d a p t e r como si de una columna m i s se tratase aunque, como es
logico, seria una columna s610 de lectura, a1 no existir fisicamente en la base de datos. Para realizar una prueba sencilla y rdpida, d&10s pasos siguientes:
Reader
Vincule el D a t a S e t con un D a t a G r i d .
spwfiguelainsmraonSelectde59Lo~lcedCeneradwdecawltaspxaB~
rafiramentela ccrsulta
datoz dcbcriaca-r
de maltas...
www.detodoprogramacion.com
Ttdo
Autor
Jeff Dunternann
Fiancisco Chaite
Francisco ChattdM Jesus Luque
Francisco Charte
Francisco Charte
Francisco Charte
Francisco Charte Oleda
Francisco Charte
Francisco Charte
Chrlr H Pappa&Wllkam H Murray
Francisco Charle
Francisco Charte
Francisco Charte
Francisco ChartdJorge Seriano
Francisco Charte Opda
Joel Spolsky
Precn
I IVA
60 5
242
1052
10 52
1052
1075
1052
1075
2404
21 04
40
3726
39
39
40
1075
31
04208
0 4208
0420s
043
04208
043
09616
08416
16
14904
1 56
1 56
16
043
1 24
IDLhro
17
11
13
14
8
9
4
15
12
16
10
7
6
3
2
Consulte la informacion de referencia del RDBMS que este usando para saber
que operadores y funciones puede emplear en una sentencia de seleccion para
crear columnas calculadas.
Como ya sabe, 10s objetos DataTable disponen de una coleccibn, accesible mediante la propiedad Columns, compuesta de objetos Datacolumn, cada uno de
10s cuales representa a una columna recuperada de las tablas del origen de datos.
En multiples ejemplos hemos recorrido esa colecci6n para mostrar todas las columnas de una tabla o conocer sus atributos.
Lo mbs interesante, es que la colecci6n a la que apunta Columns no es estbtica,
siendo posible afiadir nuevos objetos Datacolumn segun se necesite. AdemAs, esos
nuevos Datacolumn no tienen necesariamente que representar a una columna de
la base de datos, pudiendo, en su lugar, alojar una expresi6n.
at
A1 crear un Da t acolumn podemos usar distintos constructores sobrecargados
que aceptan diferentes listas de par5metros. Con ellos es posible crear una nueva
columna sin establecer propiedad alguna o bien, por el contrario, asignar valor a
las mbs relevantes. Las propiedades que mbs nos interesarbn, en este caso, son las
siguientes:
www.detodoprogramacion.com
www.detodoprogramacion.com
tablas que lo componen, o sus columnas, sino que tambien podemos introducir
cambios. Ademas, esos cambios se traducen automhticamente en modificaciones a
la clase derivada de DataSet, con lo que las nuevas columnas aparecerian como
propiedades adicionales de esta.
Partiendo del anterior, d6 10s pasos siguientes para ver un sencillo ejemplo:
Elimine la sentencia introducida en el punto anterior con la que se creaba el
Datacolumn con el precio neto.
Pulse en la ultima fila de la tabla, que aparece como un recuadro en el disefiador, e introduzca directamente el nombre y tipo. Tambikn puede escribir
y seleccionar esos datos en la ventana Propiedades.
Escriba en la propiedad Expression la expresi6n de calculo, en este caso
P re c io + IVA.
brchivo
kddo6n
yer
Libros
Titulo
Autor
PEClD
0
b
IVA
IDLibro
Neto
P_royecto Cenerar
Depurar
Ezquerna
Herramlentas
VeDtana
Ayuda
(Lrbros)
string
string
decimal
decimal
int
decimal
ewnt
(Predetermmado)
(Predetermmado)
(Predetermmado)
Precio+IVA
(Predetermmado)
(Predeterminado)
(Coleccion)
0
11
Net0
(Predeterrnmado)
true
ReadOdY
I1
,/
SubsbtL-tl5#GrOup
decimal
I w=
I 0 DataSet
8 XML
-_
--
--_
LlStO
I t
__
www.detodoprogramacion.com
I,
A1 compilar y ejecutar el programa ver6 que obtiene exactamente el mismo resultado que tenia en la figura 20.3, con la diferencia de que ahora no ha tenido que
escribir c6digo alguno. Aparte est6 la ventaja de que la nueva columna aparece como una propiedad de d s l i b r o s , de tal manera que el editor de c6digo la muestra
como un elemento m6s. Esta ventaja no la teniamos a1 crear el Datacolumn mediante c6digo.
i
3
I=.
,9
F i k l i c : I s = Forml
InhrLirc: System.Windows.Forms.Form
F o r m l ~ L o a d ( E ; ~ ~ sender
~l
Jz System.Ob>ect, E
SqlDataAdapterl . F i l l (DsLibrosl, "Libras")
P L ~ -tTc
,
rj
a Item
a ItemArray
a IVA
RelectChanger
aRowError
a Rowstate
I-.
tin 145
CoI 28
Car 28
IN5
Consulte la ayuda de la propiedad Expression de la clase Datacolumn para saber que operadores y funciones puede usar para crear sus expresiones.
www.detodoprogramacion.com
www.detodoprogramacion.com
Para empezar, tendremos que aiiadir a una de nuestras bases de datos una nueva columna, en la tabla L i b r o s , para almacenar la portada. Ya sabe que puede
www.detodoprogramacion.com
modificar la estructura de las tablas directamente desde Visual Studio .NET, por
lo que no necesita recurrir a herramientas especificas del RDBMS.
En este caso vamos a tomar, una vez m6s, la tabla Libros de SQL Server, aiiadikndole, como se aprecia en la figura 21.1, una columna llamada Portada de tip0
image. Permitiremos 10s valores nulos. De hecho, a1 tener ya la tabla una serie de
filas, el valor original de la columna Portada ser6 DBNull en todas ellas. Si utiliza las Visual Database Tools para editar el contenido de la tabla, o incluso el Administrador corporativo, ver6 que la columna Portada aparece siempre como <Binario>
(v4ase figura 21.2), no siendo posible ni ver su contenido ni modificarlo. La unica
opcion, por tanto, es crear un programa a medida que facilite esas operaciones.
' Libros - Base de datos de SQL Server zoo0 [disehr]
!rchvo
Edition
Yer
Proyecto
Ea5e de datos
iarchar
varchar
Diagrarg
50
50
VeEtana
'iz
r
.
-.
-I
"*---..
Aygda
Columnas
Descripct6n
Valor predeterminado
Formula
E l R
JP
13
.sto
w
il
I Titulo
IISBN
IDLibro
...
I Autor
dbo.libros :l a N5PIRON.Llbror)
Precio
IEditorial
1-893115-94-1
84-415.1136-5
84-4 15-1324-4
84-415-1392-9
84-415-1376-7
84-415-1351-1
84-415-1290-6
84-415-1291-4
84-415-1261-2
31
10.75
10,75
39
40
39
10,75
10,52
37,26
lo, 52
21,04
10,52
10,52
24,04
40
60,5
L'alue
www.detodoprogramacion.com
...
&I , LL,ataFuiml
doFirr 1
c k ]
Libros
IDLibro
ISBN
Tdulo
(Libros)
int
string
string
Autor
rtnng
Editorial
int
.b
b ' ditibtos
d-tibtv, its
t dsL&ros.xs
dsLibros.xs O
(Predeterrnmado)
fixed
(Predeterrninado)
'
ni lla ble
(Predeterrninado)
(Predeterrnmado)
de datcs de esk d m t o
Diseiiaremos un formulario Windows en el que podamos ver la portada asociada a cada libro, asi como modificarla si es necesario. Partiendo de un proyecto estAndar, elimine el formulario y emplee el asistente para formularios de datos con
el fin de generar una ventana que permita editar la tabla fila a fila, con controles
individuales, en lugar de usando un D a t a G r i d . Esto nos permitir6 afiadir f6cilmente un P i c t u r e B o x en el que mostrar la imagen.
.
'
.. ''I
Si prefiere basar el formulario en un D a t a G r i d , tendra entOnCeS que COntrOlar la pulsacion sobre la columna correspondiente a la portada a fin de abrir una
www.detodoprogramacion.com
ventana secundaria con el P i c t u r e B o x . Tambien puede personalizar la cuadricula, creando para ello una nueva clase de columna que sea capaz de mostrar la imagen.
Extienda las dimensiones del formulario creado por el asistente, hacihdolo
m6s alto, a fin de introducir en el Area inferior izquierda un control P i c t u r e B o x
con un b o t h debajo, como se puede ver en la figura 21.4. Inserte t a m b i h un componente O p e n F i l e D i a l o g y edite su propiedad F i l t e r para que facilite la selecci6n de archivos con grificos.
Arthvo
Edition
rer
Proyecto
Generar
Depurar
Datgs
Herramlentas
VeEtana
Aygda
Debug
DataFormLvb [Diseiio]*
.i:t )
3,
..........
JrY*33-.
. . . . . . . . .
. . . . . . . . . .
CddExtem;,On
r------
Titdo
DpenFileDialog1
True
CkeckFileEusts
CheckPathEasts
CefaultExt
True
True
Dereferenceiinks
True
IIVOS
Filterirdex
grlficos I *.bm
XnctialDrectw
RestoreDrector,
Friend
False
False
False
5howHelp
False
ShOwReadOnly
Title
False
ialidateNam
True
Modifiers
Multirded
ReadOnlyChecked
,Itado,
a
lj
!I
En principio el Pi c t u r e B o x no contendr6 ninguna imagen, pudiendo obtenerla de dos formas distintas: recuperdndola de la columna P o r t a d a de una fila de la
tabla L i b r o s 0,en caso de que se pulse el b o t h que hay debajo, directamente desde un archivo.
www.detodoprogramacion.com
~____-_ - _ _ - _ I
"-
___-___
_ _ _ _ l _ -
"-l_l_--^
- - _ _ I
____
__--- -
El c6digo generado por el asistente de creaci6n de formularios de datos se encarga de la vinculacih de todos 10s controles que hay en la ventana, per0 16gicamente no del PictureBox que hemos aAadido nosotros. Este no puede vincularse
directamente con la columna Portada de dslibros, puede intentarlo abriendo
la ventana DataBindings del PictureBox. Tenemos, por tanto, que codificar el
proceso de recuperacih de la imagen contenida en la columna para mostrarla en
el PictureBox.
Aprovechando que todos 10s metodos que causan una actualizacih de 10s datos visibles en el formulario, como 10s botones de navegacion, invocan siempre a1
metodo Positionchanged ( ) , introduciremos en el todo el c6digo necesario.
Primer0 necesitamos saber c u d es la fila actual de datos que est6 mostrindose
en el formulario, puesto que no podemos mostrar la portada de cualquier fila del
DataTable, sino la indicada por el BindingManagerBase que corresponda. Teniendo la position, comprobamos si la columna Portada de esta fila es nula o no.
Si no es nula tenemos una imagen a mostrar, per0 no podemos asignar directamente el valor de Portada, recuerde que es un arreglo de tip0 Byte, a la propiedad
Image del PictureBox, ya que 10s tipos no son compatibles.
El truco est6 en crear un flujo de datos en memoria, un objeto MemoryStream,
que contenga la secuencia de bytes alojada en la columna Portada, usando despues el metodo FromStream ( ) de la clase Image para mostrarla en el PictureBox.
Por ultimo, en caso de que la columna Portada sea nula, y por lo tanto la propiedad I s PortadaNull devuelva True, procederemos a eliminar el contenido
actual del PictureBox, mostriindolo como una superficie negra.
El metodo Positionchanged ( ) completo quedard como se muestra a continuacion. La primera sentencia es la generada por el asistente para actualizar la indicaci6n de fila actual.
Private Sub o b j d s L i b r o s-P o s i t i o n C h a n q e d ( )
M e . 1blNavLocation.Text = ( ( (Me.BindingContext (
o b j d s l i b r o s , " L i b r o s " ) . P o s i t i o n t 1 ). T o s t r i n g
"
d e ' I ) t M e . B i n d i n g C o n t e x t (objdsLibros, " L i b r o s " ) .Count . T o S t r i n q )
~
-I
D i m P o s i c i o n = B i n d i r l g C o n t e x t (obldsLibros,
"Libros") .Position
I f N o t ob]dsLibros.Libros(Pesiciori).IsPortadaNull Then
0
Dim I m a g e n As New MernoryStrearni
www.detodoprogramacion.com
E i c t u r e B rxl . C r e a t e G L a r h i c - ( )
.r l e a r
( c o l o r .B l a c k )
End If
End Sub
Si ejecuta el programa tras introducir estos cambios, podrb navegar por las filas
de datos y observar que el P i c t u r e B o x siempre aparece como una superficie negra. Es logico, ya que ninguno de 10s libros cuenta actualmente con una portada en
la base de datos.
1
I
Para llegar a tener alguna imagen en la base de datos, es nuestro objetivo, tendremos que responder a1 evento C l i c k del b o t h que hay bajo el P i c t u r e B o x
con dos fines: mostrar la imagen seleccionada en el P i c t u r e B o x , simplemente a
mod0 de informacih de retorno porque ello no indica que la imagen exista en la
base de datos, y asignar dicha imagen a la columna P o r t a d a de la actual fila de
datos.
La clase Image cuenta con un metodo F r o m F i l e ( ) capaz de recuperar la imagen del archivo y mostrarla en el P i c t u r e B o x . Los Datacolumn, por el contrario,
no disponen de un metodo similar. No podemos, sin mbs, asignar un nombre de
archivo a la columna P o r t a d a . Ya sabemos que su tipo es B y t e ( ) . Por lo tanto,
tendremos que recuperar la imagen en memoria, como si fuese una secuencia de
bytes, y despues asignarla a P o r t a d a .
El metodo correspondiente a1 evento C l i c k quedaria tal y como se muestra a
continuacion:
Private Sub Buttonl~ClickiByVal s e n d e r As S y s t e m . O b ] e c t ,
P i c t u r e B o x l . I m a g e = Irnage.FrornFile(OpenFileDia1ogl.FlleName)
Di
Ar
FileAccess . R e a d )
ivo. Len
.Read ( I r n a g e n ,
Archivo. C l o s e ( )
ivo.L e n g t h )
www.detodoprogramacion.com
o b ] ( j s L i b r o s . Libror (Me.H i r d i r q C J n t e x t 1
7 b l d ~ L i h r o . 5 , " L i b r a s " ) . " s i t i i i n ) . P o r t a l a
~
Imager)
End I f
End Sub
www.detodoprogramacion.com
www.detodoprogramacion.com
Para crear el proveedor ADO.NET tendrd que iniciar un nuevo proyecto Visual
Basic .NET, concretamente una Biblioteca de clases. Llamela FileSys temclient,
como se ha hecho en la figura 22.1. La biblioteca obtenida, a1 compilar el proyecto,
se llamara Filesystemclient. dll.
Lpos de proyecto:
flantllas:
Otros proyectos
ApIcacion
I FlleSystemClient
Ubuacion
C kqrgregar a solucion
~
cerrar solucm
FileSystemClientDataReader. vb: Este m6dulo alojara la clase Filelas interfaces IDa taReader e
IDataRecord,facilitando el acceso a 10s datos de una fila y el avance unidi-
S y s temclient Da taReader.Implementara
FileSystemClientDataAdapter. vb: Contendra la clase FileSystemClient Da t aAdap te r. Derivada de DbDa taAdap ter e implementando la
interfaz IDbDataAdapter, ser6 la clase encargada de actuar como adaptador de datos para poder llenar un DataSet a partir de un comando.
La biblioteca de clases generada no estard firmada con una clave o nombre fuerte, por lo que no podr6 aiiadirla a1 GAC para emplearla desde cualquier proyecto
www.detodoprogramacion.com
como hace con 10s otros proveedores. No obstante, no tiene m& que usar la herramienta s n para generar la clave y firmar el m6dulo DLL para poder hacerlo.
Cuando va a operarse con un cierto proveedor de datos, habitualmente lo primero que se hace es abrir una conexi6n con el origen de datos. Por ello nos vamos
a ocupar en primer lugar de esta clase, la cual ser6 la que implemente la interfaz
IDbConnection. s u cabecera seria la siguiente:
PU
Inherits C o r n p iricintM ; i e l . Cr
Implements I L h C on n e c t i o rl
ConnectionState. Closed
www.detodoprogramacion.com
Observe que la cadena de conexion se guarda, tal cual, en una de las variables
definidas a1 principio a tal efecto. A continuaci6n se extrae de ella el valor que sigue a1 signo =. El Linico partimetro que aceptar6 nuestro proveedor en la cadena de
conexi6n serh D a t a Source,siendo su valor el camino con el que se desea conectar, por ejemplo C: \Windows.
Los partimetros establecidos con la cadena de conexibn, la propia cadena de conexi6n y la base de datos, asi como el estado en el que se encuentra la conexion,
cerrada o abierta, son datos accesibles mediante propiedades definidas en IDbConnection y que implementaremos asi:
11
E n d Set
E n d Property
P u b l i c R e a d O n l y P r o p e r t y Databas? ( ) As S t r i n g
I m p l e m e n t s I D b C ~ r n n e t i o n . Database
Get
R e t u r n strDataBase
End Get
E n d Property
,
>
, .+
~,
~
P u b l i c R e a d O n l y P r o p e r t y State ( ) As ConnectionState
I m p l e m e n t s IDbConnect o r l . S t a t e
Get
Return csState
End Get
E n d Property
st
s t rCo r l n e c t i o n St r i nq
E n d Sub
"
&
s t r Da t a B a s e
www.detodoprogramacion.com
End Sub
Implements I D b C o r l r l r r t i
End Sub
El objeto FileSystemClientConnection no es muy util por si solo, y adquiere sentido a1 utilizarse conjuntamente con comandos. gstos pueden crearse
mediante el metodo Createcommand ( ) que implementaremos asi:
PU
on CreateCommand( ) A s I D b C o m m a r l d
a t t- C o m m a rid
"
"
Me 1
A1 facilitar como segundo parhmetro a1 constructor del comando una referencia a la propia conexibn, ya estti cretindose el vinculo entre conexi6n y comando.
Esto permitiri que el objeto FileSystemClientCommand sepa c u d es el camino,
en teoria base de datos, con el que debe conectar para obtener informaci6n.
La interfaz IDbConnection no define muchos mtis miembros que 10s que ya
hemos implementado. Los que restan, BeginTransaction ( ) y la propiedad
ConnectionTimeout, no tienen sentido en nuestro proveedor, y por ello, aunque
estamos obligados a implementarlos, no tendrfin funcionalidad alguna:
www.detodoprogramacion.com
Get
Return 0
End Get
End Property
Public Overloads Function Beg i n T r a rl s ;i c t i or,( ) A s I Db'r r a n s a c t 1 on
Implements I D b C o r l n t c t~i rnr! . B e c j i n T r a ns a ct i o ri
End Function
Public Overloads Function B e g i n T r a r I s a c t i o n (
ByVal l e v e l As I s o 1 , i t i o r l L e v e l ) As I D b T r s r l s a c t i o r l
Implements I Db C o r, I, e c t i o rl . B e q i rlT r a rI .c a c t i I) n
~
End Function
Inherits C o m p o n e r1 t Mo d e 1 , C o mp o n e rlt
Implements I D b C o m m a n d
Private s t r C o m m a n d T e x t As String
Private c t C o m m a n d T y p e As C o m m a n d T y p e
tion
Pr
Friend d f O r i g e n As D i r e c t o r y I n f o
www.detodoprogramacion.com
Tenemos sendas variables para almacenar el tip0 y texto del comando. La variable cnconnection mantendrfi un enlace entre el comando y el objeto FileSystemclientconnection sobre el que actuarfi. Por tiltimo tenemos la variable
dfOrigen, que actuarfi como origen de datos. A1 ejecutar el comando, segun verfi
despuks, se actuar6 sobre este objeto.
Observe que dfOrigen tiene el modificador Friend,facilitando el acceso a 61
desde la clase FileSystemClientDataReader que crearemos en el punto siguiente.
Act0 seguido implementaremos 10s distintos constructores de la clase, en este
caso concreto tres:
( )
ComrnandText
End Sub
Connection
End Sub
Son 10s tres que podemos encontrar en 10s demfis proveedores. Como puede
ver, se limitan a guardar 10s parimetros facilitados en las variables que corresponden, sin efectuar ninguna comprobaci6n adicional sobre su validez.
La conexi6n y tanto el tip0 de comando como su texto son parfimetros del comando que pueden ser modificados en cualquier momento, ya que no se emplean
hasta la invocaci6n a uno de 10s mktodos ExecuteXXX ( ) .
Las tres propiedades siguientes facilitan tanto la obtenci6n como modificaci6n
de esos parfimetros:
Public Property C o m m a n d T e x t i ) As String
Implements I D b C o m m a n d . C o m r n a n d T e x t
Get
Re turn s t r C o mma n d T e x t
End Get
SetiByVal V a l u e As String)
strCommandText
Value
End Set
End Property
www.detodoprogramacion.com
Value
End Set
End Property
Public Property C o r ~ n e c t i o r (l ) As I D b C o n n e c t i o n
Implements I DbCornm a rld . C o n n e c t Io Ii
Get
Re turn c rl Ca n n e c t i o n
End Get
Set(ByVa1 V a l u r As I D b C o r ~ n e c t i o n )
cn Coriri e c.t 1nr, = CType ( Va 1u e , Fi 1 P S ys t e m C 1 1en t Co n rl e c t 1on )
End Set
End Property
~
De 10s m4todos ExecuteXXX ( ) de la interfaz IDbCommand facilitaremos implementacion util para tres de ellos. El primero, ExecuteNonQuery ( ) , debe ejecutar el comando sin recuperar en realidad datos, devolviendo tan s610 el numero
de filas que se obtendrian. En este caso, como puede verse a continuacibn, recuperamos las entradas del camino indicado con el mktodo Get Fi1e S ystem1n fo s ( ) ,
obteniendo el numero de entradas con la propiedad Length.Antes se comprueba
que tenemos un objeto de conexi6n asociado y, adem&, que dicha conexi6n est6
abierta.
PU
esos casos habria que analizar el texto del comando y, en lugar de usar directamente la colecci6n facilitada por Get Fi1e Sys tem1 n fo s ( ) ,filtrar las entradas obtenidas, por ejemplo utilizando 10s metodos GetFiles ( ) y GetDirectories ( ) en
lugar de GetFileSystemInfos ( ) .
El siguiente metodo que implementaremos sera ExecuteReader ( ) que, como
sabe, debe facilitar un objeto que implemente las interfaces IDataReader e IDataRecord. Lo haremos ask
( )
A s IDataReader
cnConnection.State
ConnectionState.Open Then
onnection. Database)
Creamos el objeto DirectoryInfo utilizando el camino establecido en la conexi6n y, a continuaci6n, creamos un FileSys temClientDataReader asociado
con este comando, devolviendolo como resultado.
El ultimo metodo util a implementar es la versi6n de ExecuteReader ( ) que
acepta un valor CommandBehavior como parametro. Dicho valor indicaria un
comportamiento a1 que tendria que ajustarse el lector de datos. Como se ve a continuacibn, ignoramos el valor y sencillamente ejecutamos la primera versi6n del
metodo.
PU
s Function ExecuteReaderi
ByVal b e h a v i o r A s CommandBehavior) A s IDataReader
Implements 1DbComrnand.ExecutePeader
Return ExecuteReaderO
End Function
( )
Implements IDbCornmand. P r e p a r e
End Sub
Public Property C o m m a n d T i m e o u t ( ) As Integer
Implements IDbCommand. CornrnandTirneout
Get
Return 0
End Get
Set(ByVa1 V a l u e As Integer)
End Set
End Property
Protected ReadOnly Property P a r a m e t e r s 0 As
I D a t a F a r a r n e t e r C o l l e c t i o n Implements 1 D b C o r n r n a n d . P a r a r n e t e r s
Get
~
End Get
End Property
Public Property T r a n s a c t i o n ( ) As I D b T r a n s a c t i o n
Implements I DbComrna nd . T r a n s a c t i o n
Get
Return CType ( Nothing, T DbT r a n s a c t i o n )
End Get
Set (ByVal V a l u e As I D b T r a n s a c t i o n )
End Set
End Property
Public Property U p d a t e d R o w S o u r c e O As U p d a t e R o w S o u r c e
Implements 1 D b C o r n r n a n d . U p d a t e d R o w S o u r c e
Get
Return U p d a t e R o w S o u r c e . N o n e
End Get
Set(ByVa1 V a l u e As U p d a t e R o w S o u r c e )
End Set
End Property
Public Sub C a n c e l
( )
Implements IDbCornmand. C a n c e l
End Sub
www.detodoprogramacion.com
El mgtodo ExecuteReader ( ) de la clase definida en el punto anterior devuelve un objeto FileSystemClientDataReader, cuya clase nos disponemos a implementar a continuacion. Con ella podremos ir recorriendo las filas de datos,
obteniendo el valor de cada una de las columnas. La informacion ser6 recuperada
del objeto DirectoryInf o creado por el comando, a1 que tenemos acceso por haberse declarado Friend en lugar de Private.
Comenzamos, como en 10s puntos anteriores, con la declaracih de miembros
de datos de la clase, que sera la siguiente:
Pub1 1c C1 ass Fi 1 e Sy
' t e rnC'1 1 e rl t Da t a Re ad c r
Inherits ComponentModpl . C o m p o n e n t
Implements I D a t a R e a d e L
Implements I D a t a R t c o r d
Pr
cs1t
Private i R o w s As Integer
Tenemos dos variables enteras, iposition e iRows, que mantendr6 la fila actual y el numero total de filas. f s cCommand almacenar6 la referencia a1 comando
asociado a este lector.
Esta clase contar6 con un unico constructor que tomar6 como par6metro la referencia al comando asociado. Asi, no podra nunca crearse un lector de datos sin
comando asociado.
stemClientCornmand)
F i l e S y s t e m I n f 0 s .L e n g t h
iPosition
End Sub
-1
Ademas de guarder la referencia a1 comando, damos un valor inicial a la variables iRows e iposition. La primera contendr6 el ntimero de elementos obtenidos del m6todo Get FileSys temInf 0 s ( ) , mientras que la segunda ser6 -1 de tal
www.detodoprogramacion.com
forma que la primera llamada a1 metodo Read ( ) nos coloque realmente en la primera fila de datos.
El metodo Read ( ) , como se ve en el cddigo siguiente, es realmente sencillo. Incrementamos el valor de la variable iposition y, a continuacih, devolvemos
True o False dependiendo de que queden o no mas filas de datos. Para ello comparamos iPosition con iRows.
+=
End Function
Una vez que estamos colocados en una fila de datos, el paso siguiente serA recuperar el valor que almacena cada una de sus columnas. Con este fin tendremos que
implementar dos versiones diferentes de la propiedad 1tern. La primera tomara
como parametro el indice de la columna, mientras que la segunda recibirb, en lugar del indice, el nombre de la columna.
Ninguno de 10s dos metodos accede directamente a la lista devuelta por GetFileSystemInfos ( ) , sino que utilizan el metodo GetValue ( ) de la propia clase FileSys temClientDataReader.Esta siempre toma como parametro el indice
de la columna cuyo valor quiere obtenerse. Puesto que en la segunda versidn desconocemos dicho indice, lo que tenemos es el nombre de la columna, lo recuperamos mediante el metodo Getordinal ( ) .
De
Def au
Property Item(ByVa1 n a m e
As String) As Object Implements 1DataRecord.Item
Get
Return GetValue(GetOrdina1 ( n a m e ))
End Get
End Property
www.detodoprogramacion.com
Para facilitar a las dos propiedades anteriores el indice o nombre de una columna, con el fin de obtener su valor, primer0 necesitaremos saber cuintas columnas
hay disponibles y cuiles son sus nombres. Estos datos son 10s que nos facilita la propiedad Fieldcount y el m6todo GetName ( ) , que implementamos como se ve en
el c6digo siguiente:
PU
Implements 1DataRecord.FlsldCount
Get
Return 2
End Get
End Property
Como puede verse, facilitaremos tan s610 dos columnas por fila: FullName y
CreationTime, es decir, el nombre del elemento y su fecha de creaci6n. Tambien
seri util saber qu6 tip0 de dato contiene cada una de esas columnas, informaci6n
que obtendriamos con 10s dos metodos mostrados a continuaci6n:
ByVal 1 As Integer)
cord.GetDataTypeName
End Function
1
Las dos versiones de la propiedad Item hacen us0 del metodo GetValue ( ) .
h e acepta como partimetro el indice de la columna a obtener, devolviendo el valor que corresponda teniendo en cuenta que la fila actual de datos es iposition.
Implements 1DataRecord.GetValue
0
With f s cComma nd . d fOr 1 g e rl . Get Fi 1 e S y s t e m I r) f o s ( i
Select Case 1
Case 0 '
Return . F u l l N
Case 1 '
Return . Creat
End Select
End With
End Function
( i Po 5 1 t 1 on 1
El ultimo metodo citil a implementar en esta clase es Getvalues ( ) . A diferencia de GetValue ( ) , este no recibe como partimetro un indice numerico sin0 un
arreglo de elementos O b j ect en el que debe retornarse el valor de todas las columnas de la fila actual. Adem&, el metodo devuelve un valor entero indicando el
numero de elementos introducidos en el arreglo. Lo implementamos asi:
v a l u e s ( 0 ) = fscCornrnand.dfOrigen.GetFileSystem1nfos ( )
(iPosition).FullNarne
www.detodoprogramacion.com
Return 2
End Function
Por ultimo, ya sin implementaciones titiles, debemos codificar 10s metodos mostrados a continuacih. Observe que gran parte de ellos son metodos GetXXX ( ) de
la interfaz I D a t a R e c o r d , metodos que recuperan el valor de una columna no con
el tip0 original, sin0 con otro especificado.
www.detodoprogramacion.com
www.detodoprogramacion.com
_.
___
._. ..
___
..
...
La ultima clase que tenemos por implementar es la que actuar6 como adaptador de datos. A diferencia de las anteriores, esta clase no estar6 derivada de CornponentModel sin0 de DbDataAdapter.
Esta clase base se ocupa ya de la implementacih de gran parte de la funcionalidad del adaptador de datos, por lo que el trabajo que tenemos que efectuar nosotros es relativamente breve y fAcil.
Comenzamos, como en 10s casos anteriores, con la declaraci6n de miembros de
datos:
Public Class F i 1 e S y s t emCl i en t Da t aAdapt e t
Inherits D b D a t a A d a p t e i
Implements I Db Dd t aAJaF t e r
www.detodoprogramacion.com
Public Sub N e w ( )
MyBase.New()
End Sub
ternClientCommand)
fscSelectCornmand
CornmarJd
End Sub
El resto de 10s miembros que estamos obligados a implementar son 10s que aparecen a continuacih, sin c6digo util:
www.detodoprogramacion.com
End Set
End Property
Protected Overrides Function C r e a t e R o w U p d a t e d E v e n t i ByVal d a t a R o w As DataRow, ByVal command As IDbCommand, ByVal s t a t e r n e n t T y p e As S t a t e r n e n t T y p e , ByVal t a b l e M a p p i n g
As D a t a T a b l e M a p p i n g ) As R o w U p d a t e d E v e n t A r g s
Return Nothing
End Function
Protected Overrides Function C r e a t e R o w U p d a t i n g E v e n t i
ByVal d a t a R o w As DataRow, ByVal command As IDbCommand,
ByVal s t a t e m e n t T y p e As S t a t e r n e n t T y p e , ByVal t a b l e M a p p i n g
As Da t a T a b 1eMa p p i n g ) As RowlJ pd a t i ng Eve n t A r g s
Return Nothing
End Function
End Sub
Con esto se ha finalizado la clase del adaptador de datos y tambien el proveedor de datos. Sencillo, ya que no facilita la selecci6n de datos distintos mediante
consultas o la actuaIizaci6n, per0 suficiente para ser usado como ejemplo y como
base para otros proveedores.
En este momento, tras compilar el proyecto, tenemos el proveedor Filesy s temClient en un m6dulo DLL.No sabremos si funciona o no adecuadamente hasta
www.detodoprogramacion.com
que lo probemos, que es lo que vamos a hacer de inmediato. Sin cerrar el proyecto
del proveedor, afiada un nuevo proyecto a la soluci6n. Agregue a1 nuevo proyecto
una referencia a1 primero, para poder utilizar el proveedor simplemente importando el 6mbito FileSystemClient.
i t
Comenzaremos por un ejemplo muy sencillo, con el que obtendremos el numero de entradas de directorio que hay en una cierta carpeta. Para ello vamos a insertar en el formulario del proyecto afiadido a la soluci6n un b o t h , asoci6ndole el
codigo siguiente:
Definimos una conexi6n y un comando, abrimos la conexi6n y usamos el metodo ExecuteNonQuery ( ) para obtener el numero de filas que recuperariamos con
ese comando. A1 ejecutar el programa apareceria una pequefia ventana con ese numero, como se ve en la figura 22.2.
. ..
. ......................................................
..
...
,... .............II_.......-..-.-
l..l_
En vez de usar el metodo ExecuteNonQuery ( ) , podemos invocar a ExecuteReader ( ) para obtener un lector de datos. A partir de ese momento lo utilizariamos como cualquier otro DataReader de 10s que conocimos en capitulos previos.
www.detodoprogramacion.com
( )
Ll
End While
A1 ejecutar el programa, en la lista deberia aparecer el nombre y fecha de creaci6n de cada una de las entradas de directorio existentes en la carpeta indicada por
la conexion. En la figura 22.3 puede ver el ejemplo en ejecuci6n.
U N D % % m 2 0 0 2 10 12 26
UND 001 03/09/2002 16 44 32
cycled 31101 12002 8 50 14
tern Volume lnfutrnation 31 /01/2002 E
1 C \mrdownld Imp 21 /03/2001 10 13 52
C \Mi rniisica 07?08/2002 17 33 51
C iWINDOW5 08/08/2002 12 08 53
C \Documents and Settmgs 08/08?2002 12
C Vuchms de pmgrama 08/08/2002 12 12
C iPiograrn Files 03/08/2002 15 53 36
C \MIS docurnentos 09/08/2002 16 03 25
C ilnetprrb 10/08/2002 4 19 33
C WBuildw7 12/08/'2002 21 32 15
C \PBdN,sualBasicNET 14/08/2002 12 44
11
1
Figura 22.3. El L i s t B o x con 10s datos de las entradas de directorio
Disponiendo, como es el caso, de una clase de adaptador de datos, FileSystemClientDataAdapter, no es necesario usar un DataReader para recuperar las
filas de forma individual si lo unico que queremos es mostrarlas en un formulario.
Puede sustituir el Lis tBox por un DataGrid y el c6digo anterior por el siguiente:
Dim I ) a t r i As New
IDataStt ( )
Como puede ver, creamos el adaptador de datos a partir del comando previamente definido. A continuaci6n creamos el DataSet y lo llenamos con el metodo
www.detodoprogramacion.com
Fill ( ) del adaptador, como hariamos en cualquier otro caso. Por ultimo, vinculamos el D a t a S e t con el D a t a G r i d , obteniendo el resultado que se puede ver en
la figura 22.4.
www.detodoprogramacion.com
www.detodoprogramacion.com
el elemento Data Access Aplication Block, tal como se aprecia en la figura 23.1. El
archivo no llega a1 megabyte, por lo que su descarga es relativamente rfipida.
NET Fiarnevorl.
'*
'
application.
Size (bytes):
826.368
Last Updated:
04/16/2002
supparted:
NO
&Download
Docunientation
%!DISCUSSin NewSarouPs
NET Show
Il-_.!".._
I)!
(I
@ Intemt
Figura 23.1. Seccion de MSDN donde se encuentra Data Access Application Block
El paquete obtenido es autoinstalable, por lo que bastar6 con hacer doble clic
sobre 61 para poner en marcha el proceso de instalacidn en nuestro sistema. Aceptamos la licencia de uso, establecemos el camino de destino (v6ase figura 23.2) y
pulsamos el b o t h Next hasta poner en marcha el proceso de copia de archivos.
La instalacidn no facilita el ensamblado en formato compilado, ni lo registra como ensamblado cornpartido, simplemente copia en la carpeta indicada el cddigo
fuente, tanto Visual Basic como C#, y la documentacidn, facilitada en un archivo de
ayuda de Windows. T a m b i h se crea en el menu del boton Inicio una carpeta, llamada Microsoft Applications Block for .NET, que facilita el acceso a1 cddigo de estos bloques de aplicacidn, 10s ejemplos y la documentacidn, segun se aprecia en el
detalle de la figura 23.3.
www.detodoprogramacion.com
..
I-
The nslaller w l nslall Merosdt Data Access Apdicatan Block Iw NET to the Idwngloldar
To instdl 111 this fd& ckck 'Next" To instdl to a &hnnt foMer enter 1 bebw a chck "Browd'
Eolder
C Urchwos de programa\MicrosoftApplication Blocks for NET\Dala
Bjwse
Qisk Cost
Instal Microsoft Data Access Application Block foi NET fw yoursetf, or for anyone wha uses ths
cqutei
OEvwvone
@Just me
Los metodos de ayuda definidos en este paquete de c6digo son utiles para trabajar con SQL Server, no siendo aplicables al resto de proveedores .NET. Al
disponer del codigo fuente, sin embargo, seria relativamente facil adaptarlo
para operar con el proveedor que nos interese.
Corn
nsarnblado
Para poder utilizar este c6digo de ayuda, lo primer0 que tenemos que hacer es
compilarlo para generar el correspondiente ensamblado. Abra el elemento Data
Access Application Block del menu antes indicado. Da igual que use el c6digo Visual Basic .NET o el c6digo C#, ya que el ensamblado obtenido podr6 ser utilizado
indistintamente.
Se abrir6 Visual Studio .NET con el proyecto elegido. Pulse la combinaci6n de
teclas Control-Mayh-B, o bien elija la opci6n GeneraPGenerar solucion, para
compilar el proyecto y obtener el correspondiente m6dulo DLL. Puede cerrar el
proyecto y el entorno de Visual Studio .NET si lo desea. En este momento tenemos
www.detodoprogramacion.com
Todos 10s metodos del ensamblado que hemos obtenido aparecen como metodos compartidos, o estdticos, dentro de estas dos clases: SqlHelper y SqlHelperParametercache, resultando especialmente interesantes 10s de la primera. Estos
son 10s siguientes:
ExecuteNonQuery ( ) : Ejecuta un comando devolviendo el numero de filas
afectadas como un entero.
ExecuteDataSet
( ) : Ejecuta
ExecuteReader
( ) : Ejecuta
Executescalar
( ) : Ejecuta
ExecuteXmlReader
( ) : Ejecuta
La diferencia que hay entre estos mktodos y algunos de 10s existentes en un objet0 Command con el mismo nombre, es que &tos aceptan una cadena de conexion,
una cadena con el comando y devuelven el resultado, sin tener que crear objetos
intermedios como el adaptador de datos o el objeto Connection.
Por su parte, 10s mktodos de SqlHelperparameterCache tienen el objetivo
de facilitar el almacenamiento de par6metros empleados con consultas y procedimientos almacenados.
-___I_.-
--.I
~
I
_
_
_
~
_~ _
-_
~-
~ ~
Para usar estos metodos desde una aplicacion propia, lo primer0 que tenemos
que hacer es agregar una referencia a1 ensamblado Microsoft .ApplicationBlocks. Data. dll.Para ello seleccione la opci6n Agregar referencia del proyecto y, ya que no se trata de un ensamblado compartido que se encuentre registrado
en la GAC, pulse el b o t h Examinar para localizar y aiiadir el ensamblado como se
ha hecho en la figura 23.4.
En caso de que vaya a usar 10s mktodos de SqlHelper y SqlHelperParametercache en multiples proyectos, quiz6 le convenga instalar el ensamblado en la
GAC abrikndolo en Visual Studio y aiiadikndole una clave para firmarlo con un
identificador unico. En este caso el ensamblado apareceri en la lista de la p6gina
.NET y podr6 afiadirlo directamente a sus proyectos, sin necesidad de localizar el
m6dulo DLL.
www.detodoprogramacion.com
~~
~~
CRVsPackageLib
1.0.0.0
CrystalDeC~~~Cms.CrystalRepO.,9.1.3300.0
CrystalDecisions ReportSource 9.1.3300.0
9.1.3300.0
CrystalDecisions .Shared
CrystalDecsions.Web
9.1.3300.0
CrystalDecmns. M d o w s . F u . ,, 9.1.3300.0
1.0.0.0
CrystalEnterpraeLib
1.0.0.0
Cryrtallnl'o5toreLib
1.0.0.0
CrystalKeyCodeLib
TrvCtaIPIiinmMnrl h
I n nn
~.
C:\Archnos de prograrna\Arc...
C:\Archivos de prograrna\Arc.,
C:\Archivor de prograrna\Arc
C:\Archivos de prograrna\Arc...
C:\Archivos de prograrna\Arc
C:\ArchvosdeprogramalArc
C:\Archivos de progrma\Arc
C:\Archvos de prograrna\Arc...
C:\Archivos de prograrna\Arc.. .
r,lArrhlun. rlr nrnnrnmil\irr
.
...
...
...
...
"
~ o w o n e n t e sselecclonados:
Microso t,ApphcationEkb.D&a
... Archivo
C:\Archwor de programa\Mrro
Aceptar
...
Cancclar
Ayuda
-.
___
._.-_
l ^
_ _ _ _ _ _ _ l . - ~ ~ ~ ~ ~ ~ . -
Asumiendo que ya se ha aiiadido la referencia a1 ensamblado, para usar 10s metodos tendri que importar el AmbitoMicrosoft . A p p l i c a t i o n B l o c s . D a t a aiiadiendo luego la correspondiente sentencia I m p 0 r t s a1 inicio del c6digo.
A continuacibn, bastaria con invocar a 10s metodos con 10s parimetros adecuados, como hariamos en cualquier otro caso. Suponiendo que hayamos insertado
un DataGrid en un formulario, la sentencia siguiente mostraria en 61 la tabla Lib r o s completa.
DataGridl.DataSource = SqlHelper.ExecuteDataset(
" Da t a
Sour ce=I rls pi ron ; In i t i a 1 Cat a 1 og=Li b ro s ; Us e r I D = s a ' I ,
CornmandType.Text, " S E L E C T * FROM L i b r o s " )
~
Observe que no hemos arrastrado elemento alguno del Explorador de servidores, insertado componentes en el formulario o creado objetos intermedios. Basta
una llamada a ExecuteDataSet ( ) para crear el conjunto de datos con la informaci6n deseada. De manera aniloga se utilizarian 10s demis metodos.
Aunque en este caso se han usado cadenas de caracteres para definir el origen
de datos y el comando, tambien pueden emplearse objetos S q l c o n n e c t i o n
y SqlCommand en caso de que 10s hubiesemos creado con anterioridad.
www.detodoprogramacion.com
3
4
5
6
7
8
9
10
11
12
13
14
1 893115 94 1
8441511365
84 415 1324 4
84 41 5 1392 9
84 41 5 1316 7
84 415 1351 1
84 415 1290 6
84 415 1291 4
84 415 1261 2
84415 12558
84 415 1230 2
84 415 1202 7
8441511322
3
1
1
1
1
1
1
1
1
1
1
1
1
31
1 0 75
1 0 75
39
40
39
1 0 75
1 0 52
37 26
10 52
21 04
10 52
1052
Malrir Byte[]
Malriz Byte[]
Malw Byte[]
Malrir Byte[]
Malm Byte[)
Malriz Byte[]
(null]
[null
[null]
[nun]
[null]
[null]
(null
www.detodoprogramacion.com
..'
www.detodoprogramacion.com
Acronimos y significado
ACID
Atomicity, Consistency,
Isolation and Durability
ADO
ADS1
Active Directory
Services Interfaces
ANSI
American National
Standards institute
API
Application Programming
Interface
ASCII
American Standard
Code for Information
Interchange
BDE
www.detodoprogramacion.com
A . Glosario
CLS
Common Language
Specification
Especificacion creada por Microsoft para hacer posible la interoperabilidad entre distintos
lenguajes de programacion en la plataforma
.NET.
COBOL
Common Business
Oriented Language
COM
DAO
DBA
Database Administrator
DBMS
Database Management
System
Apelativo con el que se conocen las aplicaciones para la gestion de datos, lo que coloquialmente se conoce como base de datos.
DCL
DDL
DLL
Modulos, conocidos como bibliotecas de enlace dinamico, que contienen codigo compilado para ser usado desde las aplicaciones.
DML
Data Manipulation
Language
Parte de SQL que comprende todas las sentencias de seleccion y manipulacion de datos.
DOM
DSN
DTD
FK
Foreign Key
Clave externa. Columna de una tabla qlie hace referencia a una clave primaria de otra tabla.
www.detodoprogramacion.com
GAC
HTML
HyperText Markup
Language
HTTP
Hypertext Transfer
Protocol
JDBC
Java Database
Connectivity
LDAP
Lightweight Directory
Access Protocol
MDAC
Microsoft Data
Access Components
MSDE
MSlL
Microsoft Intermediate
Language
ODBC
Open Database
Connectivity
OLE DB
PK
Primary Key
PLISQL
Procedural
Language/Structured
Query Language
RDBMS
Relational Database
Management System
SAX
SGBD
Sistema gestor de
bases de datos
Equivalente a DBMS.
SGML
Standarized General
Markup Language
Lenguaje estandar de marcas del que se derivan otros, como HTML o XML.
SQL
Structured Query
Language
www.detodoprogramacion.com
www.detodoprogramacion.com
www.detodoprogramacion.com
Este libro incorpora un CD-ROM en el que podr6 encontrar todos 10s ejemplos
que se han descrito en sus capitulos, facilit6ndole asi el acceso a todo el c6digo sin
necesidad de tener que teclearlo personalmente. En la carpeta E j emplos encontrar6 una subcarpeta por cada capitulo, en cuyo interior se ha creado una carpeta
para cada ejemplo de ese capitulo en concreto.
Adem6s del c6digo fuente de 10s proyectos tambien se entregan kstos ya compilados. Estos, no obstante, no pueden ser ejecutados directamente desde Windows
a menos que se tenga instalada la plataforma Microsoft .NET, entregada t a m b i h en
el CD-ROM. En caso de que tenga instalado en su sistema el product0 Visual Studio .NET en alguna de sus versiones, ya cuenta tambikn con la plataforma .NET.
En cualquier caso, debe tener en cuenta que 10s proyectos se entregan como simples ejemplos, nunca como aplicaciones de us0 final, por lo que no se otorga garantia alguna ni soporte de su funcionamiento. Nuestro objetivo es facilitarle c6digo
sobre el que pueda hacer pruebas y desarrollar sus propios proyectos.
-nirertnrin
.. - -.-. .-
Pcrtam
Llbmd
Artkubs
No(otrla
RsCurOS
Glosario
Curso de Delphi
(m)
Sewicms de componentes en
Wmdows 2000 - COM+
Curso de Delphi (11)
ASP
it
'"
free.com [Inalkl
ConnechonsStrigs~com(Ingles)
Recuperar inforrnaci6n de hpos en
ejecucion (Castellano)
Delphi for .NET compder preview
(1ngle5)
Web Services Interoperabrhtv
Orgamzabon (Inggs)
1p-r'r-7
y l .
"$
__
www.detodoprogramacion.com
--
Por lo demis no es necesario ningun paso adicional para poder usar 10s ejemplos.
No olvide que para comprender las t6cnicas te6ricas es fundamental la prictica y
que, aunque se facilite el c6digo para que no tenga que introducirlo manualmente,
es importante que lo examine cuidadosamente y que lo utilice para experimentar,
introduciendo cambios y usandolo como base para sus propios ejemplos.
Tanto la editorial como el autor de este libro se ponen a disposici6n del lector
para cualquier problema que pudiera encontrar en el us0 del CD-ROM, su contenido o bien el del libro que tiene en sus manos. En la web de Anaya Multimedia,
http: //www.AnayaMultimedia.corn, podri encontrar informaci6n adicional,
en caso de que la hubiera, asi como el enlace necesario para solicitar ayuda. De
igual forma, el autor mantiene una sede, llamada Torre d e Babel, en la direcci6n
http: //www.fcharte.com,con datos sobre 6ste y otros libros, articulos y desde donde puede ponerse en contact0 con 61 en caso de que encuentre algun tip0 de
problema.
www.detodoprogramacion.com
A
Acceptchangeso
DataSet, 165, 261
DataTable, 166
ACID - Glosario, 501
Add() - DataRowCollection, 166
AddNew() - Dataview, 169, 276
ADO - Glosario, 501
ADS1 - Glosario, 501
AllowDBNull - Datacolumn, 168
AllowDelete - Dataview, 276
AllowEdit - DataView, 276
AllowNew - Dataview, 276
ALTER - SQL, 50
ALTER TABLE - SQL, 54
ALTER VIEW - SQL, 56
Ambitos
Microsoft.Data.Odbc, 155
System.Data, 154
System.Data.Common, 154
System.Data.OleDb, 154
System.Data.OracleClient, 155
System.Data.SqlClient, 154
System.Data.SqlTypes, 155
AND - SQL, 59
ANSI - Glosario, 501
API - Glosario, 501
Appendchild0 - XmlNode, 303
ASC
CREATE INDEX, 55
ORDER BY, 61
ASCII - Glosario, 501
ASE'.NET
AutoPostBack, 375
DataBindO, 372
DataBinder, 372
DataList, 380
Repeater, 380
Attributes - XmlNode, 302
www.detodoprogramacion.com
fndice alfabe'tico
c
CancelCommand - DataGrid, 406
CancelEdit()
DataRow, 167
DataRowView, 276
Casesensitive - DataSet, 237
Cells - DataGridItem, 406
ChangeDatabaseO IDbConnection, 178
CHAR
PLJSQL, 70
SQL, 52
char - Transact-SQL, 67
ChildColumns - DataRelation, 169
ChildNodes - XmlNode, 302
ChildRelations - DataTable, 166
ChildTable - DataRelation, 169
Close()
IDataReader, 158
IDbConnection, 161, 176
CloseConnection CommandBehavior, 218
Closed - Connectionstate, 176
CLS - Glosario, 502
COBOL - Glosario, 502
ColumnMappings ITableMapping, 156
ColumnName - Datacolumn, 167, 454
Columns
DataTable, 165, 236
OleDbSchemaGuid, 203
COM - Glosario, 502
ComboBox - Controles, 370
CommandBehavior
CloseConnection, 218
Default, 218
KeyTnfo, 218
SchemaOnly, 209
SchemaOnly, 218
SingleResult, 218
SingleRow, 218
CommandText IDbCommand, 161, 217
CommandType
IDbCommand, 161, 217
StoredProcedure, 232
TableDirect, 220
COMMIT TRANSACTION Transact-SQL, 436
Commit() - IDbTransaction, 161, 438
complexType - XSD, 125
www.detodoprogramacion.com
Conceptos
DataReader, 144
DataSet, 141
Connecting
Connectionstate, 176
IDbCommand, 161
IDbTransaction, 438
Connectionstate
Broken, 176
Closed, 176
Connecting, 176
Executing, 176
Fetching, 176
IDbConnection, 176
Open, 176
Connectionstring IDbConnection, 161, 176
ConnectionTimeout IDbConnection, 178
Constraint
ConstraintName, 168
System.Data, 168
ConstraintCollection System.Data, 165
ConstraintName - Constraint, 168
Constraints - DataTable, 165, 236
CONTINUE - Transact-SQL, 68
Control - DataBindings, 370
Controles
ComboBox, 370
DataGrid, 370
ListBox, 370
TextBox, 370
Count - CurrencyManager, 379
COUNT() - SELECT, 61
CREATE - SQL, 50
CREATE FUNCTION - PL/SQL, 72
CREATE INDEX
ASC, 55
DESC, 55
SQL, 54
CREATE PROCEDURE
PL/SQL, 72
Transact-SQL, 69
CREATE ROLE - SQL, 65
CREATE USER - SQL, 65
CREATE VIEW - SQL, 55
Createcommand() - IDbConnection,
161, 178, 216
CreateDataViewO DataViewManager, 277
CreateNavigatorO - XmlNode, 303
Createparameter - IDbCommand, 226
CurrencyManager
Count, 379
Position, 379
System.Windows.Forms, 378
Current - XPathNodeIterator, 306
Currentchanged BindingManagerBase, 379
cursor - Transact-SQL, 67
D
DAO - Glosario, 502
DataAdapter System.Data.Common, 159
Database - IDbConnection, 177
DATABASE - SQL, 50
DataBindO - ASP.NET, 372
DataBinder - ASP.NET, 372
DataBindings - Control, 370
Da taColumn
AllowDBNull, 168
AutoIncrement, 168
ColumnName, 167, 454
DataType, 167, 454
Defaultvalue, 168
Expression, 454
MaxLength, 167
System.Data, 165
Unique, 168
www.detodoprogramacion.com
h d i c e alfabetico
www.detodoprogramacion.com
RowDeleted, 166
RowDeleting, 166
Rows, 165, 236
Select(), 166, 237, 272
System.Data, 165
DataTableCollection System.Data, 164
DataTableMapping System.Data.Common, 156
DataTableMappingCollection System.Data.Common, 156
DataTextField - ListBox, 375
DataType - Datacolumn, 167, 454
DataValueFieId - ListBox, 375
DataView
AddNew(), 169, 276
AllowDelete, 276
AllowEdit, 276
AllowNew, 276
Delete(), 169, 276
Find(), 169, 281
FindRows(), 169, 281
Item, 169, 276
RowFilter, 169
RowStateFilter, 276
Sort, 169, 277
StateFilter, 169
System.Data, 169, 271
DataViewManager
CreateDataViewO, 277
DataSet, 277
DataViewSettings, 277
System.Data, 271
DataViewSettings DataViewManager, 277
DATE
PL/SQL, 70
SQL, 52
DBA - Glosario, 502
DbDataAdapter System.Data.Common, 159
www.detodoprogramacion.com
fndice alfabktico
DROP - SQL, 50
DROP INDEX - SQL, 55
DROP TABLE - SQL, 54
DROP VIEW - SQL, 56
DSN - Glosario, 502
DTD - Glosario, 502
E
Editcommand - DataGrid, 406
EditItemIndex - DataGrid, 406
element - XSD, 126
ELSE
PLISQL, 71
Transact-SQL, 68
ELSIF - PLISQL, 71
END - Transact-SQL, 68
EndEdit()
DataRow, 167
DataRowView, 276
Enforceconstraints - DataSet, 168
EXECUTE - Transact-SQL, 95
ExecuteDataSetO - SqlHelper, 496
ExecuteNonQuery ()
IDbCommand, 218
SqlHelper, 496
ExecuteOracleNonQuery() OracleCommand, 219
ExecuteOracleScalar() OracleCommand, 219
ExecuteReaderO
IDbCommand, 218
SqlHelper, 496
Executescalar()
IDbCommand, 218
SqlHelper, 496
ExecuteXmlReader()
SqlCommand, 219
SqlHelper, 496
Executing - Connectionstate, 176
Expression - Datacolumn, 454
G
GAC - Glosario, 503
GetBoolean0 - IDataRecord, 157
GetByte() - IDataRecord, 157
GetChildRows() - DataTable, 286
GetColumnsInError() - DataRow, 167
GetDeleteCommand() SqlCommandBuilder, 163
GetElementFromRow() XmlDataDocument, 310
GetFloatO - IDataRecord, 157
GetInsertCommand() SqlCommandBuilder, 163
GetOleDbSchemaTable() OleDbConnection, 202
www.detodoprogramacion.com
JDBC, 503
LDAP, 503
MDAC, 503
MSDE, 503
MSIL, 503
ODBC, 503
OLE DB, 503
PK, 503
PLISQL, 503
RDBMS, 503
SAX, 503
SGBD, 503
SGML, 503
SQL, 503
T-SQL, 504
UDL, 504
URI, 504
URL, 504
VBA, 504
W3C, 504
WWW, 504
XML, 504
XSD, 504
XSL, 504
XSLT, 504
GRANT - SQL, 65
GROUP BY - SELECT, 62
H
Haschangeso - DataSet, 164
HasChildNodes - XmlNode, 302
HasErrors - DataRow, 167
Hasversion() - DataRow, 167
HTML - Glosario, 503
HTTP - Glosario. 503
www.detodoprogramacion.com
fndice aljabe'tico
DataSetColumn, 156
SourceColumn, 156
System.Data, 156
IColumnMappingCollection System.Data, 156
IData Adapter
Fill(), 159, 239
Fillschema(), 247
MissingMappingAction, 239
MissingSchemaAction, 239
System.Data, 159, 414
Update(), 159, 241
IDataReader
Close(), 158
GetSchemaTableO, 209
NextResultO, 158, 222
Read(), 157
RecordsAffected, 157
System.Data, 157, 414
IDataRecord
Fieldcount, 157
GetBooleanO, 157
GetByte(), 157
GetFloat(), 157
Getstring(), 157
Item, 157
System.Data, 157
IDbCommand
CommandText, 161, 217
CommandType, 161, 217
Connection, 161
Createparameter, 226
ExecuteNonQuery(), 218
ExecuteReaderO, 218
Executescalar(), 218
Parameters, 217
Properties, 232
System.Data, 161, 414
IDbConnection
BeginTransactionO, 161, 178, 438
ChangeDatabaseO, 178
www.detodoprogramacion.com
MAX() - SELECT, 62
MaxLength - Datacolumn, 167
MDAC - Glosario, 503
Microsoft.Data.Odbc
Ambitos, 155
OdbcDataAdapter, 159
OdbcDataReader, 158
MINO - SELECT, 62
MissingMappingAction IDataAdapter, 239
MissingSchemaAction IDataAdapter, 239
money - Transact-SQL, 67
MoveNextO XPathNodeIterator, 306
MSDE - Glosario, 503
MSIL - Glosario, 503
K
KeyInfo - CommandBehavior, 218
L
Lastchild - XmlNode, 303
LDAP - Glosario, 503
LIKE - WHERE, 59
ListBox
Controles, 370
DataMember, 375
Datasource, 372
DataTextField, 375
DataValueField, 375
DisplayMember, 372
ValueMember, 372
Load() - XmlDocument, 302
LOOP - PL / SQL, 71
indice alfabitico
OracleDataReader
GetOracleBinaryO, 158
GetOracleNumber(), 158
Getoraclestring(), 158
System.Data.OracleClient, 158
OracleTransaction System.Data.OracleClient, 162
ORDER BY
ASC, 61
DESC, 61
SQL, 61
P
Parameters - IDbCommand, 217
ParentColumns - DataRelation, 169
ParentNode - XmlNode, 303
ParentRelations - DataTable, 166
ParentTable - DataRelation, 169
PictureBox - FromStreamO, 464
PK - Glosario, 503
PL / SQL
BFILE, 70
CHAR, 70
CREATE FUNCTION, 72
CREATE PROCEDURE, 72
DATE, 70
DECIMAL, 70
DECLARE, 70
DEFAULT, 72
DOUBLE PRECISION, 70
ELSE, 71
ELSlF, 71
FLOAT, 70
FOR, 71
Glosario, 503
IF, 71
LOOP, 71
NATURAL, 70
OPEN, 109
POSITIVE, 70
www.detodoprogramacion.com
S
RDBMS - Glosario, 503
Read() - IDataReader, 157
ReadXml() - DataSet, 165
ReadXmlSchema() - DataSet, 165, 260
RecordsAffected - IDataReader, 157
REF CURSOR - PL / SQL, 109
REFERENCES - SQL, 53
Refresh() - BindingManagerBase, 379
RejectChanges()
DataSet, 165
DataTable, 166
Relations - DataSet, 164, 236
Removechild() - XmlNode, 303
Repeater - ASP.NET, 380
Replacechild() - XmlNode, 303
www.detodoprogramacion.com
fndice alfabe'tico
NOT NULL, 52
NULL, 57
OR, 59
ORDER BY, 61
PRIMARY KEY, 52
PROCEDURE, 51
REFERENCES, 53
REVOKE, 65
SELECT, 56
SMALLINT, 52
TABLE, 50
TIME, 52
TRIGGER, 51
UNIQUE, 52
UPDATE, 56, 64
VALUES, 57
VARCHAR, 52
VIEW, 51
WHERE, 59
SqlCommand
ExecuteXmlReader(), 219
System.Data.SqlClient, 162
SqlCommandBuilder
GetDeleteCommand(), 163
GetInsertCommand(), 163
Getupdatecommand( ), 163
System.Data.SqlClient, 163
SqlConnection System.Data.SqlClient, 162
SqlDataAdapter System.Data.SqlClient, 159
SqlDataReader
GetSqlByteO, 158
GetSqlDouble(), 158
GetSqlStringO, 158
System.Data.SqlClient, 158
SqlHelper
ExecuteDataSetO, 496
ExecuteNonQuery(), 496
ExecuteReaderO, 496
Executescalar(), 496
www.detodoprogramacion.com
ExecuteXmlReader(), 496
SqlTransaction System.Data.SqlClient, 162
StateFilter - Dataview, 169
StoredProcedure - CommandType, 232
STRING - PL / SQL, 70
SUM() - SELECT, 61
SUSPEND - InterBase, 119
SuspendBindingsO BindingManagerBase, 379
System.Da ta
Ambitos, 154
Constraint, 168
ConstraintCollection, 165
Datacolumn, 165
DataRelation, 169
DataRelationCollection, 164
DataRow, 165
DataRowVersion, 167
DataRowView, 276
DataSet, 163
DataTable, 165
DataTableCollection, 164
Dataview, 169, 271
DataViewManager, 271
ForeignConstraint, 168
IBindingList, 275
IColumnMapping, 156
IColumnMappingCollection, 156
IDataAdapter, 159, 414
IDataReader, 157, 414
IDataRecord, 157
IDbCommand, 161, 414
IDbConnection, 161, 176, 414
IDbDataAdapter, 159, 414
IDbTransaction, 161, 437
ITableMapping, 156
ITableMappingCollection, 156
Uniqueconstraint, 168
System.Data.Common
Ambitos, 154
DataAdapter, 159
DataColumnMapping, 156
DataColumnMappingCollection,156
DataTableMapping, 156
DataTableMappingCollection, 156
DbDataAdapter, 159
DbDataPermission, 163
DbDataPermissionAttribute,163
RowUpdatedEventArgs, 163
RowUpdatingEventArgs, 163
System.Data.Odbc
OdbcCommand, 162
OdbcCommandBuilder, 163
OdbcConnection, 162
OdbcTransaction, 162
System.Data.OleDb
Ambitos, 154
OleDbCommand, 162
OleDbCommandBuilder, 163
OleDbConnection, 162
OleDbDataAdapter, 159
OleDbDataReader, 158
OleDbTransaction, 162
System.Data.OracleC1ient
Ambitos, 155
OracleCommand, 162
OracleCommandBuilder, 163
OracleConnection, 162
OracleDataAdapter, 159
OracleDataReader, 158
OracleTransaction, 162
System.Data.SqlClient
Ambitos, 154
SqlCommand, 162
SqlCommandBuilder, 163
SqlConnection, 162
SqlDataAdapter, 159
SqlDataReader, 158
SqlTransaction, 162
System.Data.SqlTypes - Ambitos, 155
System.DirectoryServices
www.detodoprogramacion.com
fndice alfabe'tico
DirectoryEntry, 134
DirectorySearcher, 134
System.Windows.Forms
BindingManagerBase, 378
CurrencyManager, 378
DataGridItem, 406
PropertyManager, 378
System.Xm1
IXPathNavigable, 302
XmlDataDocument, 302
XmlDocument, 297
XmlNode, 302
XmlNodeReader, 299
XmlReader, 296
XmlTextReader, 299
XmlValidatingReader, 299
XmlWriter, 302
System.Xml.XPath
XPathDocument, 297
XPathNavigator, 306
XPathNodeIterator, 306
System.Xml.Xs1
Transform(), 308
XslTransform, 298, 308
T
TABLE - SQL, 50
table - Transact-SQL, 67
Table-Constraints OleDbSchemaGuid, 203
TableDirect - CommandType, 220
Tables
DataSet, 164, 236
OleDbSchemaGuid, 203
targetschema - XML, 129
template - XSLT, 307
text - Transact-SQL, 67
TextBox - Controles, 370
THEN - PL/SQL, 71
TIME - SQL, 52
Transact-SQL
@@IDENTITY,250
BEGIN, 68
BEGIN TRANSACTION, 436
bigint, 67
binary, 67
BREAK, 68
char, 67
COMMIT TRANSACTION, 436
CONTINUE, 68
CREATE PROCEDURE, 69
cursor, 67
decimal, 67
DECLARE, 67
ELSE, 68
END, 68
EXECUTE, 95
float, 67
IF, 68
image, 67
INFORMATION-SCHEMA, 206
int, 67
money, 67
RETURN, 69
ROLLBACK TRANSACTION, 436
smallint, 67
table, 67
text, 67
varbinary, 67
varchar, 67
WHILE, 68
Transform() - System.Xml.Xs1, 308
TRIGGER - SQL, 51
T-SQL - Glosario, 504
U
UDL - Glosario, 504
Unique - Datacolumn, 168
UNIQUE - SQL, 52
Uniqueconstraint - System.Data, 168
www.detodoprogramacion.com
UPDATE
DELETE, 65
SET, 64
SQL, 56
SQL, 64
Update() - IDataAdapter, 159, 241
Updatecommand
DataGrid, 406
IDbDataAdapter, 159
UpdateRule - Foreignconstraint, 168
URI - Glosario, 504
URL - Glosario, 504
V
ValidationType XmlValidatingReader, 300
Value - XmlNode, 302
ValueMember - ListBox, 372
value-of - XSLT, 307
VALUES - SQL, 57
varbinary - Transact-SQL, 67
V ARCH AR
PL/SQL, 70
SQL, 52
varchar - Transact-SQL, 67
VBA - Glosario, 504
VIEW - SQL, 51
Views - OleDbSchemaGuid, 203
X
XML
Glosario, 504
targetschema, 129
XmlDataDocument
DataSet, 310
GetElementFromRow(), 310
GetRowFromElement(), 310
System.Xm1, 302
XmlDocument
DocumentElement, 302
Load(), 302
System.Xm1, 297
XmlNode
Appendchild(), 303
Attributes, 302
ChildNodes, 302
CreateNavigatorO, 303
Firstchild, 302
HasChildNodes, 302
InsertAfterO, 303
InsertBeforeO, 303
Lastchild, 303
Name, 302
Nextsibling, 303
NodeType, 302
ParentNode, 303
PreviousSibling, 303
Removechild(), 303
Replacechild(), 303
SelectNodes(), 303
System.Xm1, 302
Value, 302
XmlNodeReader - System.Xm1, 299
XmlReader - System.Xm1, 296
XmlTextReader - System.Xm1, 299
www.detodoprogramacion.com
fndice alfabe'tico
XmlValidatingReader
System.Xm1, 299
ValidationType, 300
XmlWriter - System.Xm1, 302
XPathDocument System.Xml.XPath, 297
XPathNavigator
Select(), 306
System.Xml.XPath, 306
XPathNodeIterator
Current, 306
MoveNextO, 306
System.Xml.XPath, 306
XSD
complexType, 125
element, 126
Glosario, 504
XSL - Glosario, 504
XSLT
for-each, 307
Glosario, 504
template, 307
value-of, 307
XslTransform System.Xml.Xs1, 298, 308
www.detodoprogramacion.com