Está en la página 1de 218

Programación

Orientada a
Objetos II
2

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 3

ÍNDICE

Presentación 5
Red de contenidos 6
Sesiones de aprendizaje
Unidad de aprendizaje 1
SEMANA 1 : Arquitectura de ADO .NET, conexión a un base de datos, 7
consulta de datos
SEMANA 2 : Operaciones de consultas y recuperación de datos 23
utilizando DataAdapter, DataReader y Command
SEMANA 3 : Manejo del TableAdapter, Usando LINQ to SQL. 39
SEMANA 4 : Modificación de datos de una fuente de datos, manejo de 59
transacciones de datos
Unidad de aprendizaje 2
SEMANA 5 : Operaciones desconectadas con programación 83
SEMANA 6 : Operaciones desconectadas: Manejo del DataView y el 103
DataTableReader desde un DataSet
SEMANA 7 : Semana de exámenes parciales teoría
SEMANA 8 : Semana de exámenes parciales laboratorio
Unidad de aprendizaje 3
SEMANA 9 : Manejo de Crystal Report 115
Unidad de aprendizaje 4
SEMANA 10 : Modelo relacional de objetos: LINQ to SQL 131
SEMANA 11 : Modelo ADO.NET Entity FrameWork, arquitectura 147
SEMANA 12 : Actualización de datos utilizando objetos EntityClient 163
Unidad de aprendizaje 5
SEMANA 13 : Operaciones XML en datos desconectados 177
Procesamiento de datos XML utilizando DOM
SEMANA 14 : Consulta XML utilizando XPath, 201
SEMANA 15 : Examen final de laboratorio
SEMANA 16 : Sustentación de proyectos
SEMANA 17 : Examen final de teoría

CIBERTEC CARRERAS PROFESIONALES


4

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 5

PRESENTACIÓN

Visual Studio 2008 y su plataforma .NET FrameWork 3.5 es un amplio conjunto


de bibliotecas de clases donde se incluye ADO .NET 3.5 que representa las
clases en el Acceso de Datos, el cual sufre de avances importantes en el
aumento de la productividad.

Programación Orientada a Objetos II pertenece a la línea de tecnología y se


dicta en las carreras de tecnología de la institución. El curso brinda un conjunto
de herramientas de programación para trabajar con un origen de datos que
permita al alumno realizar operaciones de consulta y actualización de datos en
forma eficiente.

El manual para este curso ha sido diseñado bajo la modalidad de unidades de


aprendizaje, las que desarrollamos durante semanas determinadas. En cada
una de ellas, hallará los logros que se deberá alcanzar al final de la unidad; el
tema tratado, el cual será ampliamente desarrollado; y los contenidos, que
debe desarrollar. Por último, encontrará las actividades y trabajos prácticos que
deberá desarrollar en cada sesión, que le permitirán reforzar lo aprendido en la
clase.

El curso es eminentemente práctico: consiste en programación visual Basic con


base de datos utilizando ADO .NET. La primera parte de este manual nos
enseña a familiarizarnos con los objetos de ADO .NET para realizar las
consultas y actualizaciones a la base de datos, sea ésta en forma conectada o
desconectada a la fuente de datos, mediante ejemplos didácticos.
Aprenderemos a utilizar los controles enlazados a los datos que permitan
realizar dichos procesos. Luego, vamos a realizar reportes y gráficos utilizando
el motor del Crystal Report, a continuación realizamos operaciones de consulta
actualización a través del objeto Entity; y por último desarrollamos procesos
para manejar XML.

CIBERTEC CARRERAS PROFESIONALES


6

RED DE CONTENIDOS

Programación Orientada a Objetos II

Operaciones de Operaciones Manejo de


consulta y desconectadas Reportes
actualización a un origen de
utilizando datos
ADO.NET

Arquitectu Operacion Manejo de Manejo de Consultas Diseño de Manejo de


ra de de consulta DataAdapter, DataSet, utilizando Crystal parámetros
ADO.NET y actualizar DataReader, DataTable TableDataRe Report
datos Command , ader
Table
Adapter y
LINQ to SQL

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 7

UNIDAD DE
APRENDIZAJE

1
SEMANA

ARQUITECTURA DE ADO .NET, CONEXIÓN A UN


ORIGEN DE DATOS Y CONSULTA DE DATOS

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que se


conectan a un origen de datos utilizando los objetos de ADO.NET para realizar
operaciones de consulta y actualización de datos.

TEMARIO

• Arquitectura y componentes de ADO.NET.


• Administración almacenamiento de una cadena de conexión a un origen de
datos.
• Operaciones de consulta sobre un origen de datos.
• Recuperación de datos utilizando DataAdapter, DataReader y Command
• Manejo de TableAdapter, Usando LINQ to SQL
• Modificación de datos, manejo de transacciones de datos y excepciones.

ACTIVIDADES PROPUESTAS

• Los alumnos se conectan a un origen de datos.


• Los alumnos consultan los datos en un origen de datos, utilizando sentencias SQL.
• Los alumnos consultan los datos por diversos criterios en un origen de datos
utilizando sentencias SQL.
• Los alumnos manejan los controles enlazados a los datos para realizar operaciones
de consulta.

CIBERTEC CARRERAS PROFESIONALES


8

1. INTRODUCCION AL ADO .NET 3.5


En la plataforma .NET, esos servicios reciben la denominación genérica de
ADO.NET, ha llegado a su versión 3.5 con Visual Studio 2008. Esta nueva
iteración aporta una serie de interfaces y objetos, así como nuevos controles y
mejoras en las clases ya existentes, y también en el propio motor que se encarga
de la manipulación de los datos en el cliente, incrementando su rendimiento
considerablemente.

ADO.NET incorpora varios proveedores de datos que permiten conectar con SQL
Server y Oracle, así como otros que facilitan el uso de controladores ODBC y OLE
DB para acceder a aquellos provenientes de Excel, Access, MySQL, etc. Además
incorpora el nuevo modelo de factorías que hace posible un acceso genérico a
orígenes de datos, la obtención de información de esquema, las características
específicas para SQL Server o las nuevas capacidades del objeto Datatable.

2. ARQUITECTURA DE ADO .NET


Tradicionalmente, el procesamiento de datos ha dependido principalmente de
un modelo de dos niveles basado en una conexión. A medida que el
procesamiento de datos utiliza cada vez más arquitecturas de varios niveles, los
programadores están pasando a un enfoque sin conexión con el fin de
proporcionar una escalabilidad mejor para sus aplicaciones.

ARQUITECTURA ADO.NET 2.0

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 9

3. PROVEEDOR DE DATOS ADO .NET

Cualquier aplicación que utiliza


ADO.NET accede a un origen de
datos mediante un Provider o
proveedor de datos. Un
proveedor de datos permite
conectarse a una base e datos,
ejecutar comandos y obtener
resultados. Cada proveedor de
datos implementa interfaces para
sus objetos.

3.1 Implementaciones de los proveedores de datos

Proveedor de Datos de .NET

System.Data.SqlClient: Acceso a datos para SQL Server 7.0 o posterior

System.Data.OleDb: Origen de datos que se exponen mediante OLE DB

System.Data.Odbc: Origen de datos que se exponen mediante ODBC

System.Data.OracleClient: Acceso a datos de Oracle 8.1.7 o posterior

3.2 Objetos principales de los proveedores de datos

3.2.1 Connection: Establece


una conexión a un origen de
datos.
3.2.2 Command: Ejecuta un
comando en un origen de datos.
Expone Parameters y puede
ejecutarse en el ámbito de un
objeto Transaction.
3.2.3 DataReader: Lee una
secuencia de datos de sólo
avance y sólo lectura desde un
origen de datos.
3.2.4 DataAdapter: Llena un
DataSet y realiza las
actualizaciones necesarias en el
origen de datos.

CIBERTEC CARRERAS PROFESIONALES


10

Además de las clases principales citadas en la tabla anterior, los proveedores


de datos de .NET Framework también incluyen las que se enumeran en la tabla
siguiente.

Objeto Descripción
Transaction Permite incluir comandos en las transacciones
que se realizan en el origen de datos.
CommandBuilder Objeto que genera, automáticamente, las
propiedades de comando de un DataAdapter
o que obtiene, de un procedimiento
almacenado, información acerca de
parámetros con las que puede rellenar la
colección Parameters de un objeto
Command.
ConnectionStringBuilder Objeto que genera y maneja una cadena de
conexión utilizada por el objeto Connection.
Parameter Define los parámetros de entrada, salida y
valores devueltos para los comandos y
procedimientos almacenados.
Exception Se devuelve cuando se detecta un error en el
origen de datos. En el caso de que el error se
detecte en el cliente, los proveedores de datos
de .NET Framework inician una excepción de
.NET Framework.
Error Expone la información relacionada con una
advertencia o error devueltos por un origen de
datos.
ClientPermission Se proporciona para los atributos de seguridad
de acceso a código de los proveedores de
datos de .NET Framework.

4. CONEXIÓN A UNA BASE DE DATOS POR ADO .NET


El objeto Connection permite conectarse con un determinado origen de datos
mediante una cadena de conexión en la que se proporciona la información de
autenticación necesaria. El objeto Connection utilizado depende del tipo de
origen de datos.

Cada proveedor de datos de .NET Framework, incluido en .NET Framework,


cuenta con un objeto Connection:

• OleDbConnection, proveedor de datos para OLE DB.


• SqlConnection, proveedor de datos para SQL Server.
• OdbcConnection, proveedor de datos para ODBC.
• OracleConnection, proveedor de datos para Oracle.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 11

4.1 Definición de la cadena de conexión

Para conectarse a una base de datos por ADO .NET, debe proveer de una
cadena de conexión para identificar la base de datos. Los valores que se incluyen
en una cadena de conexión dependen del origen de datos que utilice. A
continuación describiremos algunos parámetros de la cadena de conexión.

Parámetro Descripción
Provider Parámetro para conexiones de datos OLE DB
Initial Catalog o DataBase El nombre de la base de datos
Data Source Nombre o dirección de red del origen de datos
Integrated Security o Si el parámetro es false, debe especificar User
Trusted_Connection ID y Password en la cadena de conexión. Si es
true, la cuenta de autenticación es de
Windows.
User ID Cuenta de usuario
Password Clave de la cuenta de usuario ingresada
Persist Security Info SI el parámetro es false el origen de datos
(data source) no retorna seguridad sensitiva
como el password, por defecto es false.

4.2 Conexión a SQL Server mediante ADO .NET

El Data Provider del .NET Framework para SQL Server provee la conectividad a
SQL Server 7.0 o posterior. Para conectarse a SQL Server utilice la clase
SqlConnection desde el namespace System.Data.SqlClient.

4.2.1 Conexión a SQL Server mediante ADO .NET


1. Defina una cadena de conexión que identifique la base de datos a
conectar.
2. Cree un objeto SqlConnection, pase la cadena de conexión como
argumento al constructor del SqlConnection.
3. Llame al método Open del objeto SqlConnection.
4. Utilice la conexión a la base de datos en su aplicación.
5. Llame al método Close o el método Dispose para cerrar la conexión.
Puede usar una sentencia Using, el cual garantiza que el objeto
SqlConnection se libera.

El siguiente ejemplo muestra como conectarse a la base de datos


BDFactura.

Dim connectionstring As String = _


"Data Source = (local); Initial Catalog = BDFactura; Integrated Security = true"
Dim cn As New SqlConnection(connectionstring)
‘o a través de la Estructura Using
Using cn As New SqlConnection(connectionstring)

End Using

CIBERTEC CARRERAS PROFESIONALES


12

Using: Declara el principio de un bloque Using y, opcionalmente, adquiere


los recursos del sistema que controla el bloque. A veces su código requiere un
recurso no administrado, como un identificador de archivos, un contenedor
COM o una conexión SQL. Un bloque Using garantiza la eliminación de uno o más de
tales recursos cuando su código termina de usarlos. Esto los pone a disposición de otro
código para que los pueda utilizar.

4.3 Conexión con un origen de datos mediante la Librería OleDB


El Data Provider del .NET Framework para OLE DB provee la conectividad
utilizando la clase OleDbConnection desde el namespace
System.Data.OleDbConnection. El proveedor de datos .NET de OLE DB, el
formato de la cadena de conexión es igual al que utiliza en ADO con la
excepción de la palabra clave Provider.

4.3.1 Conexión a un origen de datos mediante ADO .NET


1. Defina una cadena de conexión que identifique la base de datos a
conectar. La cadena de conexión debe incluir un parámetro Provider
para especificar cuál es el OLE DB Provider para establecer la
conexión.
2. Cree un objeto OleDbConnection, pasar la cadena de conexión como
argumento al constructor del OleDbConnection.
3. Llame al método Open del objeto OleDbConnection.
4. Utilice la conexión a la base de datos en tu aplicación
5. Llame el método Close o el método Dispose para cerrar la conexión.
Puede usar una sentencia Using, el cual garantiza que el objeto
OleDbConnection se libera.

Dim connectionstring As String = _


"Provider=SQLOLEDB; server=(local); DataBase=BDFactura; uid=sa;pwd=sql"

Dim cn As New SqlConnection(connectionstring)

4.4 Almacenar una cadena de conexión en un app.config


Almacene una cadena de conexión en un Application Configuration File, sin
tener que editar el código de origen y recompilar la aplicación.

4.4.1 Almacenar una cadena de conexión en un Application


Configuration File
1. Abrir un Application Configuration File (app.config).
2. Dentro de la etiqueta <configuration> añadir una elemento llamado
<connectionStrings>.
3. Dentro de la etiqueta <connectionStrings> añadir un elemento llamado
<add> para cada cadena de conexión.
4. Por cada etiqueta <add> definir un atributo name para especificar el
nombre de la cadena de conexión, definir un atributo connectionString
para especificar la información de la cadena de conexión.

El siguiente ejemplo permite definir una cadena de conexión para la


base de datos BDFactura, la cual se llamara cnfactura.

<connectionStrings>
<add name="cnfactura" connectionString="Data Source=(local);
DataBase=BDFactura; integrated Security=true"/>
</connectionStrings>

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 13

Para utilizar la cadena de conexión almacenada en el app.config, primero


defina el namespace Configuration.ConfigurationManager, que utiliza la
propiedad ConnectionStrings definida en el app.config, tal como se muestra.

Imports System.Data.SqlClient
Imports System.Configuration.ConfigurationManager

Dim cnstring As String= ConnectionStrings("cnfactura").ConnectionString

Using cn As New SqlConnection(cnstring)


......
End Using

5. Ejecutar consultas de base de datos

ADO .NET, posee una clase que permite ejecutar consultas sobre la base de datos:
sentencias SQL embebidas, procedimientos almacenados, funciones; es la clase
SqlCommand. La clase SqlCommand tiene 4 métodos que permite utilizar para
ejecutar sentencias SQL:

SqlCommand Descripción
ExecuteScalar Ejecuta una consulta que retorna un valor.
ExecuteReader Ejecuta una consulta que retorna un conjunto de
datos a un DataReader.
ExecuteNonQuery Ejecuta una Sentencia para actualizar los datos.
ExecuteXmlReader Ejecuta una consulta y retorna un conjunto de
datos en XML.
5.1 Ejecutar una consulta en la base de datos
1. Crear un objeto Connection, tal como SqlConnection.
2. Crear un objeto Command, tal como SqlCommand. En el constructor
especificar la sentencia sql que se va a ejecutar y especificar la conexión.
3. Al ejecutar la sentencia sql, especificar la propiedad CommandType. Si va
a ejecutar una sentencia SQL el valor del CommandType es
CommandType.Text; si va a ejecutar un procedimiento almacenado el
valor del CommandType será CommandType.StoredProcedure.
4. Llame al método Open del objeto Conexión.
5. Ejecute el método del objeto Command, asignando su resultado a una
variable o control.
6. Llame al método Close del objeto conexión.

El siguiente ejemplo permite ejecutar una consulta que retorne el número


de facturas almacenadas en la base de datos BDFactura
Dim cn As New SqlConnection(aConnectionString)
Dim cmd as new SqlCommand(“Select Count(*) From fac_cabe” , cn)
cmd.CommandType=CommandType.Text
cn.Open()

Dim count as Integer=CInt(cmd.ExecuteScalar())


cn.Close()

CIBERTEC CARRERAS PROFESIONALES


14

6. Connection Pooling en ADO .NET


Cuando una aplicación se conecta a un servidor de base de datos, lo primero que
hace es abrir una conexión con el servidor; lo que resulta ser un proceso costoso:
• Desde el punto de vista del cliente, hay que abrir una conexión de red con el
servidor, enviarle una cadena de conexión y esperar la confirmación.
• Desde el punto de vista del servidor, se recibe una solicitud de conexión, se
valida el usuario que desea conectar y se envía al cliente el resultado de la
solicitud.

El objetivo de Connection Pooling es gestionar, en el cliente, un sistema que


almacena conexiones abiertas contra el servidor de base de datos. Para ello,
creará listas de conexiones, agrupadas por el par dominio de la aplicación/cadena
de conexión. Para habilitarlo usaremos Pooling=true. Al conectarse a un servidor
de base de datos, comprueba su pool de conexiones, si existe una que coincida,
utilizará la que tiene en el pool; sino creará una nueva conexión.

En el siguiente ejemplo, se crean tres objetos SqlConnection, pero solo se


necesitan dos grupos de conexión para administrarlos.

Using cn As New SqlConnection(“Server=. ;DataBase=NorthWind; uid=sa”)


cn.Open() ‘Pool A es creado
End Using
Using cn As New SqlConnection(“Server=. ;DataBase=Pubs; uid=sa”)
cn.Open() ‘Pool B es creado
End Using
Using cn As New SqlConnection(“Server=. ;DataBase=NorthWind; uid=sa”)
cn.Open() ‘La conexión coincide con Pool A
End Using

6.1 Adición de conexiones


Por cada cadena de conexión única se crea un grupo de conexión; las
conexiones se agregan al grupo cuando es necesario, hasta el tamaño máximo
del grupo especificado en la propiedad Max Pool Size (100 es el valor
predeterminado), y se liberan del grupo cuando se cierran o eliminan.

6.2 Eliminación de conexiones


Si la aplicación no cierra ni elimina explícitamente sus conexiones, es mejor
asegurarse de que llama claramente a Close y Dispose en las conexiones

7. DBFACTORY CON ADO.NET


Ante la necesidad de escribir aplicaciones que puedan trabajar con cualquier tipo
de base de datos, siempre se ha recurrido al “modelo de n capas” donde una de
ellas, era el proveedor de acceso a datos y se encargaba de abstraer esta tarea,
normalmente encapsulada en una librería “.dll” que se cambiaba a voluntad sin que
ello supusiese ningún problema para la aplicación.

Esta librería, suele contener lo que se denomina un DBFactory, una clase


abstracta o conjunto de funciones encargadas de adaptarse a la base de datos que
se le indique y obtener datos de forma transparente para su consumidor, esta
semana he descubierto como hacerlo con ADO.NET 2.0 sin tener que codificar a
penas nada con las clases que “habitan” en System.Data.Common.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 15

En el siguiente ejemplo, vamos a conectarnos a la base de datos


DBVentas, administrados por SQL Server, utilizando la clase DBFactory.

1. Defina la cadena de conexión en el app.config.

<connectionStrings>
<add name="cn"
connectionString="server=.;database=DBVentas;integrated
security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>

2. En el formulario, defina las librerías para trabajar con el origen de datos.

Imports System.Data.Common
Imports System.Configuration.ConfigurationManager

3. Defina el Proveedor de DBfactory para conectarse a SQL Server.

Private db As DbProviderFactory =
DbProviderFactories.GetFactory(ConnectionStrings("cn").ProviderName)

3. Defina la conexión a la base de datos DBVentas.

Dim cn As DbConnection = db.CreateConnection


cn.ConnectionString = ConnectionStrings("cn").ConnectionString

LABORATORIO 1.1
ACCESO A DATOS EN UN FORMULARIO WINDOWS FORM,
UTILIZANDO EL ASISTENTE
En este Laboratorio, presentamos un formulario Windows Forms sencillo que muestra
los datos de la tabla artículos en una cuadrícula de datos (DataGridView).

1. Ingrese a Visual Studio 2005


2. Selecciona Files -> New ->Project
3. Elija las siguientes opciones:
- En “Project Types” elija “Visual Basic”
- En “Templates” elija “WindowsApplication”
- En “name” coloque “appFacturacion”
- En “Location” coloque “C:\CursoPOOII”

CIBERTEC CARRERAS PROFESIONALES


16

4. En el Formulario, Agregue un control DataGridView, para realizar la conexión a


la base de datos BDFactura, se muestra la lista de tareas tal como se observa
en la figura:

Permite
visualizar la
lista de tareas
del control

5. En la lista de tareas del DataGridView1 (nombre del control) debemos asignar


un origen de datos (Choose Data Source), tal como se muestra en la figura.
Desplegar dicha opción; si no tenemos origen de datos, entonces lo
añadiremos utilizando la opción Add Project Data Source, tal como se
muestra.
Clickea
para elegir
un origen de
datos

Clickea para
añadir un
origen de
datos al
proyecto

6. Al seleccionar la opción Add Project


Data Source, se presenta el
asistente de configuración de origen
de datos. La primera opción es elegir
el tipo de origen de datos Choose a
Data Source Type, seleccione la
opción Database; luego, presione el
botón Next

7. En la segunda ventana del Asistente, permite elegir la conexión de datos


Choose Your Data Connection, el cual podemos seleccionar una conexión;
en caso de que no haya, presione el botón New Connection.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 17

Presione el botón para


crear una nueva
conexión

8. Seleccione el origen de datos, el


cual será Microsoft SQL Server, tal
como se muestra en la figura; luego,
presione el botón OK.

9. Al añadir una nueva conexión, se visualiza una ventana para crear la conexión
a la base de datos, donde se ingrese el nombre del servidor Server Name,
seleccione la autenticación Log on to the Server y seleccione la base de datos
Select o enter a DataBase Name.

Ingrese el servidor, si
utiliza SQL Server 2005,
su servidor será:
(local)\SQLEXPRESS.

Seleccione la
autenticación, que puede
ser por Windows o SQL
Server.

Seleccione la base de
datos de la lista

10. Al crear la conexión, ésta se visualiza en la ventana Choose Your Data


Connection, tal como se muestra en la figura, para continuar con el asistente
presione el botón Next.

Conexión
generada por el
asistente.

Presione la
opción
ConnectionString
para visualizar la
cadena de
conexión.

CIBERTEC CARRERAS PROFESIONALES


18

11. Creada la conexión, debemos elegir la tabla artículos para realizar la consulta,
tal como se muestra en la figura. Se puede observar que junto a la selección de
la tabla artículos se creará un DataSet llamado BDFacturaDataSet, para
almacenar la estructura de la tabla artículos. Luego, presione el botón Finish.

Seleccione la tabla
artículos de la base
de datos.

Al seleccionar el
objeto de base de
datos, se creará un
DataSet.

12. Al finalizar, se visualiza el formulario con el DataGridView1 configurado con la


tabla artículos, luego presione F5 para ejecutar.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 19

LABORATORIO 1.2
ACCESO A DATOS EN UN FORMULARIO WINDOWS FORM,
UTILIZANDO CODIGO DE PROGRAMACION
En este laboratorio, poblaremos un DataGridView con la información de los clientes de
la base de datos DBVentas basada en una cadena select SQL. A continuación,
ejecutaremos los pasos para ejecutar la consulta SQL y mostrar los resultados en la
cuadrícula.
1. Agregue un nuevo formulario de windows al proyecto
2. Agregue un control Label y un control DatGridView tal como se muestra en la
figura.

Control Label

Control
DataGridView

3. En la ventana de código, se definirán el namespace para SQL Server, en la


parte superior, tal como se muestra en la figura.

Imports System.Data.SqlClient

4. Defina, a nivel formulario, la cadena de conexión a la base de datos DBVentas.

Dim strcon As String = "server = .; DataBase=DBVentas;


Integrated Security=True"

5. Defina, a nivel formulario, el objeto Connection: SqlConnection, donde al


inicializar la conexión, pasar la cadena de conexión definida en strcon.
Private cn As New SqlConnection(strcon)

6. Programa las sentencias en el Evento Load del Form1, para listar los clientes:
a. Definir la instancia del objeto DataAdapter llamado da, ejecutando la
sentencia de consulta de la tabla tb_clientes.
b. La sentencia SQL se ejecutará en el método SelectCommand y los
registros resultantes se almacenará en el DataAdapter da.
c. Definir un DataTable llamado tabla.
d. Poblar los registros resultantes de DataAdapter (da) en tabla.
e. Asignar al origen de datos del DataGridView1 el objeto tabla.
f. Ejecutar la aplicación.

Dim da As New SqlDataAdapter(Select * From tb_clientes", cn)

Dim tabla As New DataTable


da.Fill(tabla)
Me.DataGridView1.DataSource = tabla

CIBERTEC CARRERAS PROFESIONALES


20

LABORATORIO 1.3
EJECUTAR UN PROCEDURE EN UN FORMULARIO WINDOWS
FORM, UTILIZANDO DBFACTORY PROVIDER
En este laboratorio, poblaremos un DataGridView al ejecutar un procedimiento
almacenado en la base de datos DBVentas, que visualiza los registros de los
proveedores. Los siguientes pasos permitirán ejecutar un procedimiento almacenado.
1. En el Administrador de la base de Datos, defina el procedimiento almacenado
en la base de datos.

Create Procedure usp_Proveedor


As
Select * From tb_proveedores

2. Agregue un nuevo formulario de windows al proyecto.


3. Agregue un control Label y un control DatGridView.
4. Agregue en el proyecto un app.config para definir una cadena de conexión a la
base de datos DBVentas y defina el proveedor del origen de datos: SqlClient.

<connectionStrings>
<add name="cn"
connectionString="server=.;database=DBVentas;integrated
security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>

5. En la ventana de código, defina las librerías para trabajar con la cadena de


conexión en app.config y con DBFactory.

Imports System.Data.Common
Imports System.Configuration.ConfigurationManager

6. Defina al proveedor DBFactory para conectarse a un origen de datos en SQL


Server.
Private db As DbProviderFactory =
DbProviderFactories.GetFactory(ConnectionStrings("cn").ProviderName)

7. Programe las siguientes sentencias en el evento load del Form1 para ejecutar
el procedimiento almacenado:
a. Defina un DBConnection llamado cn, asigne en la propiedad
ConnectionString el objeto definido en el app.config llamado “cn”.
b. Defina un DBCommand llamado cmd. Asigne: en la propiedad
Connection la conexión cn, en la propiedad CommandText el nombre
del procedure, en la propiedad CommandType el tipo de comando, el
cual será un procedimiento almacenado.
c. Defina un DbDataAdapter llamado da.
d. Asigna en la propiedad SelectCommand del DataAdapter, el comando.
e. Defina un DataTable llamado tabla.
f. Poblar los registros resultantes de DataAdapter (da) en tabla.
g. Asigna al origen de datos del DataGridView1 el objeto tabla.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 21

Dim cn As DbConnection = db.CreateConnection


cn.ConnectionString = ConnectionStrings("cn").ConnectionString

Dim cmd As DbCommand = cn.CreateCommand


cmd.Connection = cn
cmd.CommandText = "usp_proveedor"
cmd.CommandType = CommandType.StoredProcedure

Dim da As DbDataAdapter = db.CreateDataAdapter


da.SelectCommand = cmd
Dim tabla As New DataTable
da.Fill(tabla)
Me.DataGridView1.DataSource = tabla

8. Ejecute la aplicación.

Autoevaluación

1. ¿Cuál es la Arquitectura ADO .NET?


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

2. ¿Cuáles son los proveedores de datos en .NET Framework?


_______________________________________________________________
_______________________________________________________________

3. Defina brevemente los objetos principales de los proveedores de datos


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

4. Defina brevemente los parámetros de una cadena de conexión


_______________________________________________________________
_______________________________________________________________

5. ¿Qué es el Connection Pooling?


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

6. ¿Cuáles son los objetos para realizar una conexión utilizando DBFactory
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

CIBERTEC CARRERAS PROFESIONALES


22

Resumen

 El proveedor de datos .NET de SQL Server o del proveedor de datos .NET de OLE
DB requiere de la instalación de la versión 2.8 de Microsoft Data Access
Components.

 Existen 4 tipos de proveedores de datos: SqlClient, OleDB, ODBC, OracleClient.

 El objeto DataAdapter o adaptador de datos permite llenar un DataSet y realizar


actualizaciones a la base de datos.

 El objeto DataReader es un lector de datos; el objeto DataSet almacena un


conjunto de datos para realizar operaciones de consulta y actualización.

 La conectarse a una base de datos en SQL Server, se requiere de los siguientes


parámetros: Data Source, Inicial Catalog, Integrated Security o User Id.

 La cadena de conexión es almacenada en un app.config dentro de la etiqueta


connectionString.

 El objeto Command ejecuta sentencias SQL, procedimientos almacenados,


funciones, así como sentencias de definición de datos: crear y eliminar tablas.

 Cuando se ejecuta un Command de actualización, se debe abrir la conexión


cn.Open () y al finalizar el proceso cerrar la conexión cn.Close ().

 La librería DBFactory, es una clase abstracta o conjunto de funciones encargadas


de adaptarse a la base de datos que se le indique y obtener datos de forma
transparente para su consumidor, esta semana he descubierto como hacerlo con
ADO.NET 2.0, codificando mínimamente con las clases que “habitan” en
System.Data.Common.

 Si desea consultar mas acerca de estos temas puede consultar las


siguientes paginas:

 http://msdn2.microsoft.com/es-es/library/e80y5yhx(VS.80).aspx
Referencia a ADO.NET 2.0

 http://msdn.microsoft.com/es-es/library/27y4ybxw(VS.80).aspx
Referencia a la arquitectura de ADO.NET

 http://sabia.tic.udc.es/docencia/is/old/2006-2007/docs/transparencias/03-
ADO.NET.pdf
Referencia a ADO.NET, arquitectura, diseño e implementación

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 23

UNIDAD DE
APRENDIZAJE

1
SEMANA

OPERACIONES DE CONSULTA Y RECUPERACION


DE DATOS UTILIZANDO ADO.NET

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que se


conectan a un origen de datos utilizando los objetos de ADO.NET para realizar
operaciones de consulta y recuperación de datos.

TEMARIO

• Arquitectura y componentes de ADO.NET.


• Administración almacenamiento de una cadena de conexión a un origen de
datos.
• Operaciones de consulta sobre un origen de datos.
• Recuperación de datos utilizando DataAdapter, DataReader y Command.
• Manejo de TableAdapter, Usando LINQ to SQL.
• Modificación de datos, manejo de transacciones de datos y excepciones.

ACTIVIDADES PROPUESTAS

• Los alumnos utilizan los objetos de ADO.NET: DataAdapter, DataReader y


Command para realizar las consultas de datos.
• Los alumnos definen y ejecutan procedimientos almacenados para consultar
información de un origen de datos.

CIBERTEC CARRERAS PROFESIONALES


24

1 CONEXIÓN CON DATOS Y RECUPERACION EN ADO .NET


La principal función de cualquier aplicación de base de datos es conectarse a un
origen de datos y recuperar los datos contenidos. Los proveedores de .NET
Framework para ADO.NET sirven como puente entre una aplicación y un origen
de datos, permitiéndole ejecutar comandos y recuperar datos mediante un
DataReader, DataAdapter o un TableAdapter.

2 TRABAJO CON DATAADAPTERS


Un DataAdapter se utiliza para recuperar datos de un origen de datos y llenar
tablas con un DataSet.

El DataAdapter, también, resuelve los cambios realizados en el DataSet de


vuelta al origen de datos. Mediante el objeto Connection del proveedor de datos
de .NET Framework, DataAdapter se conecta a un origen de datos y utiliza
objetos Command para recuperarlos del origen de datos y resolver los cambios a
dicho origen.

Cada proveedor de datos de .NET Framework incluido en .NET Framework


cuenta con un objeto DataAdapter:

Proveedor Descripción
OleDataAdapter Proveedor de datos para OLE DB
SqlDataAdapter Proveedor de datos para SQL Server
OdbcDataAdapter Proveedor de datos para ODBC
OracleDataAdapter Proveedor de datos para Oracle

2.1 Forma de llenar un DataSet desde un DataAdapter


Un DataSet representa un conjunto completo de datos que incluye
restricciones y tablas, así como relaciones entre estas últimas. Dado que
DataSet es independiente del origen de datos, puede incluir datos locales de
la aplicación, así como datos de otros muchos orígenes.

La interacción con los orígenes de datos existentes se controla mediante el


DataAdapter. La propiedad SelectCommand del DataAdapter es un objeto
Command que recupera datos del origen de datos.

El método Fill del DataAdapter se usa para llenar un DataSet con los
resultados de la propiedad SelectCommand del DataAdapter. El método Fill
acepta como argumentos un DataSet que se debe llenar y un objeto
DataTable, o su nombre, que se debe llenar con las filas que devuelve
SelectCommand.

En el siguiente ejemplo de código se muestra cómo crear un objeto


SqlDataAdapter para llenar en el DataSet la lista de Clientes
(Customers) de la base de datos Northwind de SQL Server.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 25

'cn sera el Objeto SqlConnection para la Base de Datos BDFactura


Dim queryString As String = _
"SELECT CustomerID, CompanyName FROM dbo.Clientes"
Dim adapter As New SqlDataAdapter(queryString, cn)
Dim customers As DataSet = New DataSet

'poblar los datos en el DataSet y defina una Tabla “Customers”


adapter.Fill(customers, "Clientes")

3. TRABAJO CON DATAREADERS


El DataReader de ADO.NET recupera secuencias de datos de sólo lectura y sólo
avance de una base de datos. Los resultados se devuelven a medida que se
ejecuta la consulta y se almacenan en el búfer de red del cliente hasta que se
solicitan con el método Read del DataReader.

Con el DataReader puede aumentar el rendimiento de la aplicación tanto al


recuperar datos en cuanto están disponibles como al almacenar (de forma
predeterminada) una fila cada vez en memoria, lo que reduce la sobrecarga del
sistema.

Cada proveedor de datos de .NET Framework incluido en .NET Framework


cuenta con un objeto DataReader:

Proveedor Descripción
OleDataReader Proveedor de datos para OLE DB
SqlDataReader Proveedor de datos para SQL Server
OdbcDataReader Proveedor de datos para ODBC
OracleDataReader Proveedor de datos para Oracle

3.1 Recuperación de datos mediante DataReader


La recuperación de datos mediante DataReader implica crear una instancia del
objeto Command y de un DataReader, para lo cual se llama a
Command.ExecuteReader a fin de recuperar filas de un origen de datos. En el
ejemplo se muestra cómo se utiliza unSqlDataReader, donde command
representa un objeto SqlCommand válido.

'Definir el Objeto CmdReader


Dim CmdReader As New SqlCommand

'reader cargara los datos al ejecutar el Metodo ExecuteReader


Dim reader As SqlDataReader = CmdReader.ExecuteReader()

El método Read del objeto DataReader permite obtener una fila a partir de los
resultados de una consulta.

Para tener acceso a cada columna de la fila devuelta, puede pasar a DataReader
el nombre o referencia numérica de la columna en cuestión.

CIBERTEC CARRERAS PROFESIONALES


26

Sin embargo, el mejor rendimiento se logra con los métodos que ofrece el
DataReader y que permiten tener acceso a los valores de las columnas en sus
tipos de datos nativos (GetDateTime, GetDouble, GetGuid, GetInt32, etc).

En el ejemplo de código siguiente se repite por un objeto DataReader y se


devuelven dos columnas de cada fila.

Dim str As String = ""


Dim query As String = _
"SELECT CustomerID, CompanyName FROM dbo.Customers"

'Definir el Objeto CmdReader


Dim CmdReader As New SqlCommand(query, cn)
Dim reader As SqlDataReader = CmdReader.ExecuteReader()

'Preguntamos si el reader tiene filas


If reader.HasRows Then
'Bucle que se ejecuta si se puede leer un registro en reader
Do While reader.Read
str += reader.GetString(0) + vbTab + reader.GetString(1)
Loop
End If
'Terminado el proceso cerrar el reader
reader.Close()

3.2 Cerrar el DataReader


Siempre debe llamar al método Close cuando haya terminado de utilizar el objeto
DataReader. Tenga en cuenta que mientras está abierto un DataReader, éste
utiliza de forma exclusiva el objeto Connection.

4 TRABAJO CON COMMANDOS

Una vez establecida una conexión a un origen de datos, puede ejecutar:


Sentencias SQL, Procedimiento Almacenados, Funciones y devolver resultados
desde el mismo mediante un objeto Command.

Para crear un comando, puede utilizar el constructor Command, que toma


argumentos opcionales de una instrucción SQL para ejecutar en el origen de
datos, un objeto Connection y un objeto Transaction. También puede crear un
comando para una determinada conexión mediante el método CreateCommand
del objeto Connection. La instrucción SQL del objeto Command se puede
consultar y modificar mediante el uso de la propiedad CommandText. Cada
proveedor de datos de .NET Framework incluido en .NET Framework cuenta con
un objeto Command:

Proveedor Descripción
OleDbCommand Proveedor de datos para OLE DB
SqlCommand Proveedor de datos para SQL Server
OdbcCommand Proveedor de datos para ODBC
OracleCommand Proveedor de datos para Oracle

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 27

4.1 Ejecución de un comando


El objeto Command expone varios métodos Execute que puede utilizar para
llevar a cabo la acción deseada.

Método Descripción
ExecuteReader Los resultados se devuelven en una secuencia
de datos para devolver un objeto DataReader.
ExecuteScalar Retorna valor Singleton.
ExecuteNonQuery Se utiliza para ejecutar comandos que no
retornan filas.

En el siguiente ejemplo de código, se muestra cómo crear un objeto


SqlCommand para ver una lista de categorías de la base de datos
Northwind de SQL Server.

'cn sera el Objeto SqlConnection para la Base de Datos Northwind


Dim cmd As New SqlCommand("Select * from dbo.Categories", cn)

4.2 Ejecución de una consulta que retorne un conjunto de resultados


Los objetos Command de ADO .Net tiene un método ExecuteReader el cual
permite ejecutar una consulta que retorna uno o más conjunto de resultados.

Al ejecutar el método ExecuteReader podemos pasar un parámetro al


método, el cual representa la enumeración CommandBehavior, que permite
controlar al Command como es ejecutado.

A continuación, mostramos la descripción de los enumerables del


CommandBehavior.

Valor del CommandBehavior Descripción


CommandBehavior.CloseConnection Se utiliza para cerrar la
conexión en forma automática,
tan pronto como el DataReader
es cerrado.
CommandBehavior.SingleResult Retorna un único conjunto de
resultados.
CommandBehavior.SingleRow Retorna una fila.

En el siguiente ejemplo, se muestra cómo ejecutar una sentencia SQL que


visualice el nombre y precio de los artículos almacenados en la base de datos
BDFactura.

1. La sentencia SQL a Ejecutar en el comando.


Select art_nombre, art_precio From dbo.Articulos

CIBERTEC CARRERAS PROFESIONALES


28

2. Programe las siguientes sentencias para ejecutar la sentencia sql. Utilice el


bloque Using.
a. Abra la conexión cn.
b. Establecer la estructura Using cmd.
c. Defina un DataReader llamado reader.
d. Ejecute el Command cmd con el método ExecuteReader e indicar la
numeración CommandBehavior.CloseConnection or
CommandBehavior.SingleResult.
e. Preguntamos si tiene filas el reader (HasRows), procedemos a leer los
datos, después de la lectura, cerramos el DataReader.

cn.Open()
Using cmd As New SqlCommand("Select art_nombre, art_precio
From dbo.Articulos", cn)
Dim reader As SqlDataReader
reader = cmd.ExecuteReader( _
CommandBehavior.CloseConnection Or CommandBehavior.SingleResult)
If reader.HasRows Then
While reader.Read
ListBox1.Items.Add(reader.GetString(0) + vbTab + _
reader.GetDecimal(1).ToString)
End While
End If
reader.Close()
End Using

4.3 Ejecución de procedimientos almacenados utilizando Command


Los procedimientos almacenados ofrecen numerosas ventajas en el caso de
aplicaciones que procesan datos. Mediante los procedimientos almacenados,
las operaciones de bases de datos se pueden encapsular en un solo comando,
se optimizan para lograr el mejor rendimiento y disfrutan de una seguridad
adicional.

'El Command ejecutara un Procedimiento Almacenado


Dim cmd As New SqlCommand("usp_Vendedor", cn)
'Establecer la Propiedad CommandType
cmd.CommandType = CommandType.StoredProcedure

Aunque es cierto que para llamar a un procedimiento almacenado basta con


pasar en forma de instrucción SQL su nombre seguido de los argumentos de
parámetros, el uso de la colección Parameters del objeto Command de
ADO.NET permite definir más explícitamente los parámetros del procedimiento
almacenado, así como tener acceso a los parámetros de salida y a los valores
devueltos.

Un objeto Parameter se puede crear mediante el constructor Parameter o al


llamar al método Add de la colección Parameters de Command.
Parameters.Add acepta como entrada argumentos del constructor o cualquier
objeto Parameter ya existente. Al establecer como una referencia nula el valor
de Value de un objeto Parameter, debe utilizar DBNull.Value. En el caso de
parámetros que no sean de entrada (Input), debe asignar a la propiedad
ParameterDirection un valor que especifique cuál es el tipo de parámetro:
InputOutput, Output o ReturnValue.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 29

Para llamar a un procedimiento almacenado, establezca el CommandType del


objeto Command como StoredProcedure. Al asignar el valor
StoredProcedure a CommandType, puede utilizar la colección Parameters
para definir parámetros.

4.3.1 Ejecutar un procedimiento almacenado con parámetro.


1. Ejecute un procedimiento llamado usp_facturas_cliente

CREATE PROCEDURE USP_FACTURAS_CLIENTE


@cli char(5)
AS
Select * from dbo.fac_cabe
Where cli_codigo=@cli

2. Defina un objeto SqlCommand llamado cmd el cual ejecutará el


procedimiento almacenado “usp_facturas_cliente”, defina la propiedad
CommandType a StoreProcedure. Agregue el valor del parámetro @cli.

Using cn As New SqlConnection(strcon)


Dim cmd As New SqlCommand("usp_facturas_cliente", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("@cli",SqlDbType.Char).Value="C0002"
...........

3. Para guardar el resultado del Procedure, se crearán los objetos


DataAdapter y DataSet. A continuación, definido el Command,
definiremos los objetos que guardarán los registros.

...........
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
Dim ds As New DataSet
da.Fill(ds, "Facturas")
End Using

CIBERTEC CARRERAS PROFESIONALES


30

LABORATORIO 2-1
CONSULTA DE DATOS, UTILIZANDO COMMAND
En este escenario, se mostrará los registros almacenados en la tabla clientes de la
base de datos BDFactura; para lo cual se hará uso del objeto Command, para
ejecutar la sentencia SQL, el objeto DataAdapter para recuperar los registros.

1. Ingrese a Visual Studio 2005.


2. Seleccione en el menú Files -> New ->Project.
3. Elija las siguientes opciones de la ventana para crear un nuevo proyecto.
- En “Project Types” elija “Visual Basic”.
- En “Templates” elija “WindowsApplication”.
- En “name” coloque “appFacturacion02.
- En “Location” coloque “C:\CursoPOOII”.

2 Diseñe la siguiente interface de usuario como la siguiente figura:

Control Label

Control
DataGridView

Objeto Propiedad Valor


Label 1 Text Listado de Clientes
DataGridView1

3 Utilice el Namespace System.Data.SqlClient dentro de la clase Form1; agregar


código en el evento load del Form1 para visualizar los clientes al cargar el Form1.
Luego, ejecutar el formulario.

Using cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=DBVentas; integrated security=true")
Using cmd As New SqlCommand("Select* from tb_Clientes", cn)
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
Dim ds As New DataSet
da.Fill(ds, "Clientes")
Me.DataGridView1.DataSource = ds.Tables("Clientes")
End Using
End Using

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 31

LABORATORIO 2-2
CONSULTA DE DATOS, UTILIZANDO COMANDOS
PARAMETRIZADOS
En este escenario desarrollaremos una consulta a las facturas por cliente, donde al
seleccionar un cliente dentro de un ComboBox, visualizamos las facturas
correspondientes al cliente seleccionado.

1. Agregue un nuevo formulario de Windows al proyecto.

Control
ComboBox

Control
DataGridView

Objeto Name Propiedad Valor


Label 1 Label1 Text Seleccione un Cliente
ComboBox1 CboCliente
DataGridView1 DGFactura

2. Cuando necesitamos mostrar en un control de selección: ComboBox o ListBox,


una lista de valores provenientes de un campo de una tabla, debemos configurar
sus propiedades:

Propiedad Descripción
DataSource Origen de datos del control.
DisplayMember Campo a visualizar.
ValueMember Valor del campo permanecerá oculto.

3. Declare e inicialice el objeto Connection, a nivel clase Form2


Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=BDFactura; integrated security=true")

4. En el evento Load Form2, procedemos a cargar el ComboBox CboCliente.


Dim cmd As New SqlCommand( _
"Select cli_codigo, cli_nombre from tb_clientes", cn)
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
Dim tabla As New DataTable
da.Fill(tabla)
Me.CboCliente.DataSource = tabla Addhandler direcciona
Me.CboCliente.DisplayMember = "NombreCia" el evento
Me.CboCliente.ValueMember = "ClienteID" SelectedIndexChanged
Addhandler CboCliente.SelectedIndexChanged, _ del CboCliente al
addressof CboCliente_SelectedIndexChanged método.

CIBERTEC CARRERAS PROFESIONALES


32

5. Definir el método de evento CboCliente_SelectedIndexChanged que permite


desencadenar el evento SelectedIndexChanged del CboCliente, donde al
seleccionar un cliente visualice las facturas.

Private Sub CboCliente_SelectedIndexChanged(ByVal sender


As Object, ByVal e As EventArgs)
Consulta con
Dim cod As String = CboCliente.SelectedValue parámetro @cli

Dim cmd As New SqlCommand( _


"Select * from dbo.fac_cabe Where cli_codigo=@cli", cn)

cmd.Parameters.Add("@cli", SqlDbType.Char).Value = cod

Dim da As New SqlDataAdapter


da.SelectCommand = cmd Agregar el parámetro
@cli en el Command
Dim tabla As New DataTable
da.Fill(tabla)
Me.DGFactura.DataSource = tabla Poblar los datos al
DataTable tabla
End Sub

6. Ejecute el formulario y ejecute la selección en el ComboBox CboCliente.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 33

LABORATORIO 2-3
CONSULTA DE DATOS, UTILIZANDO PROCEDURES Y
PARÁMETROS
En este escenario, desarrollaremos una consulta a las facturas por vendedor y año,
donde al seleccionar un vendedor dentro de un ComboBox y un año dentro de un
ComboBox, visualizamos las facturas correspondientes al vendedor y año
seleccionado.
1. Agregue un nuevo formulario de Windows al proyecto.

Control
ComboBox
CboVendedor

Control Button
BtnConsulta

Control
ComboBox
CboAño

Control
DataGridView
DGFactura

Objeto Name Propiedad Valor


Label1 Label1 Text Vendedor
Label2 Label2 Text Año
ComboBox1 CboVendedor
ComboBox2 CboAño
Button BtnConsulta Text Consulta
DataGridView1 DGFactura

2. Definimos el procedimiento almacenado a ejecutar, donde, en su definición


agregamos dos parámetros.

CREATE PROCEDURE USP_FACTURA_YEAR_VENDEDOR


@ven char(5),
@y int
As
Select * from fac_cabe
Where ven_codigo=@ven and year(fac_fecha)=@y

3. Declaración e inicialización del objeto Connection, a nivel clase Form.

Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=BDFactura; integrated security=true")

CIBERTEC CARRERAS PROFESIONALES


34

4. En el evento Load del Form, procedemos a cargar el ComboBox CboVendedor,


para lo cual ejecutamos una consulta que recupera los datos de los vendedores.

Dim cmd As New SqlCommand( _


"Select Ven_codigo, Ven_nombre from dbo.Vendedor", cn)

Dim da As New SqlDataAdapter


da.SelectCommand = cmd Enlazar el
CboVendedor a tabla,
Dim tabla As New DataTable enlazamos los datos
da.Fill(tabla) en el DisplayMember
y ValueMember
Me.CboVendedor.DataSource = tabla
Me.CboVendedor.DisplayMember = "Ven_nombre"
Me.CboVendedor.ValueMember = "Ven_codigo"

5. En el mismo evento Load del Form, procedemos a cargar el ComboBox CboAño,


para lo cual ejecutamos una consulta que recupera los datos de los Años
facturados. Observamos que los objetos se instancian para ser reutilizados.

cmd = New SqlCommand("Select distinct “ + _


“Year(fac_fecha) as y from dbo.fac_cabe", cn)

da = New SqlDataAdapter
da.SelectCommand = cmd Enlazar el CboAño a
tabla, enlazamos los
tabla = New DataTable datos en el
da.Fill(tabla) DisplayMember y
ValueMember
Me.CboAño.DataSource = tabla
Me.CboAño.DisplayMember = "y"
Me.CboAño.ValueMember = "y"

6. En el evento Click del botón BtnConsulta se realiza el proceso de selección de las


facturas por año y vendedor seleccionado. En este proceso se ejecuta el
Procedure y se añade sus parámetros.

Dim cmd As New SqlCommand("USP_FACTURA_YEAR_VENDEDOR", cn)


cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("@ven", SqlDbType.Char).Value =
CboVendedor.SelectedValue
cmd.Parameters.Add("@y", SqlDbType.Int).Value =
CboAño.SelectedValue

Dim da As New SqlDataAdapter


da.SelectCommand = cmd
Dim tabla As New DataTable
da.Fill(tabla)
Me.DGFactura.DataSource = tabla

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 35

7. Ejecute el formulario y efectuar la selección.

LABORATORIO 2-4
NAVEGACIÓN DE REGISTROS DE DATOS.
En este escenario vamos a navegar por la filas de una tabla de un DataSet, mediante
el empleo de la clase CurrencyManager.

¿Qué es el objeto CurrencyManager?


El objeto CurrencyManager le permite sincronizar controles enlazados a medida que
un usuario examina las filas de una tabla. Por ejemplo, CurrencyManager le permite
mostrar las propiedades FirstName y LastName correctas en controles TextBox
enlazados diferentes a medida que un usuario examina la tabla clientes.

Puede utilizar estos eventos para hacer un seguimiento de cuándo un usuario se


mueve por las filas y de cuándo modifica valores de controles enlazados. En este
laboratorio describe qué acciones se van a realizar para navegación por los registros
de clientes utilizando el objeto CurrencyManager.

1. Agregar un nuevo formulario de Windows al proyecto.

Controles
TextBox

Controles
Button

Objeto Name Propiedad Valor


Label1 Label1 Text Codigo
Label2 Label2 Text Nombre
Label3 Label3 Text Direccion
Label4 Label4 Text Ruc
Textbox1 Txtcodigo Text
Textbox2 Txtnombre Text
Textbox3 Txtdireccion Text
Textbox4 Txtruc Text
Button1 Btnprimero Text |<
Button2 Btnanterior Text <
Button3 Btnsiguiente Text >
Button4 Btnultimo Text >|

CIBERTEC CARRERAS PROFESIONALES


36

2. Definimos la sentencia SQL, donde visualiza los datos de los clientes.

Select cli_codigo, cli_nombre, cli_direccion, cli_ruc


from dbo.clientes

3. Declaración e inicialización del objeto Connection, a nivel clase Form.

Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=BDFactura; integrated security=true")

4. Declarar el objeto CurrencyManager a nivel Form.


Private WithEvents myCurrencyManager As CurrencyManager

5. En el evento Load del Form, cargamos el DataSet ds, que permitirá enlazar los
datos a los TextBox; luego, especificamos el CurrencyManager de la tabla.

Dim daCust As New SqlDataAdapter( _


"Select * from dbo.clientes", cn)
Dim ds As New DataSet()
daCust.Fill(ds, "Clientes")

txtcodigo.DataBindings.Add( _
"Text", ds.Tables!Clientes, "cli_codigo")
txtdireccion.DataBindings.Add( _
"Text", ds.Tables!Clientes, "cli_direccion")
txtnombre.DataBindings.Add( _
"Text", ds.Tables!Clientes, "cli_nombre")
txtruc.DataBindings.Add( _
"Text", ds.Tables!Clientes, "cli_ruc")
'Especificar el CurrencyManager de la tabla Clientes.
myCurrencyManager =
CType(Me.BindingContext(ds.Tables!Clientes), CurrencyManager)

6. En el proceso de navegación, a cada botón se le agregará sentencias de


navegación. En el evento del botón btnprimero, el puntero se ubicará en el primer
registro.
myCurrencyManager.Position = 0

7. En el evento del botón btnanterior, el puntero se ubicará al registro anterior.

If myCurrencyManager.Position > 0 Then


'retroceder una fila.
myCurrencyManager.Position -= 1
End If

8. En el evento del botón btnsiguiente, el puntero se ubicará en el registro siguiente.


If myCurrencyManager.Position < myCurrencyManager.Count Then
'avanzar una fila.
myCurrencyManager.Position += 1
End If

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 37

9. En el evento del botón btnultimo, el puntero se ubicará en el último registro.

myCurrencyManager.Position = myCurrencyManager.Count

Autoevaluación

1. Sobre la base del siguiente formulario, seleccione un mes y año desde los
controles ComboBox, y al hacer click en el botón consulta, visualice las
facturas en el DataGridView que coincidan con el mes y año seleccionado.

2. Construya un formulario de navegación que permita desplazarse y mostrar en


los textbox los datos de las facturas al seleccionar un determinado año en un
control ComboBox. Debe de enlazar en tiempo de ejecución.

CIBERTEC CARRERAS PROFESIONALES


38

Resumen

 En cualquier lenguaje de programación, es necesario una conexión de datos.

 El DataAdapter tiene 4 metodos: SelectCommand ejecuta operaciones de


Consulta, InsertCommand ejecuta operación de Inserción, UpdateCommand
ejecuta operaciones de Actualizacion y DeleteCommand ejecuta operaciones de
eliminación de registros a la base de datos.

 Después de configurar el Command, se puede ejecutar. Los Command admiten 4


tipos de métodos: ExecuteReader ejecuta una instrucción SQL o procedimiento de
Consulta retornando un conjunto de registros que serán almacenados en un
DataReader, ExecuteNonQuery ejecuta una instrucción SQL o procedimiento de
actualización retornando el numero de registros afectados, ExecuteScalar ejecuta
una instrucción SQL o procedimiento almacenado retornando un valor,
ExecuteXMLReader obtiene datos en XML.

 El DataReader de ADO.NET recupera secuencias de datos de sólo lectura y sólo


avance de una base de datos. Los resultados se devuelven a medida que se
ejecuta la consulta y se almacenan en el búfer de red del cliente hasta que se
solicitan con el método Read del DataReader.

 Los comandos parametrizados y procedimientos almacenados con parámetros


utilizan el objeto parameter para definir un parámetro y cargarlo al objeto command
en el método Command.Parameters.Add.

 Los controles enlazados a datos utilizan la propiedad DataSource; para los


controles de lista de datos, utilizan dos propiedades: DisplayMember, que es el
campo a visualizar y el ValueMember, que es el valor del Campo a visualizar
.
 Si desea consultar mas acerca de estos temas puede consultar las
siguientes paginas:

 http://msdn2.microsoft.com/es-es/library/ms254953(VS.80).aspx
Página que referencia al tema de Trabajo con comandos

 http://support.microsoft.com/kb/311543/es
Página que referencia al objeto Currency Manager

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 39

UNIDAD DE
APRENDIZAJE

1
SEMANA

MANEJO DEL TABLEADAPTER, USANDO LINQ TO


SQL

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que se


conectan a un origen de datos utilizando los objetos de ADO.NET para realizar
operaciones de consulta y actualización de datos.

TEMARIO

• Arquitectura y componentes de ADO.NET.


• Administración almacenamiento de una cadena de conexión a un origen de
datos.
• Operaciones de consulta sobre un origen de datos.
• Recuperación de datos utilizando DataAdapter, DataReader y Command.
• Manejo de TableAdapter, Usando LINQ to SQL
• Modificación de datos, manejo de transacciones de datos y excepciones.

ACTIVIDADES PROPUESTAS

• Los alumnos utilizan el asistente del Visual Studio 2005 para crear los objetos de
datos enlazados a un origen de datos.
• Los alumnos realizan operaciones de consulta y actualización de datos en el
TableAdapter.
• Los alumnos utilizan el Mapeo de datos, LINQ, para conectarse a un origen de
datos, para realizar operaciones de consulta y filtro de datos.

CIBERTEC CARRERAS PROFESIONALES


40

1. TABLEADAPTERS
Los TableAdapters proporcionan comunicación entre su aplicación y una base de
datos mediante la ejecución de instrucciones SQL y procedimientos almacenados.

Los TableAdapter se crean con el Diseñador de DataSet dentro de los conjuntos


de datos con establecimiento inflexible de tipos. Se pueden crear con el Asistente
para Configuración de TableAdapter, o arrastrando los objetos de base de
datos del Explorador de servidores al Diseñador de DataSet.

Aunque los objetos TableAdapter se diseñan con el Diseñador de DataSet, las


clases TableAdapter generadas no se generan como clases anidadas de DataSet.
Se encuentran en un espacio de nombres separado y específico para cada
conjunto de datos.

Para tener acceso a un TableAdapter mediante programación, debe


declarar una nueva instancia del TableAdapter.

Dim Ds As New DsFactura


Dim ArticuloTableAdapter As New _
DsFacturaTableAdapters.ArticulosTableAdapter()
ArticuloTableAdapter.Fill(Ds.Articulos)

A diferencia de los DataAdapters, los TableAdapter pueden contener varias


consultas que rellenan las tablas de datos asociadas. Puede definir tantas
consultas para un TableAdapter como requiera la aplicación, con tal de que cada
consulta devuelva datos que cumplan el mismo esquema que la tabla de datos
asociada.

Por ejemplo, si la aplicación contiene una tabla de artículos, puede crear


una consulta para rellenar la tabla con todos los artículos cuyo código sea
igual a un parámetro @cod y otra consulta para rellenar la tabla con todos
los artículos.

Consulta principal del


esquema de la tabla

Consulta adicionales que


retornar diferentes vistas

El nombre asignado a un TableAdapter en el momento de su creación se basa en


el nombre de la tabla con la que está trabajando.

A continuación, se muestran los métodos y propiedades de TableAdapter más


utilizados:

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 41

Miembro Descripción

Rellena la tabla de datos asociada del


TableAdapter.Fill TableAdapter con los resultados del comando
SELECT del TableAdapter.

TableAdapter.Update Devuelve los cambios a la base de datos.

TableAdapter.GetData Devuelve una nueva DataTable con datos.

TableAdapter.Insert Crea una nueva fila en la tabla de datos.

Determina si se vacía una tabla de datos antes de


TableAdapter.ClearBeforeFill
llamar a uno de los métodos Fill.

1.1 UTILIZANDO EL ASISTENTE PARA CONFIGURAR CONSULTAS


DENTRO DE UN TABLEADAPTER
El Asistente para la configuración de consultas de TableAdapter ayuda a
crear y editar las consultas adicionales que se pueden agregar a
TableAdapters. Una consulta de TableAdapter es cualquier consulta SQL
válida o cualquier procedimiento almacenado que devuelve datos que
satisfacen el mismo esquema que la tabla de datos asociada de TableAdapter
o un valor escalar. Para iniciar el Asistente.
1. Abra su conjunto de datos en el Diseñador de DataSet.

Seleccione
el Item
DataSet

Asignarle
un Nombre:
DsFactura

2. Si está creando un nuevo TableAdapter:


o Se puede Arrastrar del ToolBox al DataSet: DsFactura.
o Haciendo click derecho en el DataSet DsFactura, seleccione la opcion
Add  TableAdapter.

Permite agregar un
TableAdapter.

CIBERTEC CARRERAS PROFESIONALES


42

3. En la página Elija la conexión de datos, seleccione o cree la conexión que


utilizará la consulta, al seleccionar Nueva Conexión, deberá indicar el
servidor, autenticación y base de datos, presione el botón OK.

Crear una Nueva


Conexión

Establece la conexión:
• servidor
• autenticación y
• base de datos

4. En la página Elija un tipo de comando, seleccione entre los métodos


siguientes para obtener datos de la base de datos:
o Usar instrucciones SQL permite escribir una instrucción SQL para
seleccionar los datos de la base de datos.
o Crear un nuevo procedimiento almacenado - El asistente crea un nuevo
procedimiento almacenado (en la base de datos) según la instrucción
SELECT especificada.
o Usar procedimientos almacenados existentes - Seleccione esta opción
para ejecutar un procedimiento almacenado existente.

Al seleccionar SQL
Statement, en la siguiente
ventana definir Select.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 43

5. En la página Elegir los metodos que se van a generar, proporciona las


opciones para seleccionar métodos genera el asistente para la consulta.
• Rellenar un DataTable.- Crea un método para rellenar la tabla de datos. El
usuario pasa el nombre de la tabla de datos como un parámetro al llamar a
este método para llenar la tabla de datos con los datos devueltos. También,
puede cambiar el nombre predeterminado en el cuadro Nombre de
método.
• Devolver un DataTable.- Crea un método para devolver una tabla de datos
llena. También puede cambiar el nombre predeterminado en el cuadro
Nombre de método.

Método Fill, para


llenar los datos.

Función GetData,
retorna los registros.

6. Al finalizar se creará un TableAdapter, con


sus métodos Fill(), GetData().

2 ENLACE DE UNA FUENTE DE DATOS EN VISUAL STUDIO


Visual Studio proporciona herramientas en tiempo de diseño para trabajar con
objetos personalizados. El único requisito para que los objetos personalizados
trabajen con las herramientas de diseño de datos de Visual Studio es que deben
contar al menos con una propiedad pública. No se precisa ningún constructor ni
atributo concreto para que los objetos personalizados trabajen con herramientas
como la ventana Orígenes de datos.

En este escenario se muestra cómo crear objetos que contengan datos


de clientes y facturas, y crear a continuación un origen de datos de objeto
basado en estos objetos.

CIBERTEC CARRERAS PROFESIONALES


44

2.1 MÉTODO DE AÑADIR UN DATASET AL PROJECTO


1. En la opción Menu Project  Add New Item.
2. Selecione la opción DataSet, asignarle el Nombre Facturación.xsd, presione
el botón Add.

2.2 CREACIÓN DE UNA CONEXIÓN A LA


BASE DE DATOS BDFACTURA
1. En la opción Menu View click en Server
Explorer
2. En el Server Explorer, cree una conexión a
la Base de Datos: click derecho a
DataConnections, seleccione Add
Connection….
3. Cree la conexión a la base de datos
BDFactura de SQL SERVER.

2.3 CREACIÓN DE LA TABLA CLIENTES


1. Expanda la Data Connection y expanda el
Nodo Tables.
2. Arrastre la tabla Clientes del Server Explorer al
Diseñador del DataSet; una tabla clientes y
clientesTableAdapter son añadidos al DataSet.

2.4 CREACIÓN DE TABLA FACTURAS


1. Arrastre la tabla Fac_ al Diseñador del
DataSet; la tabla fac_cabe y fac_cabeTableAdapter son añadidos.

2.5 CREACIÓN DE DATARELATIONS DENTRO


DEL DATASET
1. Arrastre un objeto relation desde el ToolBox
del DataSet hacia la tabla hija de la relación
(Fac_cabe).

2. Seleccione la tabla Parent


(clientes), verifique la tabla Chile
(fac_cabe), se visualizan las
columnas a relacionar. En tipo de
relación a crear es Relation
Only, significa que sólo es
consulta entre ambas tablas;
luego, presione el botón OK.

3. Al presionar el botón OK se creará la


relación, en la cual aparecerá en el
diseñador entre las dos tablas.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 45

2.6 FORMA DE POBLAR UN DATASET CON DATOS UTILIZANDO UN


TABLEADAPTER
Para poblar un DataTable utilizando
un TableAdapter, ejecute el método
Fill del TableAdapter para cargarlo
hacia la tabla. En el Load del Form,
poblar la tabla clientes del DataSet
Facturación, utilizar el método Fill
del TableAdapter a la tabla clientes
y muestre los datos en el
DataGridView.

Dim ds As New Facturacion


Dim cli As New FacturacionTableAdapters.ClientesTableAdapter
cli.Fill(ds.Clientes)
Me.DataGridView1.DataSource = ds.Clientes

3 LINQ PARA .NET


Se conoce como LINQ a un Lenguaje Integrado de Consultas (Language Integrated
Query). Nos va a permitir poder manipular mejor la información dentro de nuestras
aplicaciones.

Se basa en varias funcionalidades, tales como colecciones que pueden incluir


arreglos, clases, enumerables, XML y base de datos.

El proyecto LINQ usa características de la versión 2.0 del .NET Framework, nuevos
ensamblados relacionados con LINQ, y extensiones para los lenguajes C# y Visual
Basic .NET. Microsoft ha distribuido una versión previa del LINQ, consistente de
estas bibliotecas y compiladores para C# 3.0 y Visual Basic 9. Otros lenguajes,
como F# y Nemerle, han anunciado brindar soporte preliminar.

La arquitectura LINQ es el siguiente:

CIBERTEC CARRERAS PROFESIONALES


46

3.1 LINQ to SQL


LINQ to SQL es una implementación de O/RM (object relational mapping,
mapeador de objetos relacionales) que viene con la versión 2008 del .NET
Framework, y permite modelar bases de datos relacionales con clases de
.NET. Podemos consultar bases de datos con LINQ, así como
actualizar/añadir/borrar datos de ellas.

Hay dos herramientas disponibles para generar automáticamente un modelo de


Visual Basic o C# a partir de los metadatos de una base de datos existente:
• El Diseñador relacional de objetos proporciona una interfaz de usuario
completa para ayudarle a generar un modelo de objetos LINQ to SQL.
• Herramienta de línea de comandos SQLMetal.

3.1.1 Diseñador relacional de objetos


El Diseñador relacional de objetos proporciona una superficie de diseño
visual para crear clases de entidad y asociaciones (relaciones) de LINQ
to SQL basadas en los objetos de una base de datos.
El Diseñador relacional de objetos se usa para crear un modelo de
objetos en una aplicación que se asigna a los objetos de una base de
datos. Genera una clase DataContext con establecimiento inflexible de
tipos, que se usa para enviar y recibir datos entre las clases de entidad
y la base de datos. El Diseñador relacional de objetos también
proporciona la funcionalidad para asignar los procedimientos
almacenados y funciones a los métodos de DataContext con el fin de
devolver datos y rellenar las clases de entidad. Por último, el Diseñador
relacional de objetos permite diseñar relaciones de herencia entre las
clases de entidad.

3.1.2 Entendiendo la clase DataContext


Visual Studio genera clases .NET para representar las entidades y las
relaciones de la base de datos que hemos modelado.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 47

Por cada archivo añadido a nuestra solución por el diseñador LINQ to


SQL también se generará una clase DataContext. Esta clase es a través
de la cual realizaremos las consultas a las entidades de nuestra base de
datos. Tendrá propiedades que representarán a cada tabla que hemos
modelado, así como métodos para cada procedimiento almacenado que
añadiremos.

La clase
tb_empleados, que
representa a la tabla
tb_empleados

3.1.3 Consultando datos sobre la base de datos


LINQ to SQL, admite toda la funcionalidad clave que puede esperar un
programador de SQL. Puede consultar, insertar, actualizar y eliminar
información en las tablas.
En la selección, basta con que escriba una consulta LINQ en su propio
lenguaje de programación y, después, la ejecuta para recuperar los
resultados. LINQ to SQL convierte todas las operaciones necesarias en
las operaciones SQL con las que está familiarizado.
Una vez que hemos modelado nuestra base de datos con el diseñador
de LINQ to SQL, podemos escribir código fácilmente para trabajar con
él. Por ejemplo: listar los clientes y visualizarlos en el DataGridView.

Dim db As New DataDBVentasDataContext


Dim cliente = From c In db.tb_clientes
Me.DataGridView1.DataSource = cliente

CIBERTEC CARRERAS PROFESIONALES


48

LABORATORIO 3.1
MANEJO DE CONSULTA EN UN TABLEADAPTER
En este escenario usted creará un TableAdapter, donde creará una consulta sql que
permita visualizar los pedidos entre dos fechas, además visualice la cantidad de
facturas resultantes del proceso.

1. Ingrese a Visual Studio 2005.


2. Seleccione File->New->Project.
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “WindowsApplication”.
- En “Name” coloque “appFacturacion5”.
- En “Location” coloque “C:\CursoPOOII ».

4. Dentro de la aplicación añadir un item de tipo


DataSet asígnele el nombre
DBVentasDataSet.
5. Agregue un TableAdapter de la tabla
tb_pedidoscabe.
6. A continuación, añada un procedimiento
almacenado: click derecho en el TableAdapter y
seleccione Add Query tal como se muestra en
la Figura.

7. En la página Elija un tipo de


comando seleccione la
opción: Usar instrucción
SQL, presione Next.

8. En la página Elija un tipo de


Consulta seleccione la primera
opción: SELECT which return
rows, esta opción permite retornar
un conjunto de filas, presione el
botón Next.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 49

9. En la página Especifique una


instrucción Select de SQL,
defina la sintaxis del procedimiento
almacenado:
Select * From tb_pedidoscabe
Where fechapedido between @f1
and @f2.
Luego presione el botón Next.

10. Asigne un nombre a la instrucción


FillbyFechas, luego presione el
boton Finish.

11. A continuación proceda a diseñar el formulario:

Objeto Name Propiedad Valor


Label1 Label1 Text Fecha 1
Label2 Label2 Text Fecha 2
DateTimePicker1 DtFecha1 Format Short
DateTimePicker2 DtFecha2 Format Shor
Button1 BtnConsulta Text Consulta
DataGridView1 DGFacturas

12. A nivel Clase Form, defina el objeto DataSet: ds y el objeto TableAdapter


fac_Adapter.

Private Ds As New DBVentaDataSet


Private Pedido As New
DBVentaDataSet.tb_pedidoscabeTableAdapter

13. Para listar todas las facturas en el evento Load del Formulario se cargará al
DataTable fac_cabe a través del método Fill del TableAdapter y luego visualice
los datos.
Pedido.Fill(Ds.Fac_cabe)
Me.DGFacturas.DataSource = Ds.tb_pedidoscabe

CIBERTEC CARRERAS PROFESIONALES


50

14. Para listar las facturas entre dos fechas, en el evento click del botón consulta,
se ejecutará el método FillBy con sus dos parámetros de fecha, que representa
al Procedure creado: usp_facturas_byfechas, para cargarlo al DataTable y,
luego, visualizar los datos.

Dim f1 As Date = Me.DtFecha1.Value.ToShortDateString


Dim f2 As Date = Me.DtFecha2.Value.ToShortDateString
Pedido.FillByFechas(Ds.tb_pedidoscabe, f1, f2)
Me.DGFacturas.DataSource = Ds.tb_pedidoscabe

15. Ejecute y realice las pruebas.

LABORATORIO 3.2
RELACIONES ENTRE TABLEADAPTER
En este escenario, vamos a realizar un consulta entre los clientes y sus pedidos,
donde al seleccionar un cliente, visualizamos los pedidos asociada al cliente
seleccionado.
Para ello creamos un TableAdapter para los clientes y estableceremos la relación
entre las tablas del DataSet.

1. En el DataSet: DBVentasDataSet Agregue un TableAdapter llamado tb_clientes,


el cual contenga todos los campos de dicha tabla.
2. Creado el TableAdapter para tb_clientes, establezca la relación entre las tablas,
que solo sea de tipo relación, el nombre de la relación será: Clientes_Ped_cabe.

Relación:
Clientes_Pec_cabe

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 51

3. Diseñe el Formulario.

Objeto Name Propiedad Valor


Label1 Label1 Text Clientes
Label2 Label2 Text Facturas
DataGridView1 DGCliente
DataGridView2 DGFactura

4. Declare a nivel Clase Form el DataSet y los TableAdapter de clientes y facturas.

Private Ds As New DBVentasDataSet


Dim Cli_TableAdapter As New _
- DBVentasDataSetTableAdapters.tb_ClientesTableAdapter
-
Dim Fac_TableAdapter As New _
- DBVentasDataSetTableAdapters.tb_pedidoscabeTableAdapter
-

5. En el evento Load del Formulario, cargue los Tables de las tablas clientes y
fac_cabe con los TableAdapter, muestre los clientes en el DataGridView:
DGCliente.
Cli_TableAdapter.Fill(Ds.tb_Clientes)
Fac_TableAdapter.Fill(Ds.tb_pedidoscabe)
Me.DGCliente.DataSource = Ds.tb_Clientes

6. En el evento CellCllick del DataGridView DGCliente, al seleccionar un cliente,


visualice sus facturas; seleccione una fila del cliente y capture el indice de la fila
seleccionada: DGCliente.CurrentRow.Index, y utilizando un DataView y un
DataRowView cree la vista hija (ChildView).
Dim i As Integer = Me.DGCliente.CurrentRow.Index
Dim dv As DataView = Ds.tb_Clientes.DefaultView
Dim drv As DataRowView = dv(i)
Me.DGFactura.DataSource = _
drv.CreateChildView("Clientes_Ped_cabe")

7. Guarde la aplicación y ejecute. Pruebe los resultados.

CIBERTEC CARRERAS PROFESIONALES


52

LABORATORIO 3.3
EJECUTAR UN PROCEDIMIENTO ALMACENADO UTILIZANDO
UN TABLAADAPTER
En este escenario, vamos a ejecutar un procedimiento almacenado de consulta que
liste los pedidos de un año seleccionado.

1. Defina el procedimiento
almacenado en la base de datos
llamado usp_pedidos_year.

2. Arrastre el procedimiento almacenado


usp_pedidos_year al DataSet:
DBVentasDataSet, tal como se muestra.

Método Fill y GetData que


define el parámetro @y

3. Diseñe el formulario de la consulta.

Objeto Name Propiedad Valor


Label Label1 Text Consulta de Pedidos por Año
Label Label2 Text Año
TextBox txtAño
Button BtnConsulta Text Consulta
DataGridView DataGridView1

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 53

4. Declare a nivel Clase Form el DataSet y los TableAdapter de clientes y facturas

Private Ds As New DBVentasDataSet


-
Private pedidos As New _
- DBVentasDataSetTableAdapters.usp_pedidos_yearTableAdapter
-
5. En el evento Click del Button BtnConsulta, ejecute el método Fill de pedidos
donde definimos la tabla usp_pedidos_year y el valor del año: txtaño.text.
Visualice los registros de la tabla en el DataGridView1.
pedidos.Fill(Ds.usp_pedidos_year, Val(TXTAÑO.Text))

Me.DataGridView1.DataSource = Ds.usp_pedidos_year

6. Guarde la aplicación y ejecute. Al ingresar un año desde el control TxtAño, al


presionar el botón CONSULTA, se visualiza los pedidos.

LABORATORIO 3.4
MANEJO DE CONSULTAS UTILIZANDO LINQ to SQL
En este escenario, vamos a realizar la consulta de los pedidos por un empleado
seleccionado. Para ello vamos a utilizar LINQ to SQL para realizar la consulta de los
pedidos.

1. Agregue un nuevo elemento


en el proyecto de Windows.
2. Seleccione la plantilla
Clases de LINQ to SQL,
asigne el nombre
DataVentas.dbml

Seleccione la plantilla
para el manejo de las
tablas como clases.

CIBERTEC CARRERAS PROFESIONALES


54

3. Desde el explorador de
servidor arrastre las
tablas hacia el diseñador
llamado
DataVentas.dbml, tal
como se muestra.

4. Para establecer la relación entre


las clases, agregue una
Asociación.
En el editor de asociaciones
seleccione:
• Clase primaria la tabla
tb_empleados y
• Clase secundaria la tabla
tb_pedidoscabe.
En la sección propiedades de la
asociación, elija el campo
IdEmpleado para ambas
propiedades; luego presione el
botón Aceptar para generar la
asociación.

5. A continuación diseñe el Formulario de la consulta.

Objeto Name Propiedad Valor


Label Label1 Text Consulta de Pedidos por
Empleado
Label Label2 Text Empleado
ComboBox ComboBox1
Button BtnConsulta Text Consulta
DataGridView DataGridView1

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 55

6. A continuación defina la instancia de DataVentasDataContext a nivel Formulario.

Private Data As New DataVentasDataContext

7. En el evento Load del Formulario, declare la variable empleado para definir los
empleados desde Data. Cargue los empleados en el ComboBox1.
Dim empleado = From emp In Data.tb_empleados

Me.ComboBox1.DataSource = empleado
Me.ComboBox1.DisplayMember = "Nombre"
Me.ComboBox1.ValueMember = "IDempleado"

8. En el evento Click del button BtnConsulta, declare la variable pedidos para definir
la clase tb_pedidoscabe desde el DataVentasDataContext Data y realizar la
consulta de pedidos (p) por empleado seleccionado.

Dim pedidos = From p In Data.tb_pedidoscabe _


Where p.IdEmpleado=ComboBox1.SelectedValue.toString Select p

Me.DataGridView1.DataSource = pedidos

9. Guarda la aplicación y ejecute. Al seleccionar un empleado desde un ComoBox,


listamos los pedidos.

LABORATORIO 3.5
MANEJO DE CONSULTA DE PEDIDOS ENTRE FECHAS
UTILIZANDO LINQ to SQL
En este escenario, vamos a realizar la consulta de los pedidos entre dos fechas
ingresadas. Para ello vamos a utilizar en DataConText DataVentasDataContext.

1. Diseña el formulario.

CIBERTEC CARRERAS PROFESIONALES


56

Objeto Name Propiedad Valor


Label Label1 Text Consulta de Pedidos entre
Fechas
Label Label2 Text Fecha 1
Label Label3 Text Fecha 2
TextBox TxtFecha1
TextBox TxtFecha2
Button BtnConsulta Text Consulta
DataGridView DataGridView1

2. A continuación defina la instancia de DataVentasDataContext a nivel Formulario

Private Data As New DataVentasDataContext

3. En el evento Click del button BtnConsulta, declare la variable pedidos para definir
la clase tb_pedidoscabe desde el DataVentasDataContext Data y realizar la
consulta de pedidos (p) entre dos fechas.

Dim f1 As Date = CDate(TXTFECHA1.Text)


Dim f2 As Date = CDate(TXTFECHA2.Text)

Dim pedidos = From p In data.tb_pedidoscabe _


Where p.FechaPedido >= f1 And p.FechaPedido <= f2 Select p

Me.DataGridView1.DataSource = pedidos

4. Guarde la aplicación y ejecute. Al ingresar dos fechas desde los TextBox listaremos
los pedidos entre las fechas ingresadas.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 57

Autoevaluación

1. ¿Qué es un TableAdapter y cuáles son los métodos que utiliza con más
frecuencia? Explique brevemente.

2. ¿Cuáles son las diferencias que existen entre un TableAdapter y un


DataAdapter?

3. ¿Cuáles son los pasos para crear un TableAdapter para una tabla específica?

4. Si al TableAdapter se le desea añadir un nuevo Stored Procedure, explique


cuáles son los pasos para agregar un Nuevo Stored Procedure al
TableAdapter.

5. ¿Cómo se pueden crear relaciones entre las tablas del DataSet? Explique los
pasos.

6. ¿Cuáles son las sentencias de programación que permite poblar los datos de
un TableAdapter a un DataTable?

7. Explique el concepto del LINQ to SQL.

8. ¿Cuáles son las herramientas para trabajar con LINQ to SQL?

9. Se tiene dos tablas relacionales: Vendedores y Fac_cabe ¿Cuáles son las


sentencias de programación donde al seleccionar un vendedor, visualice sus
Facturas?

10. Desarrolle una aplicación que permita realizar la consulta de


las facturas al seleccionar un año y un mes. Para ello, debe
trabajar toda la estrategia utilizando TableAdapter.

CIBERTEC CARRERAS PROFESIONALES


58

Resumen
 Los TableAdapters proporcionan comunicación entre su aplicación y una base de
datos mediante la ejecución de instrucciones SQL y procedimientos almacenados.
El TableAdapter carga los datos devueltos en su tabla de datos asociada de la
aplicación o devuelve nuevas tablas de datos ya rellenadas.

 A diferencia de los DataAdapters, los TableAdapter pueden contener varias


consultas que rellenan las tablas de datos asociadas. Puede definir tantas
consultas para un TableAdapter como requiera la aplicación, con tal de que cada
consulta devuelva datos que cumplan el mismo esquema que la tabla de datos
asociada.

 El Asistente para la configuración de consultas de TableAdapter ayuda a crear y


editar las consultas adicionales que se pueden agregar a TableAdapters. En un
TableAdapter se pueden Agregar:

o Sentencias SQL de consulta y actualización.


o Agregar Procedures Existentes.
o Agregar nuevos Procedures.

 Visual Studio proporciona herramientas en tiempo de diseño para trabajar con


objetos personalizados. El único requisito es que deben contar, al menos, con una
propiedad pública. No se precisa ningún constructor ni atributo concreto para que
los objetos personalizados trabajen con herramientas como la ventana Orígenes
de datos.

 Los TableAdapters se crean con métodos que se pueden ejecutar directamente


contra la base de datos. A estos métodos (TableAdapter.Insert,
TableAdapter.Update y TableAdapter.Delete) se les puede llamar de forma directa
para manipular los datos de la base de datos.

 LINQ to SQL es una implementación de O/RM (object relational mapping,


mapeador de objetos relacionales) y permite modelar bases de datos relacionales
con clases de .NET. Podemos consultar bases de datos con LINQ, así como
actualizar/añadir/borrar datos de ellas.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://msdn2.microsoft.com/es-es/library/7zt3ycf2(VS.80).aspx
Página referente al TableAdapter

 http://msdn2.microsoft.com/es-es/library/87sfaezs(VS.80).aspx
Página referente a la consulta de Datos

 http://thinkingindotnet.wordpress.com/2007/05/20/usando-linq-to-sql-
1%c2%aa-parte/
Página referente al LINQ en .NET

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 59

UNIDAD DE
APRENDIZAJE

1
SEMANA

OPERACIONES DE ACTUALIZACION Y MANEJO DE


TRANSACCIONES UTILIZANDO ADO.NET

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que se


conectan a un origen de datos utilizando los objetos de ADO.NET para realizar
operaciones de consulta y actualización de datos.

TEMARIO

• Arquitectura y componentes de ADO.NET.


• Administración almacenamiento de una cadena de conexión a un origen de
datos.
• Operaciones de consulta sobre un origen de datos.
• Recuperación de datos utilizando DataAdapter, DataReader y Command.
• Manejo de TableAdapter, Usando LINQ to SQL.
• Modificación de datos, manejo de transacciones de datos y excepciones.

ACTIVIDADES PROPUESTAS

• Los alumnos definen y ejecutan procesos para actualizar datos de un origen de


éstos utilizando sentencias sql, TableAdapter o LINQ to SQL.
• Los alumnos identifican los tipos de transacciones en ADO.NET, locales o
distribuidas.
• Los alumnos manejan las transacciones en una capa de datos.

CIBERTEC CARRERAS PROFESIONALES


60

1 MODIFICAR DATOS EN UN ORIGEN DE DATOS

La mayoría de las aplicaciones escritas en Visual Basic y Visual C# giran en torno


a la lectura y actualización de información de bases de datos. Para permitir la
integración de datos en aplicaciones distribuidas y escalables, Visual Studio .NET
es compatible con una nueva generación de tecnología de acceso a datos:
ADO.NET.

El modo de comunicación entre nuestra aplicación y la base de datos implica que


ambos manejen un lenguaje de programación común; entonces para resolver este
problema de comunicación es que se usa el SQL (Structured Query Languaje) o
lenguaje estructurado de consultas.

Para ejecutar las instrucciones SQL a la base de datos se realiza mediante los
OBJETOS ADO.NET, las cuales proporcionan acceso coherente a orígenes de
datos como Microsoft SQL Server, así como a orígenes de datos expuestos
mediante OLE DB y XML.

Entre los objetos que permiten realizar este proceso tenemos:


• Objetos Command, uso de sentencias SQL.
• TableAdapter.
• LINQ to SQL.

1.1 MODIFICACION DE DATOS UTILIZANDO COMMAND


El objeto Command permite ejecutar sentencias SQL o procedimientos
almacenados sobre una base de datos. Las instrucciones SQL que modifican
datos (por ejemplo INSERT, UPDATE o DELETE) no devuelven ninguna fila.
De la misma forma, muchos procedimientos almacenados realizan alguna
acción pero no devuelven filas. Para ejecutar comandos de actualización,
creamos un objeto Command con el comando SQL adecuado y una
Connection, incluidos los Parameters necesarios. El objeto Command se
debe ejecutar con el método ExecuteNonQuery.

El método ExecuteNonQuery devuelve un entero que representa el número


de filas que se ven afectadas por la instrucción o por el procedimiento
almacenado que se haya ejecutado. Si se ejecutan varias instrucciones, el
valor devuelto es la suma de los registros afectados por todas las
instrucciones ejecutadas.

En el ejemplo siguiente se ejecuta una instrucción INSERT para


aplicar un registro en una base de datos mediante el método
ExecuteNonQuery.

connection.Open()

Dim sql As String = "INSERT Customers(CustomerID,CompanyName) " & _


" Values('NWIND', 'Northwind Traders')"

Dim command As New SqlCommand(queryString, connection)


Dim registros As Int32 = command.ExecuteNonQuery()

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 61

Para ejecutar un procedimiento almacenado utilizando el objeto Command,


debe indicar el nombre del procedimiento a través de la propiedad
CommandText, y además indicar que el objeto a ejecutar es un
procedimiento almacenado a través de la propiedad CommandType.
Agregue sus parámetros del procedimiento a través de la colección
Parameters. Para ejecutar el procedure utilice el método ExecuteNonQuery
devuelve un entero que representa el número de filas que se ven afectadas
por el procedimiento almacenado que se haya ejecutado.

En el ejemplo de código siguiente se ejecuta el procedimiento


almacenado para insertar un registro a la tabla tb_paises, que reciba
dos parámetros de entrada.

Dim command As New SqlCommand("InsertPais" , connection)


command.CommandType = CommandType.StoredProcedure

command.Parameters.Add("@id", SqlDbType.Int).Value=12
command.Parameters.Add("@Name", SqlDbType.Char, 15).Value="Iran”

Dim rowCount As Int32 =command.ExecuteNonQuery()

1.2 MODIFICACION DE DATOS UTILIZANDO TABLEADAPTER


Los TableAdapters definen métodos que se ejecutar directamente contra la
base de datos. A estos métodos (TableAdapter.Insert, TableAdapter.Update y
TableAdapter.Delete) se les puede llamar de forma directa para manipular los
datos de la base de datos.

Si no desea crear estos métodos directos, establezca la propiedad


GenerateDbDirectMethods de TableAdapter en false en la ventana
Propiedades. Cualquier consulta agregada a TableAdapter, además de la
consulta principal, es una consulta independiente, no genera estos métodos
DbDirect.

a) Para insertar nuevos registros directamente en una base de datos


Llame al método Insert del TableAdapter, pasando los valores de cada
columna como parámetros.
b) Para actualizar registros directamente en una base de datos
Llame al método Update del TableAdapter, pasando los valores nuevos
y originales de cada columna como parámetros.
c) Para eliminar registros directamente de una base de datos
Llame al método Delete del TableAdapter, pasando los valores de cada
columna como parámetros de Delete.

1.2.1 MODO DE GUARDAR UN DATASET TIPEADO UTILIZANDO UN


TABLEADAPTER
Después que la Data en el DataSet ha sido modificada y validada,
probablemente quiere enviarla para actualizar la data a la base de
datos. Para modificar la data de la base de datos llame al método
Update del TableAdapter o DataAdapter. El método Update del
DataAdapter, actualizará una tabla y ejecuta los comandos INSERT,
UPDATE y DELETE basado en el estado de la fila RowState.

CIBERTEC CARRERAS PROFESIONALES


62

Al actualizar un origen de datos (Data Source) dentro de un DataSet,


puede contener errores, se debería colocar el código que ejecuta el
método Update dentro del bloque Try … Catch.
Try
Tablacli.Update(Facturacion.Clientes)
Catch ex As Exception
Messagebox.Show(“No se Actualizó”)
End Try

1.2.2 MODO DE GUARDAR DOS TABLAS RELACIONADAS EN UN


DATASET UTILIZANDO UN TABLEADAPTER
Cuando actualiza tablas en un DataSet., es importante actualizar los
datos según la prioridad para reducir los cambios de una violación del
constraint de integridad referencial. Para prevenir los errores de la
integridad de datos, la mejor práctica es actualizar la Base de Datos en
la siguiente secuencia:
1. Tabla Hija: Eliminar registros
2. Tabla Padre: Insertar, Actualizar y Eliminar registros.
3. Tabla Hija: Insertar y Actualizar registros.
Debería incluir todas las actualizaciones lógicas dentro de una
transacción.

1.2.3 VISUALIZACIÓN DE DATOS EN DATA GRID DEL FORM


Puede visualizar datos en un DataGridView si arrastra los elementos
de la Ventana de origen de datos a su formulario. Antes de arrastrar
desde la ventana orígenes de datos, establezca el tipo de control de
la tabla en DataGridView. Una alternativa de mostrar los datos en una
cuadrícula es mostrar los datos en controles individuales.

Para visualizar datos en un DatagridView


del Windows Form

1. Abra la Ventana Data Source:


2. Opción de menú Data.
3. Seleccione la tabla en el Data Source.

4. Arrastre la Tabla del Data Source al


formulario. Se visualizará:
a. Un control DataGridView.
b. Un BindingNavigator, navegar por los registros.
c. Un DataSet, un TableAdapter, BindingSource y
BindingNavigator.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 63

2 TRANSACCIÓN EN .NET
Cuando se compra un libro de una librería en línea, se intercambia dinero (en
forma de crédito) por el libro. Si el crédito es correcto, una serie de operaciones
relacionadas garantiza que se obtiene el libro y que la librería obtiene el dinero.
Sin embargo, si una operación sufre un error durante el intercambio, el error
afecta a la totalidad del proceso. No se obtiene el libro y la librería no obtiene el
dinero.

Las transacciones garantizan que los recursos orientados a datos no se


actualicen permanentemente, salvo que todas las operaciones de la unidad
transaccional se completen de forma satisfactoria.

3 TRANSACCIONES EXPLÍCITAS E IMPLÍCITAS

Los programadores de aplicaciones de transacciones pueden sacar partido de


los dos modelos de programación que proporciona el espacio de nombres
System.Transactions para crear una transacción. Puede utilizar el modelo de
programación explícito mediante la claseTransaction o el modelo de
programación implícito en el que la infraestructura administra de forma
automática las transacciones por medio de la clase TransactionScope.

Ambos modelos admiten la confirmación de una transacción cuando el programa


alcanza un estado coherente. Si la confirmación se ejecuta correctamente, la
transacción se confirma de forma duradera. Si la confirmación no se realiza
correctamente, ésta se anula. Si el programa de aplicación no puede realizar
correctamente la transacción, intenta anular y deshacer los efectos de la
transacción.

3.1 Implementar una transacción con CommittableTransaction

La clase Committable Transaction proporciona un modo explícito de que las


aplicaciones utilicen una transacción.

Es útil para las aplicaciones que desean utilizar la misma transacción en varias
llamadas a funciones o varias llamadas a subprocesos. A diferencia de lo que
sucede con la clase TransactionScope, quien escribe las aplicaciones tiene que
llamar de forma específica a los métodos Commit y RollBack para confirmar o
anular la transacción. Cuando se implementa una transacción, se debe llamar
al método BeginTransaction dentro del objeto de conexión. Al crear la
transacción, puede especificar el nivel de aislamiento que se aplica a la
transacción.

El nivel de aislamiento de una transacción determina qué nivel de acceso


tienen otras transacciones a los datos variables antes de que finalice una
transacción. Si va especificar el nivel de aislamiento, pasar un valor
enumerable de System.Data.IsolationLevel dentro del método
BeginTransaction. Los valores numerables del IsolationLevel:

CIBERTEC CARRERAS PROFESIONALES


64

Método Descripción

Los cambios pendientes de las transacciones más aisladas no


Chaos
se pueden sobrescribir.

Los datos variables no se pueden leer durante la transacción,


ReadCommitted
pero se pueden modificar.

Se pueden leer datos variables y modificarse durante la


ReadUncommitted
transacción.

Se pueden leer datos variables pero no modificarse y no se


Serializable
pueden agregar nuevos datos durante la transacción.

Antes de que una transacción modifique los datos, comprueba


si otra transacción ha cambiado los datos después de
haberlos leído inicialmente. Si se han actualizado los datos, se
produce un error. Esto permite a una transacción llegar al
valor previamente confirmado de los datos.
Snapshot
Cuando intenta promocionar una transacción que se ha
creado con este nivel de aislamiento, se produce una
excepción InvalidOperationException con el mensaje de
error "No se pueden promocionar transacciones con el nivel
de aislamiento Snapshot".

3.2 Actualizar una base de datos dentro de una transacción local

En el siguiente ejemplo, actualizaremos el stock y el precio de un


determinado artículo.
 Declarar el objeto SqlConnection

Dim cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=BDFactura; integrated security=true")

 Abra el objeto Conection; cree el objeto transaction y asignarle al


Transaction BeginTransaction del objeto Connection con el nivel de
Isolation Serializable.
Dim success As Boolean = True
cn.Open()
Dim tr As SqlTransaction
tr = cn.BeginTransaction(IsolationLevel.Serializable)

 Para cada comando que se va a ejecutar dentro de la transacción, asignar


la propiedad Transaction para referir al objeto transacción.
Using cmd As New SqlCommand("Update dbo.Articulos Set
art_precio = art_precio + 15 Where art_codigo='a0002'", cn,tr)
Dim i As Integer = cmd.ExecuteNonQuery
If i > 0 Then
Using cmd1 As New SqlCommand("Update dbo.Articulos Set
art_stock += 15 Where art_codigo='a0002'", cn, tr)
i = cmd1.ExecuteNonQuery
If i > 0 Then success = True
End Using 'Libera el Command que actualiza el Stock
End If
End Using 'Libera el Command que actualiza el precio

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 65

 Si los comandos se ejecutaron con éxito, es decir, la variable success es


true, llamar al método Commit del objeto Transaction; si hubo un problema,
llamar al método RollBack para cancelar las actualizaciones.
If success = True Then
tr.Commit()
Else
tr.Rollback()
End If

 Los objetos command se liberarán dentro del Using, luego cerrar la


conexión.

cn.Close()

4 MANEJO DE TRANSACCIONES EN LA CAPA DE DATOS


Se puede manejar transacciones en la capa de datos (Data Tier) utilizando
sentencias SQL, dentro de un procedimiento almacenado y triggers o
disparadores, al iniciar una transacción, al comitear la transacción y al deshacer
los cambios (rollback) en la transacción.

La siguiente tabla muestra algunas de las sentencias SQL que se utilizan para
manejar transacciones dentro de la capa de datos

Sentencia SQL Descripción

BEGIN Marca el inicio de una transacción local.


TRANSACTION

Marcar el fin de una transacción completada con éxito, y


COMMIT
comitea o actualiza los cambios efectuados después del
TRANSACTION
BEGIN TRANSACTION.

Marca el fin de una transacción no completada con éxito, y


ROLLBACK
cancela todos los cambios efectuados después del BEGIN
TRANSACTION
TRANSACTION.

4.1 Manejo de una transacción explícita en la capa de datos

 Crear un procedimiento almacenado


 En el procedimiento almacenado, iniciar una transacción (BEGIN
TRANSACTION).
 Colocar las sentencias de actualización dentro de la transacción.
 Si todas las operaciones se ejecutaron correctamente, comitear la
transacción, pero si la operación falló, deshacer los cambios a la
transacción.

El siguiente ejemplo muestra cómo manejar una transacción en un


procedimiento almacenado. El procedimiento almacenado crea una
transaccione y ejecuta dos sentencias de actualización dentro de la

CIBERTEC CARRERAS PROFESIONALES


66

transacción. Si se ejecutó satisfactoriamente se aplicará Commit, si hubo al


error se aplicará RollBack.

CREATE PROCEDURE dbo.UpdatePrecios


@codprod1 char(5),
@codprod2 char(5) Inicia la transacción donde
As las actualizaciones se
DECLARE @success BIT agrupan a partir de aquí
Select @success=0

BEGIN TRANSACTION
Update dbo.Articulos Set art_precio=art_precio * 1.5
Where art_codigo=@codprod1
if(@@error=0 AND @@rowcount=1)
Begin
Update dbo.Articulos Set art_precio=art_precio * 2.0
Where art_codigo=@codprod2

if(@@error=0 AND @@rowcount=1)


Select @success=1 Sentencia de actualización
End de precios por un artículo
If @success=1
COMMIT TRANSACTION
Else
ROLLBACK TRANSACTION Si los procesos se
Return ejecutan
satisfactoriamente, se
aplicará COMMIT, sino se
aplicara ROLLBACK

5 MANEJO DE TRANSACCIONES DISTRIBUIDAS

Las transacciones distribuidas permiten incorporar en una sola acción de


cumplimiento o incumplimiento varias operaciones distintas que tienen lugar en
sistemas diferentes.
La clase System.Transactions.TransactionScope proporciona una manera
sencilla de marcar un bloque de código como participante en una transacción, sin
que el usuario tenga que interactuar con la transacción.

Un ámbito de transacción puede seleccionar y administrar la transacción de


ambiente de forma automática. Gracias a su fácil uso y a su eficacia, se
recomienda utilizar la clase TransactionScope cuando se desarrolle una
aplicación de transacción.
Además, no es necesario inscribir recursos de forma explícita con la transacción.
Cualquier administrador de recursos de System.Transactions (como SQL
Server 2005) puede detectar la existencia de una transacción de ambiente
creada por el ámbito e inscribirla de forma automática.
Crear un ámbito de transacción, utilizando TransactionScope.

Using scope As TransactionScope = New TransactionScope()


...

End Using

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 67

La clase TransactionScope proporciona varios constructores sobrecargados que


aceptan una enumeración del tipo TransactionScopeOption, que define el
comportamiento transaccional del ámbito. Un objeto TransactionScope tiene tres
opciones:

Opción Descripción

Hay presente una transacción de ambiente. El ambiente se une a


Required esa transacción. Si no existe ninguna transacción, el ambiente
crea una nueva. Es el valor por defecto.

RequiresNew La transacción siempre crea una nueva transacción.

Nunca participa en una transacción, independientemente si hay


Supress una de éstas presente. Por lo tanto, no existirá ninguna
transacción.

5.1 Completar un ámbito de transacción


Cuando la aplicación finalice, todo el trabajo que desea llevar a cabo en una
transacción se debe llamar al método Complete sólo una vez para informar al
administrador de transacciones que se puede confirmar la transacción. Es muy
conveniente realizar la llamada a Complete como última instrucción en el
bloque using; si no se llama a este método, la transacción se anula, ya que el
administrador de transacciones lo interpreta como un error del sistema o como
una excepción iniciada dentro del ámbito de transacción.

La instrucción using garantiza que se llame al método Dispose del objeto


TransactionScope aunque se produzca una excepción. El método Dispose
marca el final del ámbito de transacción. Puede que las excepciones que tienen
lugar después de llamar a ese método no afecten a la transacción. Este
método, también, restaura la transacción de ambiente a su estado anterior.

5.2 Deshacer una transacción


Si desea deshacer una transacción, no debe llamar al método Complete dentro
del ámbito de transacción. Por ejemplo, puede iniciar una excepción en el
ámbito. La transacción en la que éste participa se deshará.

En el ejemplo siguiente, se muestra un objeto TransactionScope que crea


tres objetos de ámbito anidados, cada uno con una instancia con un valor
de TransactionScopeOption distinto.

Using scope1 As New TransactionScope()


'Default is Required
Using scope2 As New TransactionScope( _
TransactionScopeOption.Required)
'.....
End Using

Using scope3 As New TransactionScope( _


TransactionScopeOption.RequiresNew)
'...
End Using

End Using

CIBERTEC CARRERAS PROFESIONALES


68

LABORATORIO 4.1
ACTUALIZACIÓN DE DATOS UTILIZANDO PROCEDIMIENTOS
ALMACENADOS.
En este escenario, vamos a realizar la actualización de los datos de los empleados,
incluyendo la foto del empleado, utilizando procedimientos almacenados de tipo
INSERT, UPDATE y DELETE, ejecutando los procedures con el objeto COMMAND.

1. En la Base de datos DBVentas, defina cada uno de los procedimientos


almacenados para realizar el proceso de inserción, actualización, eliminación y listado
de los empleados, tal como se muestra a continuación.
Create Procedure usp_insertar
@id char(5),
@nombre varchar(50),
@ape varchar(50),
@dni varchar(8),
@foto image
As
Insert tb_empleados Values(@id,@nombre,@ape,@dni,@foto)
--------------------------------------
Create Procedure usp_modificar
@id char(5),
@nombre varchar(50),
@ape varchar(50),
@dni varchar(8),
@foto image
As
Update tb_empleados
Set nomempleado=@nombre,apeempleado=@ape,dniempleado=@dni,
foto=@foto Where idempleado=@id
--------------------------------------
Create Procedure usp_eliminar
@id char(5)
As
Delete From tb_empleados Where idempleado=@id
--------------------------------------
Create Procedure usp_listado
As
select * from tb_empleados

2. Diseña el Formulario, incluya el control image para mostrar la foto del empleado.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 69

Lista de controle del Formulario.

Control Name Propiedad Valor


Label Label1 Text Codigo
Label Label2 Text Apellidos
Label Label3 Text Nombres
Label Label4 Text DNI
Button BtnExaminar Text Examinar
Button BtnNuevo Text Nuevo
Button BtnGrabar Text Grabar
Button btnActualizar Text Actualizar
PictureBox PictureBox1
TextBox Txtcodigo
TextBox TxtApellido
TextBox txtNombres
TextBox TxtDNI

3. Defina el Namespace: System.Data.SqlClient


Defina el NameSpace: System.IO

4. Definir e inicializar la cadena de conexión a nivel Class Form.


Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=DBVentas; integrated security=true")

5. Defina la función Empleados en la ventana de código del Formulario que ejecute el


procedure usp_listado donde retorna los empleados.

Function Empleados()
Dim da As New SqlDataAdapter("usp_listado", cn)
Dim tabla As New DataTable
da.Fill(tabla)
Return tabla
End Function

6. En el evento Load del Form, llenar los datos en DGArticulos

Me.DataGridView1.DataSource = Empleados()

7. Programa el evento Click del boton Examinar que permita buscar la foto del
empleado utilizando el objeto OpenFileDialog.

'BUSCAR LA IMAGEN QUE SE VISUALIZA EN EL PICTUREBOX


Dim BUSCAR As New OpenFileDialog
BUSCAR.Filter = "Archivo de Imagen|*.bmp"
'SI PRESIONASTE EL BOTON OK
If BUSCAR.ShowDialog = Windows.Forms.DialogResult.OK Then
Me.PictureBox1.Image = Image.FromFile(BUSCAR.FileName)
End If

CIBERTEC CARRERAS PROFESIONALES


70

8. Programa el evento Click del botón Agregar que permite insertar un registro a la
tabla tb_empleados. Ejecute el procedimiento almacenado usp_insertar.

Dim Ms As New MemoryStream


Me.PictureBox1.Image.Save(Ms, Imaging.ImageFormat.Bmp)
Dim DATA() As Byte = Ms.ToArray

'PROCESO DE INSERCION
Dim CMD As New SqlCommand("usp_insertar", cn)
CMD.CommandType = CommandType.StoredProcedure
'PASO DE PARAMETROS
With CMD.Parameters
.Add("@id", SqlDbType.Char, 5).Value = txtcodigo.Text
.Add("@nombre", SqlDbType.VarChar, 50).Value = txtnombre.Text
.Add("@ape", SqlDbType.VarChar, 50).Value = txtapellido.Text
.Add("@dni", SqlDbType.VarChar, 10).Value = txtdni.Text
.Add("@foto", SqlDbType.Image).Value = DATA
End With
cn.Open()
Try 'EJECUTAR EL PROCESO
Dim i As Integer = CMD.ExecuteNonQuery
MessageBox.Show(i.ToString & " Registro Agregado")
Me.DataGridView1.DataSource = Empleados()
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
cn.Close() 'CERRAR LA CONEXION
End Try

9. Programa el evento Click en el botón Actualizar que permita actualizar los datos
de un empleado por su código. Ejecute el procedimiento almacenado usp_modificar.

Dim Ms As New MemoryStream


Me.PictureBox1.Image.Save(Ms, Imaging.ImageFormat.Bmp)
Dim DATA() As Byte = Ms.ToArray

'PROCESO DE ACTUALIZACION
Dim CMD As New SqlCommand("usp_modificar", cn)
CMD.CommandType = CommandType.StoredProcedure
'PASO DE PARAMETROS
With CMD.Parameters
.Add("@id", SqlDbType.Char, 5).Value = txtcodigo.Text
.Add("@nombre", SqlDbType.VarChar, 50).Value = txtnombre.Text
.Add("@ape", SqlDbType.VarChar, 50).Value = txtapellido.Text
.Add("@dni", SqlDbType.VarChar, 10).Value = txtdni.Text
.Add("@foto", SqlDbType.Image).Value = DATA
End With
cn.Open()
Try 'EJECUTAR EL PROCESO
Dim i As Integer = CMD.ExecuteNonQuery
MessageBox.Show(i.ToString & " Registro Actualizado")
Me.DataGridView1.DataSource = Empleados()
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
cn.Close() 'CERRAR LA CONEXION
End Try

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 71

10. Programa el evento Click en el botón Eliminar que permita eliminar un empleado
por su código. Ejecute el procedimiento almacenado usp_eliminar.
'PROCESO DE ELIMINACION
Dim CMD As New SqlCommand("usp_eliminar", cn)
CMD.CommandType = CommandType.StoredProcedure
'PASO DE PARAMETROS
CMD.Parameters.Add("@id",SqlDbType.Char).Value = txtcodigo.Text
cn.Open()
Try 'EJECUTAR EL PROCESO
Dim i As Integer = CMD.ExecuteNonQuery
MessageBox.Show(i.ToString & " Registro Eliminado")
Me.DataGridView1.DataSource = Empleados()
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
cn.Close() 'CERRAR LA CONEXION
End Try

11. Programa el evento CellClick del DataGridView1, donde al seleccionar un registro,


visualizamos los datos en los controles.

With DataGridView1.CurrentRow
txtcodigo.Text = .Cells(0).Value
txtapellido.Text = .Cells(1).Value
txtnombre.Text = .Cells(2).Value
txtdni.Text = .Cells(3).Value
'ALMACENAR LA CELDA DE LA IMAGEN EN UN ARRAY
Dim data() As Byte = .Cells(4).Value
'GUARDAR EL ARRAY DE BYTES EN EL MEMORY
Dim Ms As New MemoryStream
Ms.Write(data, 0, data.Length)
'VISUALIZAR LA IMAGEN EN EL PICTUREBOX
PictureBox1.Image = Image.FromStream(Ms)
End With

12. Guarda la aplicación y ejecutar.

CIBERTEC CARRERAS PROFESIONALES


72

LABORATORIO 4.3
ACTUALIZACIÓN DE DATOS UTILIZANDO UN TABLEADAPTER
En este escenario, vamos a realizar el proceso de actualización de los datos de los
vendedores utilizando un TableAdapter. Para ello vamos a crear dos procedures:
INSERT y UPDATE dentro del TableAdapter para efectuar dichos procesos. A
continuación, desarrolle los siguientes pasos.

1. En el DataSet DsFacturas, agregue un


TableAdapter llamado Vendedor, tal como se
muestra en la figura.

2. Para agregar los métodos INSERT y UPDATE,


haga click derecho en el TableAdapter y
seleccione la opción Add Query tal como se
muestra en la figura.

3. En la página Choose
Command Type seleccione la
opción create new stored
procedure, presione el botón
Next.

4. En la página Choose a Query


Type, seleccione el tipo de
consulta; en este caso
seleccionamos la opción
INSERT. Presione el botón
Next.

5. En la página Generate the


Stored Procedure el
Asistente ha definido la
sentencia del INSERT y
además mostrará los datos
actualizados: SELECT, tal
como se muestra en la figura.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 73

6. En la página Create the Stored


Procedure asigne un nombre al
Procedure: InsertVendedor, presione
el boto Next.

7. En la página Choose Function Name


confirme el mismo nombre. Presione el
botón Finish.

8. En el TableAdapter de vendedor, se
visualiza el método InsertVendedor a
continuación, Ud., desarrollará el
método UpdateVendedor que
permitirá actualizar los datos de los
vendedores por su código.

Método InsertVendedor

Método InsertVendedor

9. Agregue un formulario dos botones y cambie los valores de las propiedades:

Control Propiedad Valor


Label1 Text Codigo
Label2 Text Nombre
Label3 Text Fono
Label4 Text Direccion
Button1 Text Limpiar
Button2 Text Añadir
Button3 Text Modificar

CIBERTEC CARRERAS PROFESIONALES


74

10. Defina a nivel Class Form, el DataSet DsFactura y su TableAdapter:


Ven_TableAdapter.

Private Ds As New DsFactura


Dim Ven_TableAdapter As New _
FacturaTableAdapters.VendedorTableAdapter

11. Dentro del evento Form3_Load, coloque lo siguiente:

Ven_TableAdapter.Fill(Ds.Vendedor)
Me.DataGridView1.DataSource = Ds.Vendedor

12. En el evento btnAñadir_Click, permitirá agregar un registro de vendedor, Coloque


lo siguiente:
a. Ejecutar el método InsertVendedor enviando sus parámetros.
b. Ejecutar el método Fill, para actualizar el DataTable vendedor.
c. Mostrar los datos en el DataGridView1.

Ven_TableAdapter.InsertVendedor(Me.TXTCODIGO.Text, _
Me.TXTNOMBRE.Text, Me.TXTFONO.Text, Me.TXTDIRECCION.Text)

Ven_TableAdapter.Fill(Ds.Vendedor)
Me.DataGridView1.DataSource = Ds.Vendedor

13. En el evento btnModificar_Click, permitirá modificar los datos de un vendedor.


Coloque lo siguiente:

Dim i As Integer
i = Ven_TableAdapter.UpdateVendedor(Me.TXTNOMBRE.Text, _
Me.TXTFONO.Text, Me.TXTDIRECCION.Text, TXTCODIGO.Text)
Ven_TableAdapter.Fill(Ds.Vendedor)
Me.DataGridView1.DataSource = Ds.Vendedor

14. Guarde el proyecto, ejecute la aplicación y compruebe el estado del servicio.

LABORATORIO 4.4
USO DE TRANSACCIONES LOCALES
En este escenario realizaremos el proceso de actualización de los clientes registrados
en la base de datos BDFactura utilizando transacciones (transacciones explícitas).
1. Ingrese a Visual Studio 2005.
2. Seleccione en el menú Files -> New ->Project…
3. Elija las siguientes opciones de la ventana para crear un nuevo proyecto.
a. En “Project Types” elija “Visual Basic”.
b. En “Templates” elija “WindowsApplication”.
c. En “name” coloque “appFacturacion03.
d. En “Location” coloque “C:\CursoPOOII”.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 75

4. Diseñe la siguiente interface:

Objeto Name Propiedad Valor


Label1 Label1 Text Codigo
Label2 Label2 Text Nombre
Label3 Label3 Text Direccion
Label4 Label4 Text Fono
Label5 Label5 Text Ruc
Textbox1 Txtcodigo Text
Textbox2 Txtnombre Text
Textbox3 Txtdireccion Text
Textbox4 Txtfono Text
Textbox5 Txtruc Text
Button1 BtnLimpiar Text Limpiar
Button2 BtnGrabar Text Grabar
Button3 BtnBuscar Text Buscar
Button4 BtnModificar Text Modificar
Button5 BtnEliminar Text Eliminar
DataGridView1 DGCliente

5. Defina los namespaces: System.Data.SqlClient y System.Transaction.

6. Defina e inicializar la cadena de conexión a nivel Class Form.

Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=BDFactura; integrated security=true")

7. Defina la función DataClientes que retorne los registros de los clientes.

Function DataClientes() As DataTable


Dim da As New SqlDataAdapter("Select * from Clientes", cn)
Dim t As New DataTable
da.Fill(t)
Return t
End Function

8. En el evento Load del Form, cargamos los registros de los clientes en el


DataGridView DGClientes y configuramos el DataGridView para que no se
pueda añadir registros.
Indica no se
Me.DGCliente.AllowUserToAddRows = False puede añadir
Me.DGCliente.DataSource = DataClientes() registros

CIBERTEC CARRERAS PROFESIONALES


76

9. Para navegar por los registros del DataGridView DGCliente y al seleccionar


un registro se visualice en los Textboxes, se deberá programar en el evento
CellClick.
With DGCliente.CurrentRow CurrentRow representa la
txtcodigo.Text = .Cells(0).Value fila actual
txtnombre.Text = .Cells(1).Value
txtfono.Text = .Cells(2).Value
txtruc.Text = .Cells(3).Value CurrentRow se obtiene el
txtdireccion.Text = .Cells(4).Value
valor de las columnas, el
End With
valor de la primera
columna:
CurrentRow.Cells(0).Value

10. En el evento Click del botón Limpiar, limpie los controles del Form.
Me.txtcodigo.Text = ""
Me.txtnombre.Text = ""
Me.txtdireccion.Text = ""
Me.txtfono.Text = ""
Me.txtruc.Text = ""
Me.txtcodigo.Focus()

11. En el evento Click del botón Guarde, ingresará un nuevo cliente:


a. Abrir la conexión.
b. Crear una transacción, cuyo nivel de aislamiento es serializable.
c. Dentro del Try crear un SqlCommand, añadir los parámetros.
d. Ejecutar el comando con el método ExecuteNonQuery.
e. Si se procesó correctamente, se ejecutará el método Commit.
f. Si el proceso tuvo un error, se desencadena el Catch y se ejecutará el
método RollBack de la transacción tr.
g. Al finalizar el proceso, se cerrará la conexión.
cn.Open()
Using tr As SqlTransaction = _
cn.BeginTransaction(Data.IsolationLevel.Serializable)
Try
Dim cmd As New SqlCommand( "Insert Into Clientes
Values(@cod, @nom, @dir, @fono, @ruc)", cn, tr)
cmd.Parameters.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
cmd.Parameters.Add("@nom", SqlDbType.VarChar).Value = txtnombre.Text
cmd.Parameters.Add("@dir", SqlDbType.VarChar).Value = txtdir.Text
cmd.Parameters.Add("@fono", SqlDbType.VarChar).Value = txtfono.Text
cmd.Parameters.Add("@ruc", SqlDbType.VarChar).Value = txtruc.Text
cmd.ExecuteNonQuery()
tr.Commit()
Me.DGCliente.DataSource = DataClientes()
Catch ex As SqlException
MessageBox.Show(ex.Message)
tr.Rollback()
Finally
cn.Close()
End Try
End Using

12. En botón modificar, ejecuta el proceso de actualización del cliente:


a. Crear una transacción, cuyo nivel de aislamiento es serializable.
b. Dentro del Try crear un SqlCommand, añadir los parámetros.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 77

c. Ejecutar el comando con el método ExecuteNonQuery, este método


retorna el número de registros afectados donde es almacenado en c.
d. Si el valor de c es 1, ejecutar el método Commit, caso contrario se
aplicará el método RollBack de la transacción tr.
cn.Open()
Using tr As SqlTransaction = _
cn.BeginTransaction(Data.IsolationLevel.Serializable)
Try
Dim cmd As New SqlCommand("Update dbo.Clientes Set
cli_nombre=@nom, cli_direccion=@dir, cli_telefono=@fono,
cli_ruc=@ruc Where cli_codigo=@cod", cn, tr)
cmd.Parameters.Add("@nom", SqlDbType.VarChar).Value=txtnombre.Text
cmd.Parameters.Add("@dir", SqlDbType.VarChar).Value=txtdir.Text
cmd.Parameters.Add("@fono", SqlDbType.VarChar).Value=txtfono.Text
cmd.Parameters.Add("@ruc", SqlDbType.VarChar).Value = txtruc.Text
cmd.Parameters.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
Dim c As Int16 = cmd.ExecuteNonQuery()
If c = 1 Then
tr.Commit()
DGCliente.DataSource = DataClientes()
Else
tr.Rollback()
MessageBox.Show("No se Actualizado")
End If
Catch ex As SqlException
MessageBox.Show(ex.Message)
tr.Rollback()
Finally
cn.Close()
End Try
End Using

13. En el botón eliminar, se borrará un cliente; en el evento Click del botón


eliminar, se ejecutará el proceso de eliminación del cliente:
a. Abrir la conexión.
b. Dentro del Try crear un SqlCommand, añadir los parámetros.
c. Ejecuta el comando con el método ExecuteNonQuery.
d. Si c es 1, aplicar Commit; sino aplicar RollBack.
e. Al finalizar el proceso, cerrar la conexión.
cn.Open()
Using tr As SqlTransaction = _
cn.BeginTransaction(Data.IsolationLevel.Serializable)
Try
Dim cmd As New SqlCommand( _
"Delete From dbo.Clientes Where cli_codigo=@cod", cn, tr)
With cmd.Parameters
.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
End With
Dim c As Int16 = cmd.ExecuteNonQuery()
If c = 1 Then
tr.Commit()
MessageBox.Show("Cliente Eliminado")
Me.DGCliente.DataSource = DataClientes()
Else
tr.Rollback()
MessageBox.Show("No se Elimino")
End If

CIBERTEC CARRERAS PROFESIONALES


78

. . .
Catch ex As SqlException
MessageBox.Show(ex.Message)
tr.Rollback()
Finally
cn.Close()
End Try
End Using

14. Ejecutar la aplicación y verificar los resultados.

¿Cómo desarrollaría el proceso de búsqueda de un cliente? Aplique sus


ideas dentro del ejercicio.

LABORATORIO 4.4
TRANSACCIONES DISTRIBUIDAS, TRANSACTIONSCOPE
En este escenario, se aplicará un caso donde se trabajará con dos base de datos:
BDFactura y BDAlmacen. En ellas, se actualizarán los datos sobre dos tablas:
artículos en BDFactura y kardex en BDAlmacen:
• Cuando se agregue un nuevo artículo, éste se agregará en el kardex.
• Cuando se actualice el stock de artículos, se actualizará el stock en el kardex.
La estructura de las tablas es la siguiente:
DATABASE BDFACTURA
CREATE TABLE ARTICULOS(
art_codigo char(5) primary key,
art_nombre varchar(30),
art_unidad char(4),
art_precio Decimal,
art_stock int)
DATABASE BDALMACEN
CREATE TABLE KARDEX(
kar_codigo char(5) primary key,
har_nombre varchar(30),
kar_unidad char(4),
kar_stock int)

1. Agregue un formulario al proyecto.


2. Diseñe la siguiente interface.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 79

Objeto Name Propiedad Valor


Textbox1 Txtcodigo Text
Textbox2 Txtdescripcion Text
Textbox3 Txtunidad Text
Textbox4 Txtprecio Text
Textbox5 Txtstock Text
Button1 BtnLimpiar Text Limpiar
Button2 BtnGrabar Text Grabar
Button3 BtnActualizar Text Actualizar
DataGridView1 DGArticulos

3. Definir los Namespaces: System.Data.SqlClient y System.Transaction.


4. Definir e inicializar la cadena de conexión a nivel Class Form.
Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=BDFactura; integrated security=true")

5. Definir la función DataArticulos que retorne los artículos.

Function DataArticulos() As DataTable


Dim da As New SqlDataAdapter("Select * from Articulos", cn)
Dim t As New DataTable
da.Fill(t)
Return t
End Function

6. En el evento Load del Form, llenar los datos en DGArticulos

Me.DGArticulos.DataSource = DataArticulos()

7. Programa el evento CellClick del DataGridView DGArticulos donde al


seleccionar un registro se visualice en los Textboxes.
8. En botón Guardar, registrar un nuevo artículo en la tabla artículos y registrar el
artículo en el kardex:
a. Abrir la conexión y crear una conexión para BDAlmacen.
b. Crear un transacción Scope de tipo Required.
c. Establecer la estructura Try … Catch … Finally.
d. Ejecutar el comando con el método ExecuteNonQuery.
e. En el Command, definir la sentencia de inserción al kardex.
f. Ejecutará el método Complete de la transacción.
g. Si el proceso tuvo un error, se desencadena el Catch.
h. Al finalizar el proceso, se cerrarán las conexiones.

cn.Open()
cnk.Open()
Using tr As New TransactionScope(TransactionScopeOption.Required)
Try
Dim cmd As New SqlCommand("Insert Articulos(art_codigo,
art_nombre,art_unidad,art_precio,art_stock)
Values(@cod, @nom, @uni, @pre, @st)", cn)
With cmd.Parameters
.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
.Add("@nom", SqlDbType.VarChar).Value = txtdescripcion.Text
.Add("@uni", SqlDbType.VarChar).Value = txtunidad.Text
.Add("@pre", SqlDbType.Decimal).Value = Val(txtprecio.Text)
.Add("@st", SqlDbType.Int).Value = Val(txtstock.Text)
End With
......

CIBERTEC CARRERAS PROFESIONALES


80

......
cmd.ExecuteNonQuery()
cmd = New SqlCommand("Insert Kardex(kar_codigo,har_nombre,
kar_unidad,kar_stock) Values(@cod, @nom, @uni,@st)", cnk)
With cmd.Parameters
.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
.Add("@nom", SqlDbType.VarChar).Value = txtdescripcion.Text
.Add("@uni", SqlDbType.VarChar).Value = txtunidad.Text
.Add("@st", SqlDbType.Int).Value = Val(txtstock.Text)
End With
cmd.ExecuteNonQuery()
tr.Complete()
MessageBox.Show("Articulo Agregado")
Me.DGArticulos.DataSource = DataArticulos()
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
cn.Close() : cnk.Close()
End Try
End Using

9. En botón actualizar, actualizar el stock en artículo y en kardex:


a. Abrir la conexión y crear una conexión para BDAlmacen.
b. Crear un transacción Scope de tipo Required.
c. Establecer la estructura Try … Catch … Finally.
d. Dentro del Try, definir un Command que inserta los artículos.
e. Ejecutar el comando con el método ExecuteNonQuery.
f. En el Command, definir la sentencia de inserción al kardex.
g. Ejecutará el método Complete de la transacción.
h. Si el proceso tuvo un error, se desencadena el Catch.
i. Al finalizar el proceso, se cerrarán las conexiones.
cn.Open()
cnk.Open()
Using tr As New TransactionScope()
Try
Dim cmd As New SqlCommand("Update dbo.Articulos Set
art_stock = @st Where art_codigo=@cod", cn)
cmd.Parameters.Add("@st", SqlDbType.Int).Value= Val(txtstock.Text)
cmd.Parameters.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
cmd.ExecuteNonQuery()

cmd = New SqlCommand("Update dbo.Kardex Set


kar_stock = @st Where kar_codigo=@cod", cnk)
cmd.Parameters.Add("@st", SqlDbType.Int).Value= Val(txtstock.Text)
cmd.Parameters.Add("@cod", SqlDbType.Char).Value = txtcodigo.Text
cmd.ExecuteNonQuery()

tr.Complete()
Me.DGArticulos.DataSource = DataArticulos()
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
cn.Close()
cnk.Close()
End Try
End Using

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 81

Autoevaluación
1. ¿Cuál es la diferencia entre una transacción local y una transacción distribuida?
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

2. Defina los niveles de aislamiento (isolation level) de una transacción.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

3. ¿Qué es una transacción distribuida? Explique acerca de TransactionScope


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

4. Explique brevemente cada uno de los valores de TransactoinScopeOption.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
____________________________________

5. Desarrollo práctico: Implemente un programa donde realice la


actualización de vendedores dentro de la base de datos BDFactura, y en
dicho proceso aplicar las transacciones locales.

CIBERTEC CARRERAS PROFESIONALES


82

Resumen
 Las transacciones locales son útiles para las aplicaciones que desean utilizar la
misma transacción en varias llamadas a funciones o a subprocesos. Tiene que
llamar de forma específica a los métodos Commit y RollBack para confirmar o
anular la transacción.

 Las transacciones locales utilizan niveles de aislamiento o Isolation Level:


ReadCommitted, ReadUnCommitted, Serializable, Chaos al momento de actualizar
los datos.

 En la capa de datos, también, se maneja transacciones donde se utilizan las


siguientes sentencias:

o BEGIN TRANSACTION
o COMMIT TRANSACTION
o ROLLBACK TRANSACTION

 Las transacciones distribuidas están definidas en el .NET FrameWork 2.0 con la


clase TransactionScope.

 La clase TransactionScope define un conjunto de valores según el tipo de


transacción a realizar:

o Required: crea una transacción, si ya existe se agrega.


o RequiresNew: siempre crea una nueva transacción.
o Suppress: suprime una transacción, donde las sentencias se ejecutan
sin transacciones.

 Al crear una transacción: TransactionScope se utiliza la sentencia Using y para


actualizar los procesos se utiliza el método Complete.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://msdn2.microsoft.com/es-es/library/z80z94hz(VS.80).aspx
Página que referencia el manejo de transacciones

 http://msdn2.microsoft.com/es-es/library/ms172152(VS.80).aspx
Página que maneja la implementación de transacciones

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 83

UNIDAD DE
APRENDIZAJE

2
SEMANA

OPERACIONES DE SCONECTADAS A UN ORIGEN


DE DATOS

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que accedan a
un origen de datos en forma desconectada utilizando los objetos del ADO.NET para
obtener una mejor performance en los procesos de consulta y actualización de una
aplicación.

TEMARIO

• Creación y definición DataSet, DataTable, Constraint y DataView.


• Proceso de consulta y actualización de datos desconectados en un DataSet.
• Operaciones desconectadas utilizando el Asistente del Visual Studio.
• Operaciones de consultas utilizando el DataView.
• Manejo de un DataTableReader desde un DataSet o DataTable.

ACTIVIDADES PROPUESTAS

• Los alumnos reconocen el modelo desconectados de ADO.NET.


• Los alumnos manejan los objetos desconectados de datos.
• Los alumnos realizan operaciones de actualización en un DataSet.

CIBERTEC CARRERAS PROFESIONALES


84

1 ARQUITECTURA DE ADO .NET

El procesamiento de datos ha dependido, principalmente, de un modelo basado


en una conexión. A medida que el procesamiento de datos utiliza cada vez más
arquitecturas de varios niveles, los programadores están pasando a un enfoque
sin conexión. Existen dos componentes de ADO.NET que se pueden utilizar
para obtener acceso a datos:
• Proveedores de datos de .NET Framework: permite manipular los datos y
acceso de sólo lectura.
• DataSet: permite el acceso a datos independientemente del origen de datos.
En este capítulo estudiaremos al DataSet y su Modelo.

2 DATASET

El DataSet es una representación de datos residente en memoria que


proporciona un modelo de programación relacional coherente con
independencia del origen de datos. Representa un conjunto completo de datos
que incluye tablas relacionadas y restricciones, así como relaciones entre las
tablas. En la siguiente ilustración, se muestra el modelo de objetos DataSet.

2.1 Creación de un DataSet


Al crear un DataSet se define una instancia de Dataset llamando a su
constructor. Si lo desea, especifique un nombre de argumento. Si no
especifica ninguno, se le asignará "NewDataSet".

Dim ds As New DataSet("DsFactura")

También puede crearse un nuevo DataSet basado en un DataSet


existente. El método Clone solo copia la estructura del DataSet original. El
método GetChanges solo copiará los datos modificados. Si ejecuta el
método Copy, copia el contenido del DataSet.

Dim ds As DataSet = ds.Clone()

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 85

2.2 Forma de añadir una tabla a DataSet


ADO .NET te habilita para crear objetos DataTables y añadirlos a un
DataSet existente. El siguiente ejemplo define un DataSet y se añade un
DataTable al DataSet.

Dim ds As New DataSet("DsFactura")


Dim tabla As New DataTable("Clientes")
ds.Tables.Add(tabla)

2.3 Forma de añadir columnas a una tabla


El esquema de una tabla está representado por columnas y constraints.
La definición de un esquema de un DataTable es a través de los objetos
DataColumn, como también de los objetos ForeignKeyConstraint y
UniqueConstraint.
Se crea un objeto DataColumn dentro de una DataTable utilizando un
constructor de DataColumn o llamando al método Add de la propiedad
Columns de una tabla. El método Add aceptará:
o ColumnName: nombre de la columna.
o DataType: tipo de dato de la columna.
o Expresión: argumento que crea una nueva columna.

En el siguiente ejemplo, se añade 4 columnas a la tabla Recibos.

Dim tabla As New DataTable("Recibos")


tabla.Columns.Add("numero", Type.GetType("System.String"))
tabla.Columns.Add("fecha", Type.GetType("System.DateTime"))
tabla.Columns.Add("detalle", Type.GetType("System.String"))
tabla.Columns.Add("monto", Type.GetType("System.Decimal")))

o también a través del DataColumn.

Dim tabla As New DataTable("Recibos")


Dim dc As New DataColumn("num", Type.GetType("System.String"))
tabla.Columns.Add(dc)
dc = New DataColumn("fecha", Type.GetType("System.DateTime"))
tabla.Columns.Add(dc)
dc = New DataColumn("detalle", Type.GetType("System.String"))
tabla.Columns.Add(dc)
dc = New DataColumn("monto", Type.GetType("System.Decimal"))
tabla.Columns.Add(dc)

2.4 Creación de expresiones


Puede definirse una expresión para una columna, habilitándolo para
contener un valor calculado desde otra columna en la misma fila o desde
valores de varias columnas de las filas en la tabla. El DataType debe ser el
apropiado para el valor de la expresión.

En el siguiente ejemplo, agregar la columna renta que representa el


10% del monto.
tabla.Columns.Add("monto", Type.GetType("System.Decimal"))
tabla.Columns.Add("monto", Type.GetType("System.Decimal"), _
monto*0.10")

CIBERTEC CARRERAS PROFESIONALES


86

o se puede generar a través del DataColumn.

dc = New DataColumn("monto", Type.GetType("System.Decimal"))


tabla.Columns.Add(dc)
dc = New DataColumn("monto", Type.GetType("System.Decimal"))
dc.Expression = "monto*0.10"
tabla.Columns.Add(dc)

2.5 Creación de columnas que generen autogeneren valores


Para asegurar que los valores sean únicos, puede colocar una columna
cuyos valores se incrementen automáticamente cuando se añade una
nueva columna. Para crear una columna Autoincrementada, colocar la
propiedad AutoIncrement a true. A continuación, se define las siguientes
propiedades:

Opción Descripción

AutoIncrementSeed Valor inicial del autogenerado

AutoIncrementStep Valor incremental

ReadOnly Indica que la columna será de solo lectura

En el siguiente ejemplo agregar la columna número, cuyo valor se


incrementará de 5 en 5, a partir del valor de 10.

Dc= New DataColumn("numero", Type.GetType("System.Int32"))


dc.AutoIncrement = True
dc.AutoIncrementSeed = 10
dc.AutoIncrementStep = 5
dc.ReadOnly = True
tabla.Columns.Add(dc)

2.6 Definición de una clave primaria para la tabla


Una tabla, por lo general, tiene una columna o un grupo de columnas que
identifica en forma única a cada fila dentro de la tabla. La identificación es
llamada Primary key. Cuando un dataColumn se identifica como
PrimaryKey para la tabla, la propiedad AllowDBNull es falsa, pero la
propiedad Unique no es colocada a true.
La propiedad PrimaryKey recibe los valores como un array de una o más
objetos DataColumns. El siguiente ejemplo permite definir un Primary Key
de una columna o un Primary Key de dos columnas.
tabla.PrimaryKey = New DataColumn() {tabla.Columns(0)}
'o
dc = tabla.Columns(0)
tabla.PrimaryKey = New DataColumn() {dc}

tabla.PrimaryKey = New DataColumn() {tabla.Columns(0),


tabla.Columns(1)}

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 87

2.6 Forma de añadir un Constraint a una tabla


Puede utilizar Constraint para establecer restricciones a los datos en un
DataTable y mantener la integridad de datos. Un Constraint es una regla,
aplicada a una columna que determina el curso de acción cuando el valor de
una fila es alterada. Existen dos tipos de constraint: ForeignKeyConstraint y
el UniqueConstraint.

2.6.1 ForeignKeyConstraint
Las propiedades DeleteRule y UpdateRule definen la acción a ser
tomada cuando el usuario actualiza o elimina una fila en la tabla
relacionada. Si una fila de la tabla principal es eliminada, también se
borrarán los registros de la tabla hija que tienen el mismo valor.
A continuación, se muestra las reglas para las propiedades de
UpdateRule y DeleteRule.

Rule Descripción

Cascade Elimina o actualiza las filas relacionadas.

SetNull Coloca el valor relacional a DBNull.

SetDefault Coloca el valor por defecto a las filas relacionales.

None Especifica que no se efectúa acción a las filas relacionales.

El objeto ForeignKeyConstraint es agregado a la colección Constraint


de la tabla relacionada a través del método Add.

El siguiente ejemplo establece un ForeignKey entre las tablas


clientes y factura, donde el valor DeleteRule es None.

Dim FKCliFact As New ForeignKeyConstraint("FK1", _


Cliente.Columns("cli_codigo"), Factura.Columns("cli_codigo"))
FKCliFact.DeleteRule = Rule.None

dataSet.Tables("Factura").Constraints.Add(FKCliFact)

2.6.2 UniqueConstraint
El objeto UniqueConstraint aplica la unicidad de los valores de las filas
de una tabla para una columna o un array de columnas. Se puede crear
un UniqueConstraint para una columna o array de columnas.
El objeto UniqueConstraint es agregado a la colección Constraint de
la tabla a través del método Add.
Podemos crear una constraint de tipo Unique asignando la propiedad
Unique a true.

El siguiente ejemplo permite crear UniqueConstraint a la


columna num.

Dim dc As New DataColumn("num", Type.GetType("System.Int32"))


dc.Unique = True

CIBERTEC CARRERAS PROFESIONALES


88

El siguiente ejemplo permite crear UniqueConstraint, a dos


columnas.

Dim uknumeros As New UniqueConstraint( _


New DataColumn() {ds.Tables("facturas").Columns(0), _
ds.Tables("facturas").Columns(1)})
ds.Tables("facturas").Constraints.Add(uknumeros)

2.7 FORMA DE AÑADIR RELACIONES ENTRE TABLAS


En un DataSet que contiene muchas tablas (DataTables), puede utilizar
objetos DataRelations donde, permita relacionar dos tablas, navegar entre los
registros de las dos tablas y retorne los registros de la tabla hija.
Para crear un DataRelation, se debe establecer como argumentos el campo
de la tabla padre y el campo de la tabla referencial o hija.
Añadiendo un DataRelation a un DataSet, por defecto se crea un Constraint
de tipo Unique en la tabla padre y otro constraint de tipo Foreign en la tabla
hija, para recuperar todas las filas de facturas de una fila de clientes
determinada mediante GetChildRows.

El siguiente ejemplo crea una relación de la tabla clientes y facturas


donde la primera columna será de la tabla padre (clientes) y la segunda
será de la tabla hija (facturas).

Dim relclifac As New DataRelation( _


"r1", ds.Tables("clientes").Columns(“cli_codigo”),
ds.Tables("facturas").Columns(“cli_codigo”))
ds.Relations.Add(relclifac)
For Each pRow In ds.Tables("Clientes").Rows
Console.WriteLine(pRow("cli_codigo").ToString())
For Each cRow In pRow.GetChildRows(relation)
Console.WriteLine(vbTab & cRow("fac_numero").ToString())
Next
Next

3 DATAADAPTER

El DataSet es un conjunto de datos que residen en memoria, el cual nos


proporciona un modelo relacional independiente del origen de datos.
Como el DataSet es independiente al origen de datos, para interactuar con los
orígenes de datos actuales se necesita del DataAdapter.
Un DataAdapter es usado para recuperar los datos desde un origen de datos y
publica tablas dentro de un DataSet. Los proveedores que incluye para el
DataAdapter son:
Proveedor Descripción

SqlDataAdapter Proveedor para SQL Server

OleDbDataAdapter Proveedor para OLE DB

OdbcDataAdapter Proveedor para ODBC

OracleDataAdapter Proveedor para Oracle

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 89

3.1 CONFIGURACIÓN DE UN DATAADAPTER


El DataAdapter tiene 4 propiedades que son utilizadas para recibir y actualizar
datos al origen de datos:

Propiedades Descripción

InsertCommand Comando para insertar filas en un almacén de datos.

UpdateCommand Comando para modificar filas en el almacén de datos.

DeleteCommand Comando para eliminar filas en el almacén de datos.

SelectCommand Comando para recuperar filas en el almacén de datos.

En el ejercicio ejecutamos una consulta (Select) en la tabla facturas y


procedemos a poblar los registros al DataSet utilizando el método Fill.

Dim da As New SqlDataAdapter("Select * from Facturas", cn)


Dim ds As New DataSet
da.Fill(ds, "facturas")

3.2 MÉTODO PARA POBLAR LOS DATOS DESDE UN


DATAADAPTER
El método Fill del DataAdapter es usado para poblar un DataSet con los
resultados del SelectCommand del DataAdapter. El Método Fill toma como
argumentos el nombre del DataSet para publicar los registros y el nombre del
objeto DataTable.

3.2.1 Llenar un DataSet desde múltiples DataAdapter


Se puede utilizar cualquier cantidad de objetos DataAdapter con un
DataSet. Cada DataAdapter se puede utilizar para llenar uno o varios
objetos DataTable y para reflejar en el origen de datos correspondiente
las actualizaciones que sean necesarias. Se pueden agregar, de forma
local, objetos DataRelation y Constraint al DataSet, de manera que se
pueden relacionar datos procedentes de varios orígenes distintos. Para
ocuparse de la comunicación con cada origen de datos se pueden usar
uno o varios objetos DataAdapter.
Dim daCli As New SqlDataAdapter("SELECT * FROM Clientes", cn)
Dim daFact As New SqlDataAdapter("SELECT * FROM Facturas", cn)
Dim ds As New DataSet()
daCli.Fill(ds, "Clientes")
daFact.Fill(ds, "Facturas")
Dim relation As DataRelation = ds.Relations.Add("CustOrders", _
ds.Tables("Clientes").Columns("cli_codigo"), _
ds.Tables("Facturas").Columns("cli_codigo"))
Dim pRow, cRow As DataRow
For Each pRow In ds.Tables("Clientes").Rows
Console.WriteLine(pRow("cli_codigo").ToString())
For Each cRow In pRow.GetChildRows(relation)
Console.WriteLine(vbTab & cRow("fac_numero").ToString())
Next
Next

CIBERTEC CARRERAS PROFESIONALES


90

3.3 ACTUALIZANDO UNA BASE DE DATOS CON UN


DATAADAPTER Y UN DATASET

El método Update del DataAdapter efectúa los cambios efectuados en un


DataSet. El método Update, al igual que el método Fill, acepta como
argumentos una instancia de un DataSet el que contiene los cambios
efectuados y un objeto DataTable que identifica la tabla desde la que se
pueden recuperar esos cambios.

Al llamar al método Update, el DataAdapter analiza los cambios efectuados y


ejecuta el comando apropiado (INSERT, UPDATE o DELETE). Cuando el
DataAdapter encuentra un cambio en una DataRow, utiliza los comandos
InsertCommand, UpdateCommand o DeleteCommand para reflejarlo. Antes
de llamar a Update, debe establecer de forma explícita los comandos.

El método Update refleja, en el origen de datos los cambios efectuados, pero


ya han modificado datos en el origen de datos desde el momento en que se
llenó el DataSet. Utilice el DataAdapter y el método Fill.

Si el método Fill encuentra un valor de clave principal para una fila del DataSet
que coincide con un valor de clave principal de una fila de los resultados
devueltos por SelectCommand, éste actualiza la fila existente con la
información de la fila devuelta por SelectCommand y establece el RowState
de la fila existente en Unchanged. Si una fila devuelta por SelectCommand
tiene un valor de clave principal que no coincide con ninguno de los valores de
clave principal de las filas del DataSet, el método Fill agrega una nueva fila con
un RowState de Unchanged.

En este ejemplo, se demuestra cómo se deben realizar las


actualizaciones en las filas modificadas estableciendo, de forma
explícita, el comando UpdateCommand de DataAdapter. Observe
cómo el parámetro @cod especificado en la cláusula WHERE de la
instrucción UPDATE utiliza el valor Original de SourceColumn. Este
hecho es muy importante, ya que el valor Current puede haber sido
modificado de forma que ya no coincida con el valor del origen de datos.
Dim da As New SqlDataAdapter("Select * from Articulos", cn)
da.UpdateCommand = New SqlCommand("Update Articulos Set
art_nombre=@nom, art_precio=@pre, art_stock = @st Where
art_codigo=@cod", cn)

With da.UpdateCommand.Parameters
.Add("@nom", SqlDbType.VarChar, 30, "art_nombre")
.Add("@pre", SqlDbType.Decimal, 10, "art_precio")
.Add("@st", SqlDbType.Int, 10, "art_stock")
Dim par As SqlParameter = .Add("@cod", SqlDbType.Char)
par.SourceColumn = "art_codigo"
par.SourceVersion = DataRowVersion.Original
End With

Dim ds As New DataSet


da.Fill(ds, "Articulos")
Dim row As DataRow = ds1.Tables("Articulos").Rows(i)
row("art_stock") = Val(txtstock.Text)
row("art_nombre") = Me.txtdescripcion.Text
row("art_precio") = Val(Me.txtprecio.Text)
da.Update(ds, "Articulos")
Me.DGArticulos.DataSource = ds.Tables("Articulos")

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 91

4 MANIPULACIÓN DE DATOS EN UN DATATABLE


Después de crear un DataTable en un DataSet, se pueden realizar las mismas
actividades que al utilizar una tabla de una base de datos. Se puede agregar,
ver, modificar y eliminar datos en la tabla, supervisar los errores y eventos y
consultar los datos de la tabla. Al modificar los datos de una DataTable, se
puede comprobar si los cambios son precisos y determinar si aceptarlos o
rechazarlos mediante programación.

4.1 ADICIÓN DE UNA FILA A UN DATATABLE


Creado el DataTable, se le pueden agregar nuevas filas de datos. Para
agregar una nueva fila, declare una nueva variable como tipo DataRow. Se
devuelve un nuevo objeto DataRow cuando se llama al método NewRow.

En el ejemplo siguiente se muestra cómo se crea una nueva fila


llamando al método NewRow.

Dim Row As DataRow = dt.NewRow


Row(0) = txtcodigo.Text
dt.Rows.Add(Row)

4.2 BÚSQUEDA UNA FILA EN UN DATATABLE


Para ubicar una Fila en una tabla, utilice el método Find. Éste retorna la
fila especificada por el valor de la clave primaria.

El siguiente ejemplo muestra cómo se realiza una búsqueda por el


código; si existe, se muestra los datos; sino, se muestra un mensaje.

Dim Row As DataRow = dt.Rows.Find(txtcodigo.Text)


If Not Row Is Nothing Then
txtdescripcion.Text = Row(1)
txtunidad.Text = Row(2)
Else
MessageBox.Show("No Existe")
End If

4.3 ELIMINACIÓN DE UNA FILA EN UN DATATABLE


Existen dos métodos:
Metodo Descripción

Remove Elimina una fila del DataRowCollection

Marca la fila para su eliminación. La eliminación propiamente se


Delete
produce al ejecutar el método AcceptChanges

Si se usa Delete, se puede comprobar mediante programación qué filas


están marcadas para eliminación antes de eliminarlas. Cuando una fila
está marcada para eliminación, su propiedad RowState está
establecida en Deleted.
Cuando el DataAdapter encuentra una fila marcada como Deleted,
ejecuta el método DeleteCommand para eliminar la fila en el origen de
datos. A continuación se puede quitar la fila permanentemente utilizando el
método AcceptChanges.

CIBERTEC CARRERAS PROFESIONALES


92

En el siguiente ejemplo, se muestra cómo se realiza la eliminación de una


fila por el método Remove
'capturo el indice de la Fila Actual(CurrentRow) del DataGrid
Dim i As Integer = Me.DGArticulos.CurrentRow.Index
Dim row As DataRow = dt.Rows(i)
dt.Rows.Remove(row)

4.4 ESTADOS Y VERSIONES DE UNA FILA


ADO .NET administra las filas de las tablas mediante:
o Estado de fila indica el estado de una fila.
o Versiones de fila mantienen los valores almacenados en una fila en
cuanto se modifica, incluyendo los valores actuales, originales y
predeterminados.
Cada objeto DataRow cuenta con la propiedad RowState que puede
examinar para determinar el estado actual de la fila. En la tabla siguiente,
se describen brevemente los valores de la enumeración RowState.

Estado Descripción

No se han hecho cambios desde la última llamada a


UnChanged
AcceptChanges.

Se ha agregado la fila a la tabla, pero no se ha llamado a


Added
AcceptChanges.

Modified Se ha cambiado algún elemento de la fila.

Se ha eliminado la fila de una tabla y no se ha llamado a


Deleted
AcceptChanges.

La fila no forma parte de ninguna DataRowCollection. El RowState


de una fila recién creada se establece en Detached. Una vez que se
Detached ha agregado la nueva DataRow a la DataRowCollection llamando al
método Add, el valor de la propiedad RowState se establece en
Added.

Cuando se llama a AcceptChanges en DataSet, DataTable o DataRow,


se quitan todas las filas con el estado de fila Deleted. Las filas que quedan
reciben el estado de fila Unchanged y los valores de la versión de fila
Original se sobrescriben con los valores de la versión de fila Current. Si
se llama a RejectChanges, se quitan todas las filas con el estado de fila
Added. Las filas que quedan reciben el estado de fila Unchanged y los
valores de la versión de fila Current se sobrescriben con los valores de la
versión de fila Original.

El siguiente ejemplo muestra los registros añadidos, no


modificacdos y eliminados (Delete) en un DataTable.

Dim tabla As DataTable = dt.GetChanges(DataRowState.Added)


Dim tabla1 As DataTable = dt.GetChanges(DataRowState.Deleted)
Dim tabla2 As DataTable = dt.GetChanges(DataRowState.Unchanged)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 93

Las distintas versiones de una fila se pueden ver pasando un parámetro


DataRowVersion con la referencia de la columna, como se muestra en el
ejemplo siguiente.

Versión Descripción

Current Valores actuales de la fila.

Es la versión de fila predeterminada para una determinada fila. La


Default versión de fila predeterminada para una fila Added, Modified o
Unchanged es Current.

Original Valores originales de la fila.

Proposed Valores propuestos para la fila.

Se puede comprobar si una DataRow tiene una versión de fila concreta


llamando al método HasVersion y pasando una DataRowVersion como
argumento. Ejemplo, DataRow.HasVersion (DataRowVersion.Original)
devolverá false para las filas recién agregadas antes de que se llame a
AcceptChanges.

4.5 MÉTODO PARA ACEPTAR O RECHAZAR LOS CAMBIOS EN LA


FILAS
Después de comprobar la exactitud de los cambios realizados en un
DataTable, se pueden aceptar con el método AcceptChanges de
DataRow, DataTable o DataSet, que configurará los valores de fila
Current de modo que sean los valores Original y establecerá la propiedad
RowState en Unchanged.
Si se aceptan o se rechazan los cambios, se elimina la información de
RowError y se establece la propiedad HasErrors en false. Aceptar o
rechazar cambios también puede afectar a la actualización de datos en el
origen de datos. Si hay restricciones de clave externa en la DataTable, los
cambios que se acepten o se rechacen con AcceptChanges y
RejectChanges se propagan a las filas secundarias de la DataRow de
acuerdo con la ForeignKeyConstraint.AcceptRejectRule

En el siguiente ejercicio, si los registros actualizados han generado


errores, HasErrors visualizamos el conjunto de errores y deshacemos la
actualización RehectChanges, si no hay errores, se procede a actualizar
AcceptChanges.

If dt.HasErrors Then
Dim str As String = ""
For Each row As DataRow In dt.GetErrors
str = str + row.RowError + vbCrLf
Next
MessageBox.Show(str)
dt.RejectChanges()
End If
dt.AcceptChanges()

CIBERTEC CARRERAS PROFESIONALES


94

LABORATORIO 5.1
CONSULTA DE DATOS RELACIONALES
En el ejemplo siguiente se muestra la consulta entre dos tablas: tb_clientes y
tb_pedidoscabe, donde al seleccionar un cliente en un control ListBox, visualice los
pedidos del cliente seleccionado.
1. Ingrese a Visual Studio 2005
2. Seleccione File->New->Project
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”
- En “Templates” elija “WindowsApplication”
- En “Name” coloque “appFacturacion4”
- En “Location” coloque “C:\CursoPOOII”
4. Diseño del Formulario:

5. Defina el Namespaces: System.Data.SqlClient.


6. Defina e inicialice la cadena de conexión a nivel Class Form, el objeto DataSet,
que almacenará las tablas.
Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=DBVentas; integrated security=true")
Private ds As New DataSet

7. En el Load del formulario realizar las siguientes operaciones:


a. Cargar las tablas clientes y pedidos utilizando el DataAdapter.
b. Poblar los registros del DataAdapter al DataSet.
c. Enlazar el Listbox1, con la tabla clientes.
d. Definir la relación entre las tablas y añadir la relación al DataSet.
'Manejo de DataAdapter
Dim da As New SqlDataAdapter("Select * from tb_clientes", cn)
da.Fill(ds, "Clientes")
ds.Tables("clientes").PrimaryKey = _
New DataColumn() {ds.Tables("clientes").Columns(0)}
da = New SqlDataAdapter("Select * from tb_pedidoscabe",cn)
da.Fill(ds, "pedidos")
'Enlazar el Listbox1
Me.ListBox1.DataSource = ds.Tables("clientes")
Me.ListBox1.DisplayMember = "NombreCia"
Me.ListBox1.ValueMember = "IdCliente"
'Establecer la Relacion entre las Tablas
Dim drel As New DataRelation( _
"r1", ds.Tables("clientes").Columns("IdCliente"), _
ds.Tables("facturas").Columns("IdCliente"))
'Agregar la relacion
ds.Relations.Add(drel)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 95

8. En el click del Listbox, mostramos las facturas según el cliente seleccionado:


a. Capturar el índice de la fila seleccionada: Listbox1.SelectedIndex.
b. Definir un Dataview de la tabla clientes.
c. Definir un DataRowView.
d. A través del método CreateChildView (nombre de la relación) del
DataRowView se capturan las filas de fac_cabe las cuales se visualizan en
el DataGrid1.
Dim i As Integer = ListBox1.SelectedIndex
Dim dv As New DataView(ds.Tables("clientes"))
Dim drv As DataRowView = dv(i)
Me.DataGridView1.DataSource = drv.CreateChildView("r1")

9. Guarde su aplicación y ejecute. Compruebe el resultado.

LABORATORIO 5.2
ACTUALIZACIÓN DE DATOS, UTILIZANDO EL DATAADAPTER
En este escenario, se implementara un formulario para realizar el mantenimiento de
los vendedores de la base de datos DVentas.

A través de este ejemplo utilizaremos los métodos del DataAdapter para la


actualización de datos

1. Agregar un formulario al proyecto y diseñarlo.

Objeto Name Propiedad Valor


Label1 Label1 Text Codigo
Label2 Label2 Text Nombre
Label3 Label3 Text Teléfono
Label4 Label4 Text Direccion
Textbox1 Txtcodigo Text
Textbox2 Txtnombre Text
Textbox3 Txtfono Text
Textbox4 Txtdireccion Text
Button1 BtnLimpiar Text Limpiar
Button2 BtnGrabar Text Grabar
Button3 BtnActualizar Text Actualizar
Button4 BtnEliminar Text Eliminar
DataGridView1 DGVendedor

CIBERTEC CARRERAS PROFESIONALES


96

2. Defina el Namespace y la cadena de conexión


3. Defina la función DataArticulos que retorne los artículos.
Function DataVendedor() As DataTable
Dim da As New SqlDataAdapter("Select*fron tb_vendedor",cn)
Dim t As New DataTable

da.Fill(t)
Return t
End Function

4. En el evento Load del Form, llenar los datos en DGVendedor.

Me.DGVendedor.DataSource = DataVendedor()

5. Para navegar por los registros del DataGridView DGVendedor y al seleccionar


un registro se visualice en los Textboxes, se deberá programar en el evento
CellClick.

With DGVendedor.CurrentRow
txtcodigo.Text = .Cells(0).Value
txtnombre.Text = .Cells(1).Value
txtfono.Text = .Cells(2).Value
txtdireccion.Text = .Cells(3).Value
End With

6. En el evento click del botón actualizar, modificamos los datos de un vendedor


seleccionado:
a. Capture el índice de la fila seleccionada.
b. Defina un DataAdapter de tipo UpdateCommand.
c. Defina sus parámetros.
d. Crea un DataRow de la fila seleccionada.
e. Aplique el Update del DataAdapter a la tabla.

Dim i As Integer = Me.DGVendedor.CurrentRow.Index


Dim da As New SqlDataAdapter("Select * from tb_Vendedor", cn)
da.UpdateCommand = New SqlCommand("Update tb_Vendedor Set
ven_nombre=@nom, ven_telefono=@f, ven_direccion = @d Where
ven_codigo=@cod", cn)
With da.UpdateCommand.Parameters
.Add("@nom", SqlDbType.VarChar, 30, "ven_nombre")
.Add("@f", SqlDbType.Char, 8, "ven_telefono")
.Add("@d", SqlDbType.VarChar, 60, "ven_direccion")
Dim par As SqlParameter = .Add("@cod", SqlDbType.Char)
par.SourceColumn = "ven_codigo"
par.SourceVersion = DataRowVersion.Original
End With
Dim dt As New DataTable
da.Fill(dt)
Dim row As DataRow = dt.Rows(i)
row("ven_nombre") = txtnombre.Text
row("ven_telefono") = txtfono.Text
row("ven_direccion") = txtdireccion.Text
da.Update(dt)
Me.DGVendedor.DataSource = ds1

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 97

7. En el evento click del botón grabar, insertaremos un nuevo vendedor:


a. Defina un DataAdapter de tipo InsertCommand, defina sus parámetros.
b. Cree un DataRow, definir de tipo NewRow, y le agregamos sus valores.
c. Añada la nueva fila a la tabla.
d. Aplicamos el Update del DataAdapter a la tabla y visualizamos los
registros.

¿Cómo evaluaría si el código del vendedor se va a duplicar?

Dim da As New SqlDataAdapter("Select * from tb_Vendedor", cn)


da.InsertCommand = New SqlCommand("Insert Into
tb_Vendedor(ven_codigo,ven_nombre,ven_telefono,ven_direccion)
Values(@cod, @nom, @f, @dir)", cn)
With da.InsertCommand.Parameters
.Add("@cod", SqlDbType.Char, 5, "ven_codigo")
.Add("@nom", SqlDbType.VarChar, 30, "ven_nombre")
.Add("@f", SqlDbType.VarChar, 8, "ven_telefono")
.Add("@dir", SqlDbType.VarChar, 60, "ven_direccion")
End With
Dim dt As New DataTable
da.Fill(dt)
Dim row As DataRow = dt.NewRow
row("ven_codigo") = txtcodigo.Text
row("ven_nombre") = txtnombre.Text
row("ven_telefono") = txtfono.Text
row("ven_direccion") = txtdireccion.Text
dt.Rows.Add(row)

da.Update(dt)
Me.DGVendedor.DataSource = dt

8. Aplique el concepto para eliminar un registro seleccionado


9. Guarde su aplicación y ejecútela.

LABORATORIO 5.3
ACTUALIZACIÓN DE DATOS, UTILIZANDO EL DATASET
En este escenario, se implementará un formulario para realizar el mantenimiento de
los artículos de la base de datos BDFactura.
1. Agregue un formulario al proyecto y diséñelo.

CIBERTEC CARRERAS PROFESIONALES


98

Objeto Name Propiedad Valor


Label1 Label1 Text Codigo
Label2 Label2 Text Descripcion
Label3 Label3 Text Unidad
Label4 Label4 Text Precio
Label5 Label5 Text Stock
Textbox1 Txtcodigo Text
Textbox2 Txtdescripcion Text
Textbox3 Txtunidad Text
Textbox4 Txtprecio Text
Textbox5 Txtstock Text
Button1 BtnLimpiar Text Limpiar
Button2 BtnBuscar Text Buscar
Button3 BtnGrabar Text Grabar
Button4 BtnModificar Text Modificar
Button5 BtnEliminar Text Eliminar
DataGridView1 DGArticulos

2. Defina el NameSpace, su conexión y un DataTable.


Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=DBVentas; integrated security=true")
Dim dt As New DataTable

3. En el evento Load del Form, defina el DataTable y una clave primaria.

Dim da As New SqlDataAdapter("Select*from tb_productos",cn)


da.Fill(dt)
dt.PrimaryKey = New DataColumn() {dt.Columns(0)}
Me.DGArticulos.DataSource = dt

4. Al seleccionar una fila en el DataGridView, mostrar sus datos, donde haremos


una búsqueda de la fila por su código.

Dim row As DataRow = dt.Rows.Find( _


Me.DGArticulos.CurrentRow.Cells(0).Value)
txtcodigo.Text = row(0)
txtdescripcion.Text = row(1)
txtunidad.Text = row(2)
txtprecio.Text = row(3)
txtstock.Text = row(4)

5. En el evento click del botón grabar, agregar un nuevo artículo.


Dim Row As DataRow = dt.NewRow
Row(0) = txtcodigo.Text
Row(1) = txtdescripcion.Text
Row(2) = txtunidad.Text
Row(3) = Val(txtprecio.Text)
Row(4) = Val(txtstock.Text)
dt.Rows.Add(Row)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 99

6. En el evento click del botón buscar, ubique un registro por su código, si lo ubica
llenará los TextBox.

Dim Row As DataRow = dt.Rows.Find(txtcodigo.Text)


If Row Is Nothing Then
MessageBox.Show("No Existe")
Else
txtdescripcion.Text = Row(1)
txtunidad.Text = Row(2)
txtprecio.Text = Row(3)
txtstock.Text = Row(4)
End If

7. En el evento click del botón eliminar, se ejecuta el proceso de borrar un registro


seleccionado.

Dim row As DataRow


Row =
dt.Rows.Find(Me.DGArticulos.CurrentRow.Cells(0).Value)
dt.Rows.Remove(row)

8. En el evento click del botón modificar, se ejecutará en proceso donde se


cambiarán los datos del artículo seleccionado. Se observa que no se actualiza
el código del artículo.

Dim row As DataRow


row =
dt.Rows.Find(Me.DGArticulos.CurrentRow.Cells(0).Value)
row(1) = Me.txtdescripcion.Text
row(2) = Me.txtunidad.Text
row(3) = Val(txtprecio.Text)
row(4) = Val(txtstock.Text)

9. Pinte el botón Actualizar Datos, el cual actualizará los datos del DataTable,
donde evalúa, primero, si no tiene errores actualizará los cambios utilizando el
método AcceptChanges, caso contrario, visualiza los errores y deshace la
operación a través del método RejectChanges.

If Not dt.HasErrors Then


dt.AcceptChanges()
Else
Dim str As String = ""
For Each row As DataRow In dt.GetErrors
str = str + row.RowError + vbCrLf
Next
MessageBox.Show(str)
dt.RejectChanges()
End If

CIBERTEC CARRERAS PROFESIONALES


100

10. Guarde el proyecto y ejecute para realizar las pruebas.

Pregunta: ¿Cómo pasar los datos actualizados en el DataSet a la base


de datos?, investigue acerca del CommandBuilder. Tarea de
Investigación.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 101

Autoevaluación

1. ¿Cuál es la Arquitectura del DataSet?


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

2. ¿Cómo se agrega columnas, cómo se define un campo Unique y un Primary


Key?
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

3. ¿Cuáles son los métodos del DataAdapter? Explique brevemente.


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

4. Explique el estado y la versión de una fila.


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

5. ¿Qué es un DataView? Explique su método de ordenamiento y filtro.


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

CIBERTEC CARRERAS PROFESIONALES


102

Resumen

 El modelo de datos desconectados, está representado por el DataSet, el cual está


conformado por DataTable Collection, DataRelation Collection, Primary Key,
Constraint.

 Un DataTable se puede trabajar dentro o fuera del DataSet; se le puede agregar


columnas, definir constraint: UniqueConstraint y ForeignKeyConstraint.

 Un DataRelation establece la relación entre dos tablas: principal y la hija; al


generar un DataRelation, está se agrega al DataSet y crea, por defecto, un
Constraint Unique y ForeignKey.

 En un DataAdapter, los datos son actualizados a través de sus cuatro métodos:


InsertCommand, UpdateCommand, DeleteCommand y SelectCommand, los que
afectan directamente al origen de datos, utilizando el método Update.

 Se puede realizar operaciones en un DataTable: añadir registros, modificar sus


datos, eliminar los registros. Para confirmar los registros, se utiliza los métodos
AcceptChanges (actualizar) o RejectChanges (deshacer los cambios).

 Las filas de un DataTable, según su operación manejan estados: Added, Deleted,


Modified y Unchanged. Ello para que éstas sean visualizadas por el
DataRowVersion.

 El DataView es una vista de datos de una tabla, la cual puede realizar operaciones
de ordenamiento y filtro, independiente de la tabla de origen.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://msdn2.microsoft.com/es-es/library/zb0sdh0b(VS.80).aspx
Página que explica la estructura del DataSet de ADO.NET

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 103

UNIDAD DE
APRENDIZAJE

2
SEMANA

OPERACIONES DE SCONECTADAS: USO DEL


DATAVIEW Y EL DATATABLEREADER

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos elaboran aplicaciones Windows .NET que accedan a
un origen de datos en forma desconectada utilizando los objetos del ADO.NET para
obtener una mejor performance en los procesos de consulta y actualización de una
aplicación.

TEMARIO

• Creación y definición DataSet, DataTable, Constraint y DataView.


• Proceso de consulta y actualización de datos desconectados en un DataSet.
• Operaciones desconectadas utilizando el Asistente del Visual Studio.
• Operaciones de consultas utilizando el DataView.
• Manejo de un DataTableReader desde un DataSet o DataTable.

ACTIVIDADES PROPUESTAS

• Los alumnos realizan operaciones de consulta en un DatView.


• Los alumnos realizan operaciones de consulta en un DataTableReader sobre un
DataSet o DataTable.

CIBERTEC CARRERAS PROFESIONALES


104

1. DATAVIEW
Una DataView proporciona una vista de datos dinámica en la DataTable
subyacente: el contenido, el orden y la pertenencia reflejan los cambios en
cuanto se producen. Este comportamiento difiere del método Select de la
DataTable, que devuelve una matriz de DataRow de una tabla basada en un
filtro o un orden determinados: este contenido refleja cambios en la tabla
subyacente, pero la pertenencia y la ordenación siguen siendo estáticas.

1.1 CREACIÓN DE UN DATAVIEW


Hay dos formas de crear una DataView. Puede utilizar el constructor
DataView o puede crear una referencia a la propiedad DefaultView de la
DataTable. El constructor DataView puede estar vacío o puede aceptar
también DataTable como único argumento o DataTable junto con el
criterio de filtro o de ordenación, y un filtro de estado de fila.

Dim dv As DataView = dt.DefaultView

Al crear una DataView sin especificar criterios de ordenación o de filtro y


establecer posteriormente las propiedades Sort, RowFilter o
RowStateFilter hace que el índice se construya dos veces como mínimo:
una vez al crear la DataView y otra vez más al modificar cualquiera de las
propiedades de ordenación o filtro. En el siguiente ejemplo creamos un
DataView definido por el DataTable dt, con un filtro RowFilter:
cli_codigo=’C0001’; ordenamiento true, y que el estado de las filas sean
Current.

Dim dv1 As New DataView(dt, "cli_codigo='C0001'", True,


DataViewRowState.CurrentRows)

1.2 ORDENAMIENTO Y FILTRACIÓN DE DATOS MEDIANTE


DATAVIEW
Proporciona varias formas de ordenación y filtrado en una DataTable:
• Mediante la propiedad Sort puede especificar criterios simples o
múltiples de ordenación de columnas e incluir parámetros ASC
(ascendente) y DESC (descendente).
• Mediante la propiedadApplyDefaultSort puede crear automáticamente
un criterio de ordenación, en orden ascendente, basado en la columna o
columnas de clave principal de la tabla.
• La propiedad RowFilter puede especificar subconjuntos de filas
basándose en sus valores de columna.
• Si desea devolver los resultados de una consulta determinada en los
datos, en lugar de proporcionar una vista dinámica de un subconjunto
de los datos, para conseguir el máximo rendimiento utilice los métodos
Find o FindRows de la DataView en lugar de establecer la propiedad
RowFilter. La propiedad RowFilter es más idónea en una aplicación
enlazada a datos donde un control enlazado muestra resultados
filtrados. Los métodos Find y FindRows aprovechan el índice actual,
sin necesidad de volver a generarlo.
• Mediante la propiedad RowStateFilter puede especificar las versiones
de fila que desea ver. La DataView administra, implícitamente, qué
versión de fila exponer, dependiendo del RowState de la fila

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 105

subyacente. Por ejemplo, si el RowStateFilter está establecido como


DataViewRowState.Deleted, la DataView expone la versión de fila
Original de todas las filas Deleted, porque no hay ninguna versión de
fila Current.

En la siguiente tabla se muestran las opciones de DataViewRowState.


Estado Descripción

Valor predeterminado, la versión de fila Current de


CurrenRows
las filas Unchanged, Added, Modified.

Added Versión de todas las filas Added.

ModifiedCurrent Versión de la fila Current de las filas Modified.

Deleted Versión de todas las filas Deleted.

ModifiedOriginal Versión de fila Original de las filas Modified.

Versión de fila Original de filas Unchanged, Modified


OriginalRows
y Deleted.

Unchanged Versión de fila Current de las filas Unchanged.

El siguiente ejercicio, crea una vista de la tabla artículos que


muestra los registros donde su stock sea menor a 50, y que esté
ordenado por su nombre en forma descendente.

Dim dv As DataView = dt.DefaultView


dv.RowFilter = "art_stock<=50"

dv.Sort = "art_nombre desc"


Me.DGArticulos.DataSource = dv

1.3 MODIFICAR OBJETOS DATAVIEW


Puede utilizar DataView para agregar, eliminar o modificar filas de datos de
la tabla subyacente. La posibilidad de utilizar DataView para modificar los
datos de la tabla subyacente se controla estableciendo una de las tres
propiedades booleanas de DataView. Dichas propiedades son: AllowNew,
AllowEdit y AllowDelete. Están establecidas como true de forma
predeterminada.
1.3.1 AllowNew: Utilice el método AddNew de la DataView para crear
una nueva DataRowView.
Tenga en cuenta que no se agrega realmente una nueva fila a la
DataTable subyacente hasta que se llama al método EndEdit de la
DataRowView. Si se llama al método CancelEdit de la
DataRowView, se descartará la nueva fila. Si se llama al método
AddNew o BeginEdit de la DataRowView mientras hay una fila
pendiente, se llamará implícitamente a EndEdit en la fila pendiente.
Cuando se llama a EndEdit se aplican los cambios a la DataTable
subyacente; más tarde se pueden confirmar o rechazar mediante los
métodos AcceptChanges o RejectChanges del objeto DataTable,
DataSet o DataRow.

CIBERTEC CARRERAS PROFESIONALES


106

1.3.2 AllowEdit: Modifica el contenido de la DataRow mediante


DataRowView. Puede confirmar los cambios realizados en la fila
subyacente mediante DataRowView.EndEdit o rechazarlos con
DataRowView.CancelEdit. Tenga en cuenta que sólo puede
modificar una fila cada vez. Cuando se llama a EndEdit, los cambios
propuestos se ponen en la versión de fila Current de la DataRow
subyacente; más tarde se pueden confirmar o rechazar mediante los
métodos AcceptChanges o RejectChanges del objeto DataTable,
DataSet o DataRow.
1.3.3 AllowDelete: Elimina filas en la DataView mediante el método
Delete del objeto DataView o DataRowView y las filas se eliminarán
de la DataTable subyacente. Más tarde puede confirmar o rechazar
las eliminaciones mediante AcceptChanges o RejectChanges,
respectivamente.

En el siguiente ejemplo de código se deshabilita el uso de


DataView para eliminar filas y se agrega una nueva fila a la
tabla subyacente mediante la DataView.

Dim custTable As DataTable = custDS.Tables("tb_clientes")


Dim custView As DataView = custTable.DefaultView
custView.Sort = "CompanyName"

custView.AllowDelete = False

Dim newDRV As DataRowView = custView.AddNew()


newDRV("CustomerID") = "ABCDE"
newDRV("CompanyName") = "ABC Products"
newDRV.EndEdit()

2. DATATABLEREADER
La clase DataTableReader obtiene el contenido de uno o varios objetos
DataTable con el formato de uno o varios conjuntos de resultados de solo
lectura y con desplazamiento sólo hacia delante.

La clase DataTableReader funciona de forma bastante similar a cualquier otro


lector de datos, como SqlDataReader, excepto en que la clase
DataTableReader permite recorrer en iteración las filas de un objeto
DataTable. En otros términos, permite recorrer en iteración las filas que hay en
una caché. Es posible modificar los datos almacenados en memoria caché
mientras el objeto DataTableReader está activo y el lector mantiene su
posición automáticamente.

2.1 CREACION DE UN DATATABLEREADER


Cuando se crea un objeto DataTableReader a partir de un objeto
DataTable, el objeto DataTableReader resultante contiene un conjunto de
resultados con los mismos datos que el objeto DataTable a partir del cual
se ha creado, salvo cualquier fila que haya sido marcada como eliminada.
Las columnas aparecen en el mismo orden que en el objeto DataTable
original. El resultado que devuelve tiene el mismo formato de esquema y
datos que el objeto DataTable original. El objeto DataTableReader que
se cree llamando al método GetDataReader de un objeto DataSet

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 107

contendrá varios conjuntos de resultados si el objeto DataSet incluye más


de una tabla. Los resultados tendrán la misma secuencia que los objetos
DataTable de la colección DataTableCollection del objeto DataSet.
El conjunto de resultados devuelto sólo contiene la versión actual de cada
DataRow; se omiten las filas que se hayan marcado para eliminarlas.
La clase DataTableReader proporciona un iterador estable; esto es, el
contenido de un objeto DataTableReader no se invalida aunque se
modifique la colección subyacente durante la iteración.
Por ejemplo, si se eliminan o quitan una o varias filas de la colección de
Rows durante la iteración, la posición actual en el objeto
DataTableReader se mantiene correctamente y el iterador no se invalida.

2.1 PROPIEDADES DE UN DATATABLEREADER


Nombre Descripción

FielCount Devuelve el número de columnas de la fila actual.

Obtiene un valor que indica si el objeto DataTableReader


HasRows
contiene una o varias filas.

Obtiene un valor que indica si el objeto DataTableReader


IsClosed
está cerrado.

Obtiene el valor de la columna especificada en su formato


Item
nativo.

Obtiene el número de filas insertadas, modificadas o


RecordAffected
eliminadas al ejecutar la instrucción SQL.

Avanza el objeto DataTableReader al conjunto de


NextResult
resultados siguiente, si hay alguno.

Next Desplaza el objeto DataTableReader al siguiente registro.

Cuando se crea un objeto DataTableReader a partir de un objeto


DataTable, el objeto DataTableReader resultante contiene un conjunto de
resultados con los mismos datos que el objeto DataTable a partir del cual
se ha creado, salvo cualquier fila que haya sido marcada como eliminada.
Las columnas
En el ejemplo siguiente se rellenan de datos en un DataTable. A
continuación, se crea un objeto DataTableReader que se inicializa con el
objeto DataTable para mostrar el contenido de sus registros en un
ListView.
Dim pReader As New DataTableReader(Productos())
Do
While pReader.Read
Dim it As New ListViewItem(pReader.GetInt32(0))
it.SubItems.Add(pReader.GetString(1))
it.SubItems.Add(pReader.GetInt32(2))
it.SubItems.Add(pReader.GetInt32(3))
it.SubItems.Add(pReader.GetInt32(2)*pReader.GetInt32(3))
Me.ListView1.Items.Add(it)
End While
Loop Until pReader.HasRows

CIBERTEC CARRERAS PROFESIONALES


108

LABORATORIO 6.1
CONSULTA DE DATOS UTILIZANDO UN DATAVIEW
En el ejemplo siguiente se muestra la consulta de los productos registrados en la
base de datos por su descripción. Para este caso, ingrese la descripción del producto
desde un TextBox, donde filtrará los registros por su descripción.

1. Ingrese a Visual Studio 2005.


2. Seleccione File->New->Project.
3. Asigne el nombre al proyecto: “appConsulta”.

4. Defina el Namespaces: System.Data.SqlClient.


5. Defina e inicialice la cadena de conexión a nivel Class Form, el objeto DataSet,
que almacenará las tablas y el objeto DataView para realizar la consulta.

Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;


DataBase=DBVentas; integrated security=true")
Private ds As New DataSet
Private dv As New DataView

6. En el Load del formulario realizar las siguientes operaciones:


a. Cargar la tabla tb_productos utilizando el DataAdapter.
b. Poblar los registros del DataAdapter al DataSet, definiendo un datatable
llamado productos.
c. Definir la relación entre las tablas y añadir la relación al DataSet.
'Manejo de DataAdapter
Dim da As New SqlDataAdapter("Select * from tb_productos", cn)
da.Fill(ds, "productos")
'Cargar los registros al dataView
dv = ds.Tables("productos").DefaultView
'cargar los registros al DataGrid utilizando el DataView
Me.DSArticulos.DataSource = dv

7. En el click del botón Consulta, donde mostramos los productos por su nombre:
a. Ingresa la descripción del producto en el control TextBox.
b. Asigne al método RowFilter la expresión de comparación.
c. Mostrar el resultado del filtro en el control DataGridView DGArticulos.

dv.RowFilter = _
"nombreproducto LIKE '" + txtdescripcion.Text + "%'"
Me.DSArticulos.DataSource = dv

8. Guarde su aplicación y ejecute. Compruebe.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 109

LABORATORIO 6.2
CONSULTA DE DATOS RELACIONALES UTILIZANDO
DATAVIEW
En el ejemplo siguiente se muestra la consulta de los pedidos por un empleado
determinado, donde al seleccionar un empleado en un ComboBox, visualice los
pedidos del empleado seleccionado.
1. Ingrese a Visual Studio 2005.
2. Seleccione File->New->Project.
3. Agregue un Formulario en el proyecto “appConsulta”.
4. Diseña el Formulario:

5. Defina el Namespaces: System.Data.SqlClient.


6. Defina e inicialice la cadena de conexión a nivel Class Form, el objeto DataSet,
que almacenará las tablas y la vista de datos para los empleados.
Private cn As New SqlConnection("server=.;database=DBVentas;
integrated security=true")
Private ds As New DataSet
Private DvEmpleado As New DataView

7. En el Load del formulario realizar las siguientes operaciones:


a. Cargar los empleados y pedidos utilizando el DataAdapter.
b. Poblar los registros del DataAdapter al DataSet.
c. Enlazar el ComboBox1, con el DataView DsEmpleado.
d. Definir la relación entre las tablas y añadir la relación al DataSet.
Dim da As New SqlDataAdapter( _
"Select Idempleado,Nombre+' '+Apellidos as Datos from
tb_empleados", cn)
da.Fill(ds, "empleados")
ds.Tables("empleados").PrimaryKey = _
New DataColumn() {ds.Tables("empleados").Columns(0)}
DvEmpleado = ds.Tables("empleados").DefaultView
da = New SqlDataAdapter("Select * from tb_pedidoscabe", cn)
da.Fill(ds, "pedidos")
Me.ComboBox1.DataSource = dsEmpleado
Me.ComboBox1.DisplayMember = "Datos"
Me.ComboBox1.ValueMember = "Idempleado"

'Establecer la Relacion entre las Tablas


Dim drel As New DataRelation( _
"r1", ds.Tables("empleados").Columns(0), _
ds.Tables("pedidos").Columns("Idempleado"))
ds.Relations.Add(drel)

CIBERTEC CARRERAS PROFESIONALES


110

8. En el click del Listbox, mostramos los pedidos del empleado seleccionado:


a. Capturar el índice de la fila seleccionada: ComboBox1.SelectedIndex.
b. Definir un DataRowView.
c. A través del método CreateChildView, del DataRowView, se capturan las
filas de pedidos las cuales se visualizan en el DataGrid1.
Dim DVista As DataRowView=vEmpleado(ComboBox1.SelectedIndex)
Me.DataGridView1.DataSource = DVista.CreateChildView("r1")

9. Guarde su aplicación y ejecute. Compruebe el resultado.

LABORATORIO 6.3
ACTUALIZACION DE DATOS UTILIZANDO DATAVIEW
En el ejemplo siguiente desarrollamos una interfaz que permita actualizar los datos de
los clientes utilizando un DataView. En este proceso el DataView estará asociado aun
DataTable para realizar, el DataView, los procesos de Agregar, Modificar y Eliminar
registros de Clientes sobre el DataTable.
1. En el Proyecto AppConsulta, agregue un Formulario.
2. Diseña el Formulario:

Objeto Name Propiedad Valor


Label Label1 Text Actualizacion de Clientes
Label Label2 Text Codigo
Label Label3 Text Nombre
Label Label4 Text Direccion
Label Label5 Text País
Label Label6 Text Fono
TextBox Txtcodigo
TextBox TxtNombre
Textbox TxtDireccion
TextBox TxtFono
ComboBox ComboBox1
Button BtnAgregar Text Agregar
Button BtnModificar Text Modificar
Button BtnEliminar Text Eliminar
DataGridView DGClientes

3. Defina el Namespaces: System.Data.SqlClient.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 111

4. Defina e inicialice la cadena de conexión a nivel Class Form, el objeto DataSet,


que almacenará las tablas y la vista de datos para los Clientes.

Private cn As New SqlConnection("server=.;database=DBVentas;


integrated security=true")
Private DvClientes As New DataView
Private Clientes As New DataTable

5. En el evento Load del formulario, realice las siguientes operaciones:


a. Cargar los datos de los países en el control ComboBox1.
b. Cargar los datos de los clientes en el DataTable “Clientes”.
c. Asignar la vista del DataTable “Clientes” al DataView “DvClientes”.
Using da As New SqlDataAdapter("Select * from tb_paises", cn)
Dim t As New DataTable
da.Fill(t)
Me.ComboBox1.DataSource = t
Me.ComboBox1.DisplayMember = "NombrePais"
Me.ComboBox1.ValueMember = "IdPais"
End Using
Using da As New SqlDataAdapter("Select * from tb_clientes", cn)
da.FillSchema(Clientes, SchemaType.Mapped)
da.Fill(Clientes)
DvClientes = Clientes.DefaultView
Me.DGClientes.DataSource = DvClientes
End Using

6. En el evento Click del botón Agregar, procedemos agregar un Cliente utilizando el


objeto DataView DvClientes.
Dim r As DataRowView = DvClientes.AddNew
r(0) = TXTCODIGO.Text
r(1) = TXTNOMBRE.Text
r(2) = TXTDIRECCION.Text
r(3) = Me.ComboBox1.SelectedValue
r(4) = TXTFONO.Text
r.EndEdit()
Clientes.AcceptChanges()
Me. DGClientes.DataSource = DvClientes
7. En el evento Click del botón Modificar, procedemos a modificar los datos de un
Cliente seleccionado desde el DataGridView.
'la variable f se le asigna la fila seleccionada del DataGridView
Dim r As DataRowView = DvClientes(DGClientes.CurrentRow.Index)
r(0) = TXTCODIGO.Text
r(1) = TXTNOMBRE.Text
r(2) = TXTDIRECCION.Text
r(3) = Me.ComboBox1.SelectedValue
r(4) = TXTFONO.Text
r.EndEdit()
Clientes.AcceptChanges()
Me.DGClientes.DataSource = DvClientes

8. En el evento Click del botón Eliminar, procedemos a eliminar un Cliente.


seleccionado
'la variabledesde el DataGridView
f se le asigna la fila seleccionada del DataGridView
Dim r As DataRowView = DvClientes(DGClientes.CurrentRow.Index)
r.Delete()
r.EndEdit()
Clientes.AcceptChanges()
DGClientes.DataSource = DvClientes

CIBERTEC CARRERAS PROFESIONALES


112

9. En el evento CellClick del DataGridView, seleccionamos un cliente y visualizamos


los datos del registro, almacenado en el DataView, en los controles.
'la variable f se le asigna la fila seleccionada del DataGridView
Dim f As Integer = Me.DataGridView1.CurrentRow.Index
TXTCODIGO.Text = DvClientes(f)(0)
TXTNOMBRE.Text = DvClientes(f)(1)
TXTDIRECCION.Text = DvClientes(f)(2)
Me.ComboBox1.SelectedValue = DvClientes(f)(3)
TXTFONO.Text = DvClientes(f)(4)

10. Guarde y ejecute la aplicación.

LABORATORIO 6.4
LISTADO DE PRODUCTOS UTILIZANDO DATATABLEREADER
En el ejemplo siguiente desarrollamos una interfaz que permita listar los productos en
un control ListView, utilizando un objeto DataTableReader.
1. En el Proyecto AppConsulta, agregue un Formulario.
2. Diseña el Formulario:

3. Defina la función Productos() el cual retorne los registros de la tabla tb_productos.


Para este caso utilice el TableAdapter DSVentasTableAdapter.
Function Productos() As DataTable
Dim ds As New DBVentasDataSet
Dim prod As New _
DVentasDataSetTableAdapters.tb_productosTableAdapter()
prod.Fill(ds.tb_productos)
Return ds.tb_productos
End Function

4. En el evento Load del formulario, listamos los productos en el control ListView


utilizando un DataTableReader, el cual se inicializa con la función Productos().

Dim pReader As New DataTableReader(Productos())


Do
While pReader.Read
Dim it As New ListViewItem(pReader.GetInt32(0))
it.SubItems.Add(pReader.GetString(1))
it.SubItems.Add(pReader.GetInt32(2))
it.SubItems.Add(pReader.GetInt32(3))
it.SubItems.Add(pReader.GetInt32(2) * pReader.GetInt32(3))
Me.ListView1.Items.Add(it)
End While
Loop Until pReader.HasRows

5. Guarde y ejecute la aplicación.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 113

Autoevaluación

1. ¿Cómo se crea un DataView? Explique las dos formas.


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

2. ¿Cuáles son los métodos para ordenar y filtrar un DataView? Explique


mediante un ejemplo.
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

3. Explique las propiedades del DataViewRowState.


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

4. ¿Cuáles son los métodos para modificar los datos a través del DataView?
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

5. ¿Qué es un DataTableReader?, ¿Cuál es la diferencia con el DataReader?


_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________
_____________________________________________________________

CIBERTEC CARRERAS PROFESIONALES


114

Resumen

 Una DataView proporciona una vista de datos dinámica en la DataTable


subyacente: el contenido, el orden y la pertenencia reflejan los cambios en cuanto
se producen.

 Hay dos formas de crear una DataView.


o Puede utilizar el constructor DataView.
o O puede crear una referencia a la propiedad DefaultView de la
DataTable.

 Un DataView proporciona metodos para filtrar y ordenar registros:


o Mediante la propiedad Sort puede especificar criterios simples o
múltiples de ordenación de columnas e incluir parámetros ASC
(ascendente) y DESC (descendente).
o Mediante la propiedad RowFilter puede especificar subconjuntos de
filas basándose en sus valores de columna.

 Un DataView puede agregar, eliminar o modificar filas de datos de la tabla


subyacente. La posibilidad de utilizar DataView para modificar los datos de la tabla
subyacente se controla estableciendo una de las tres propiedades booleanas de
DataView. Dichas propiedades son: AllowNew, AllowEdit y AllowDelete. Están
establecidas como true de forma predeterminada.

 La clase DataTableReader funciona de forma bastante similar a cualquier otro


lector de datos, como SqlDataReader, excepto en que la clase DataTableReader
permite recorrer en iteración las filas de un objeto DataTable.

 Cuando se crea un objeto DataTableReader a partir de un objeto DataTable, el


objeto DataTableReader resultante contiene un conjunto de resultados con los
mismos datos que el objeto DataTable a partir del cual se ha creado, salvo
cualquier fila que haya sido marcada como eliminada. Las columnas aparecen en
el mismo orden que en el objeto DataTable original.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://msdn.microsoft.com/es-
es/library/system.data.datatablereader.hasrows(VS.80).aspx
Página referente al uso del método HasRows del datatableReader

 http://msdn.microsoft.com/es-
es/library/system.data.datatablereader.getvalues(VS.80).aspx
Página referente al uso de los metodos Get del datatableReader

 http://msdn.microsoft.com/es-es/library/system.data.dataview(VS.80).aspx
Página referente a la clase DataView

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 115

UNIDAD DE
APRENDIZAJE

3
SEMANA

MANEJO DE REPORTES

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET construyen


reportes, listados y gráficos utilizando Crystal Report conectado a un origen de datos.

TEMARIO

• Uso del Crystal Report.

• Manejo de reportes y parámetros con Crystal Report.

• Uso de reportes gráficos.

ACTIVIDADES PROPUESTAS

• Los alumnos construyen reportes utilizando el asistente Crystal Reports enlazados


a un origen de datos.
• Los alumnos realizan operaciones de listado de datos visualizando el resultado en
el Crystal Report.
• Los alumnos construyen gráficos estadísticos utilizando el asistente Crystal Report.

CIBERTEC CARRERAS PROFESIONALES


116

1 CRYSTAL REPORT

Visual Studio .NET proporciona un conjunto de herramientas y asistentes que


permiten interactuar con un Origen de Datos. Una de esas herramientas es el
Crystal Report.

En Visual Studio .NET, se puede crear un nuevo informe Crystal o agregar uno
existente a un proyecto. Puede guardar el informe en un equipo local o publicarlo
como servicio Web en un servidor Web. En función de si va a desarrollar una
aplicación de Windows o una aplicación Web, deberá enlazar primero el informe
con Windows Forms Viewer o con Web Forms Viewer y, a continuación, crear la
aplicación. Los usuarios pueden ejecutar la aplicación para Windows en una
plataforma de Windows o implementar la aplicación Web en un servidor Web y
ver el informe Crystal en un explorador Web.

2 ACCESO A DATOS DE INFORMES


Crystal Reports se conecta a bases de datos mediante controladores de bases
de datos. Cada controlador se escribe para controlar un tipo de base de datos
específico o la tecnología de acceso a bases de datos.

MODELO DE EXTRACCIÓN E INSERCIÓN


Con el fin de ofrecer el acceso a datos más flexible para los programadores, los
controladores de base de datos de Crystal Reports se han diseñado para
proporcionar un modelo de extracción e inserción de acceso a datos.

2.1.1 Modelo de Extracción


En un modelo de extracción, el controlador se conectará a la base de datos y
extraerá datos cuando se necesiten. Con este modelo, Crystal Reports controla
tanto la conexión a la base de datos como el comando SQL que se ejecuta
para obtener los datos y no necesita ninguna codificación del programador. Si
no se escribe ningún código especial en tiempo de ejecución, se utiliza el
modelo de extracción.

2.1.1 Modelo de Inserción


En comparación, el modelo de inserción necesita que el programador escriba
código para conectarse a la base de datos, ejecutando un comando SQL para
crear un conjunto de registros o de datos que se ajusten a los campos del
informe y enviando ese objeto al informe. Este método le permite crear
recursos compartidos de conexión en la aplicación y filtrar los datos antes de
que Crystal Reports los reciba.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 117

3 DISEÑO DE INFORMES
Los informes se crean en el Diseñador de Crystal Report. El Diseñador de
Crystal Report se inicia automáticamente al añadir un objeto de Crystal Reports
al proyecto o al hacer doble clic en un objeto de Crystal Reports existente en el
proyecto.

CONEXIÓN DE LA BASE DE DATOS


En Crystal Report Designer, seleccione primero el origen de datos al que hará
referencia el informe. Puede utilizar varios orígenes de datos en un informe.

A continuación, seleccione las tablas de la base de datos que desee utilizar


en el informe. Crystal Reports puede vincular las tablas automáticamente, o
bien puede especificar el modo en el que desea vincularlas. Las tablas de
bases de datos se vinculan para que los registros de una base de datos
coincidan con los registros relacionados de otra tabla.

3.2 OBJETOS DE INFORMES


Crystal Report Designer utiliza una funcionalidad de arrastrar y colocar
parecida a la que se utiliza en Visual Studio .NET, se arrastra un objeto de
informe hasta el diseñador (como un campo de base de datos o un objeto de
texto) y se utiliza la ventana Propiedades o el menú contextual para dar
formato al objeto.
Algunos de los objetos de informe que puede añadir al informe y a los que
puede dar formato según las necesidades incluyen:

• Campos de base de datos.


• Campos de fórmula.
• Campos de parámetro.
• Campos de nombre de grupo.
• Campos de total acumulado.
• Campos de resumen.
• Gráficos.
• Subinformes.

3.3 SECCIONES DE INFORMES


Crystal Report Designer está dividido en secciones de informe, como los
encabezados de las secciones, los pies de página y los detalles. Los objetos
se arrastran a una sección de informe.

Los datos que aparecen en el informe finalizado dependen de las opciones de


organización. En particular, los datos del informe varían según las secciones
en las que desee insertar objetos de informe concretos. Por ejemplo, si
inserta un objeto de gráfico en la sección Encabezado de informe, el gráfico
sólo aparecerá una vez al principio del informe y resumirá los datos que
contiene el informe. Además, si un objeto de gráfico se añade a la sección
Encabezado de grupo, aparecerá un gráfico individual al principio de cada
grupo de datos y sólo se resumirán los datos relacionados con dicho grupo.

CIBERTEC CARRERAS PROFESIONALES


118

A continuación detallamos cada una de las secciones de un informe:

3.3.1 Encabezado de informe


Los objetos que se colocan en el Encabezado de informe se imprimen
una vez, al principio del informe.
Esta sección normalmente contiene el título del informe y la información
adicional que desea que aparezca sólo al principio del mismo.

• Los gráficos y las tablas cruzadas de esta sección contienen los


datos de todo el informe.
• Las fórmulas de esta sección se evalúan una vez, al principio del
informe.

3.3.2 Encabezado de página


Los objetos incluídos en la sección Encabezado de página se imprimen
al principio de cada nueva página.

Esta sección suele contener la información que desea que aparezca en


la parte superior de cada página. Puede incluir campos como el nombre
de un capítulo, de un documento o información similar. También se
puede utilizar para incluir títulos de campos, que aparecerán como
etiquetas sobre las columnas con los datos de los campos del informe.

• En esta sección no se pueden incluir gráficos ni tablas cruzadas.


• Las fórmulas que se colocan en esta sección se evalúan una vez por
página, al principio de cada página nueva.

3.3.3 Detalles
Los objetos colocados en la sección Detalles se imprimen con cada
registro nuevo.

Esta sección contiene los datos del cuerpo del informe. Aquí aparece la
mayor parte de los datos de éste. Cuando se ejecuta el informe, la
sección Detalles se vuelve a imprimir para cada registro. Por ejemplo, si
añade un objeto de base de datos con 100 registros a la sección
Detalles, el informe imprimirá 100 secciones de detalle individuales en
tiempo de ejecución.

• En esta sección no se pueden incluir gráficos ni tablas cruzadas.


• Las fórmulas incluidas aquí se evalúan una vez por cada registro.

3.3.4 Pie de informe


Los objetos que se colocan en el Pie de informe se imprimen una vez, al
final del informe.

Esta sección se utiliza para incluir la información que desea que sólo
aparezca una vez al final del informe, como los totales generales.

• Los gráficos y las tablas cruzadas de esta sección contienen los


datos de todo el informe.
• Las fórmulas de esta sección se evalúan una vez, al final del
informe.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 119

3.3.5 Pie de página


Los objetos colocados en la sección Pie de página se imprimen en la
parte inferior de cada página.

Normalmente, esta sección refleja el número de página, así como


cualquier otra información que desee que aparezca en la parte inferior
de las páginas.

• En esta sección no se pueden incluir gráficos ni tablas cruzadas.


• Las fórmulas de esta sección se evalúan una vez por página, al final
de cada una de ellas.

4 IMPLEMENTACION DEL CRYSTAL REPORT


Es necesario distribuir los archivos de informe (.rpt) cuando se implementa una
aplicación .NET. Puede elegir entre compilar los archivos de informe en la
aplicación o distribuirlos por separado.

4.1 Archivos de informe incrustados


Cuando se agregan informes a una aplicación Web o Windows .NET, éstos
se agregan de manera predeterminada como recurso incrustado de la
aplicación. Esto quiere decir que los archivos de informe se compilarán en el
manifiesto del ensamblado, no se cargarán desde otro archivo de informe
separado. La ventaja de los archivos de informe incrustados estriba en que
no es necesario distribuir archivos de informe externos y los usuarios finales
no pueden modificarlos.

4.2 Archivos de informe no incrustados


Los archivos de informe no incrustados son archivos de informe que no están
compilados en el ensamblado de una aplicación y se distribuyen
independientemente de ésta. Para evitar que los informes se compilen en el
manifiesto del ensamblado como un recurso incrustado, es necesario cambiar
la manera de agregar el informe al proyecto. Vea Archivos de informes para
obtener información sobre cómo hacer que los archivos de informe no sean
incrustables. Cuando se crea el proyecto, el informe no se compilará en el
ensamblado del proyecto y será necesario cargarlo por separado.

La ventaja de conservar los informes fuera del ensamblado es que, de esa


manera, se pueden modificar y volver a implementar sin tener que volver a
compilar e implementar toda la aplicación. La desventaja es que no se
pueden utilizar objetos de informe con tipos declarados en la aplicación y hay
que cargar los informes por separado.

5 IMPLEMENTACION DE INFORMES
Crystal Reports 10 funciona en una arquitectura de uno, dos o tres niveles tanto
en plataformas Windows Forms como Web Forms.

5.1 DESCRIPCION DE LOS NIVELES


Piense en estos niveles como en una progresión en términos de escalabilidad.
Una aplicación de un solo nivel requiere que todos los componentes de los
informes se instalen en el equipo del usuario y, además, el procesamiento
depende del equipo cliente. Una aplicación de tres niveles sólo necesita un

CIBERTEC CARRERAS PROFESIONALES


120

explorador en el equipo del usuario; la aplicación reside en un servidor Web y


obtiene acceso al servicio Web de informes a través de HTTP. Se pueden
centralizar los cambios realizados en la aplicación. Además, los cambios
realizados en el servicio Web de informes se reflejan de forma inmediata, ya
que la aplicación se comunica directamente con este servicio.

Nota: En estos casos, los niveles se definen en función de donde residan los
componentes o la arquitectura de Crystal Reports. El tipo de base de datos
que utiliza el informe también puede añadir un nivel adicional.

5.2 APLICACIONES DE UN SOLO NIVEL


Una aplicación de Windows que contiene un informe local se basa en un
método de un solo nivel en el que todos los componentes se instalan en el
equipo del usuario.

Los componentes de los informes, incluidos el archivo del informe (archivo .rpt)
y el motor de informes, se instalan con el archivo ejecutable en el equipo del
usuario.

Escalabilidad
Las aplicaciones de Windows con informes locales son las más adecuadas
para una implementación a pequeña escala, ya que la aplicación se instala en
el equipo del usuario. Si depende mucho del proceso del cliente, no dude en
optar por esta opción.
Si hay que realizar cambios en el informe, se debe volver a instalar la
aplicación en el equipo del usuario.

5.3 APLICACIONES DE DOS NIVELES


Si desarrolla una aplicación Web que albergue un informe local (archivo .rpt),
el procesamiento se basa en una relación de dos niveles en la que el servidor
Web gestiona los eventos que tienen lugar en el cliente.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 121

Escalabilidad
Los usuarios sólo necesitan tener un explorador en el equipo. Todos los
componentes de informes residen en el servidor y se pueden actualizar de
forma centralizada.

5.4 APLICACIONES DE TRES NIVELES


Un servicio Web de informes es un informe Crystal que se ha publicado o se
ha mostrado para que lo utilice una aplicación. En Internet, una aplicación de
Windows puede conectarse con un servicio Web de informes, utilizar el
informe Crystal mostrado y presentar el informe a los usuarios almacenándolo
en un visor de formularios.

Puede utilizar un servicio Web de informes que forme parte de la arquitectura u


obtener acceso a un servicio Web de informes que forme parte de otra
arquitectura, como podría ser la arquitectura de un socio comercial.

Escalabilidad
Dependiendo del tipo de aplicación, los usuarios sólo necesitan un Visor de
Windows Forms o un explorador Web para ver los servicios Web de informes.
El resto de los componentes de los informes reside con el servicio Web de
informes en un servidor remoto. Los cambios realizados en el servicio Web de
informes se reflejan de forma inmediata en la aplicación.

CIBERTEC CARRERAS PROFESIONALES


122

LABORATORIO 9.1
MANEJO DE REPORTE SIMPLE CON CRYSTAL REPORT
En el ejemplo siguiente se muestra el listado de los pedidos registrados (tabla
tb_pedidoscabe) en la base de datos utilizando el Crystal Report.

1. Ingrese a Visual Studio 2005.


2. Seleccione File->New->Project.
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “WindowsApplication”.
- En “Name” coloque “appReportes”.
- En “Location” coloque “C:\CursoPOOII”.
4. Defina un DataSet para definir el tablaAdapter tb_pedidoscabe.

TableAdapter
tb_pedidoscabe

5. Agrega en la aplicación un nuevo elemento de


tipo Crystal Report, el cual se llamará
rptPedidos, luego presionar el botón Agregar.

Selecciona el elemento
Crystal Report

Asigna un nombre al
elemento: RptReportes

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 123

6. Cuando se configura por


primera vez, aparece una
licencia. Presiona el botón
Acepto el Contrato de
licencia y luego Aceptar.

Presiona el botón
Aceptar contrato, para
continuar con el
proceso de diseño.

7. A continuación se visualiza la
Galeria de Crystal Report para el
diseño de un Reporte. Selecciona la
opción Usar asistente de informes
y el tipo de asistente es Estándar,
presione el botón Aceptar.

8. El asistente muestra la
ventana DATOS que
permite seleccionar
desde un origen de
datos: ADO.NET
DataSets el
tableAdapter
tb_pedidoscabe.
Agregarlo a las Tablas
Seleccionada y presione
TableAdapter
el botón Siguiente>
tb_pedidoscabe

CIBERTEC CARRERAS PROFESIONALES


124

9. En la ventana
Campos, debe
seleccionar las áreas
que conforma el
reporte, tal como se
muestra en la figura.
Para terminar
presione el botón
Finalizar.

Campos que se
visualizan en el
reporte.

10. Al finalizar el diseño del reporte, se visualiza el archivo de Crystal Report


RptReportes.rpt.
Sección
encabezado
de informe.

Sección
encabezado
de página.

Sección
Detalles: los
campos.

Sección pie
de página.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 125

11. En el Formulario agrega el control CrystalReportViewer para listar el reporte


diseñado, tal como se muestra en la figura.

12. Codifique el proceso para visualizar el reporte en el Formulario.

Defina la instancia
ds de DataSet1 y el
tableAdapter de
pedidos para poblar
los registros al
DataSet1 ds.

Defina la instancia rp
de RptReportes y
asignar como origen
de datos al DataSet1
ds.

Defina la propiedad
ReportSource del
control a rp.

13. Ejecute la aplicación.

CIBERTEC CARRERAS PROFESIONALES


126

LABORATORIO 6.2
MANEJO DE REPORTE CON PARAMETROS CON CRYSTAL
REPORT
En el ejemplo siguiente se muestra el reporte de los pedidos al seleccionar un Cliente
desde un ComboBox. Utilice el TableAdapter para implementar el origen de datos.

1. Defina en el TableAdapter
tb_pedidoscabe un método
que liste los pedidos por un
cliente específico.

Agregue en el
TableAdapter
tb_pedidoscabe el
metodo que consulte los
pedidos por cliente.

2. En la ventana Sentencia SQL,


defina la condición para listar
los pedidos por cliente, tal
como se muestra en la figura.

Condicion para listar


los pedidos por
cliente.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 127

3. Asigna el nombre
al método:
FillByCliente

4. Diseña el
formulario:

Control
ComboBox1
para listar los
clientes.

Control
CrystalReport
Viewer para
mostrar el
reporte.

CIBERTEC CARRERAS PROFESIONALES


128

5. En la ventana de programación, defina la conexión y el proceso para configurar el


ComboBox1 con los datos de los clientes.

Conexión a la
base de datos.

Recuperar los
clientes en el
dataTable.

Configura el
combobox1 con
los clientes.

6. Codifica el botón Reporte para listar el reporte de pedidos por cliente seleccionado
en el control ComboBox1.
Defina la
instancia ds de
DataSet1 y el
tableAdapter de
pedidos para
poblar los
pedidos por
cliente al
DataSet1 ds.

Defina la
instancia rp de
RptReportes y
asignar como
origen de datos
al DataSet1 ds.

7. Ejecuta la aplicación, seleccione el cliente desde el ComboBox1, al presionar el


botón Reportes, se lista los pedidos por el cliente seleccionado.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 129

Autoevaluación

1. ¿Cuál es la importancia de desarrollar Reportes? Explique brevemente

2. ¿En qué tipos de plataformas se puede generar reportes?

3. Explique brevemente cada una de las secciones de un Reporte en Crystal


Report.

4. ¿Cuáles son las capas o niveles de programación donde se puede implementar


el Crystal Report? Explique brevemente cada uno de ellos.

5. Desarrolle un Formulario que permita listar los pedidos al seleccionar un mes y


año desde controles de selección.

6. Desarrolle un Formulario que permita visualizar un cuadro estadístico de barras


de los pedidos realizados por cada año.

CIBERTEC CARRERAS PROFESIONALES


130

Resumen

 En Visual Studio .NET, se puede crear un nuevo informe Crystal o agregar uno
existente a un proyecto. Puede guardar el informe en un equipo local o publicarlo
como servicio Web en un servidor Web.

 Crystal Reports se conecta a bases de datos mediante controladores de bases de


datos. Cada controlador se escribe para controlar un tipo de base de datos
específico o la tecnología de acceso a bases de datos.

 En un modelo de extracción, el controlador se conectará a la base de datos y


extraerá éstos cuando se necesiten. En el modelo de inserción necesita que el
programador escriba código para conectarse a la base de datos, ejecutando un
comando SQL para crear un conjunto de registros o de datos que se ajusten a los
campos del informe y enviando ese objeto al informe.

 Una aplicación de Windows que contiene un informe local se basa en un método


de un solo nivel en el que todos los componentes se instalan en el equipo del
usuario. Los componentes de los informes, incluidos el archivo del informe (archivo
.rpt) y el motor de informes, se instalan con el archivo ejecutable en el equipo del
usuario.

 Una aplicación de dos niveles o Web, alberga un informe local (archivo .rpt), el
procesamiento se basa en una relación de dos niveles en la que el servidor Web
gestiona los eventos que tienen lugar en el cliente.

 Una aplicación de “n” niveles represente un servicio Web de informes es un


informe Crystal que se ha publicado o se ha mostrado para que lo utilice una
aplicación. En Internet, una aplicación de Windows puede conectarse con un
servicio Web de informes, utilizar el informe Crystal mostrado y presentar el
informe a los usuarios almacenándolo en un visor de formularios.s.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://www.willydev.net/CrystalDesde0
Página que permite crear un reporte desde cero

 http://rs10.rapidshare.com/files/20840690/Manual_de_Crystal_Reports.rar
Permite descargar el manual del Crystal Report

 www.mygnet.net/manuales/crystalreport//manual_completo_crystal_repor
t10.945
Página que permite descargar el manual del Crystal Report

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 131

UNIDAD DE
APRENDIZAJE

4
SEMANA

10

MODELO RELACIONAL DE OBJETOS

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET utilizan una
plataforma de acceso a datos, para mapear un modelo conceptual de tipo entidad-relación
apoyándonos en un entorno visual integrado con Visual Studio, y realizar consultas a través
del nuevo lenguaje de consultas integrado.

TEMARIO

• Modelo Relacional de Objetos, introducción.

• LINQ: arquitectura, DataContext.

• Consultas y actualización de datos utilizando LINQ to SQL.

• ADO.NET Entity FrameWork.

• Acceso a datos utilizando EntityClient Provider; administración de los objetos Entity:


EntityConnection, EntityCommand, EntityDataReader, EntityTransaction.

• Acceso a datos utilizando Servicios de Objetos y LINQ to Entity.

ACTIVIDADES PROPUESTAS

• Los alumnos conocen las plataformas de acceso a datos del ADO.NET.

• Los alumnos realizan operaciones de consultas utilizando el modelo de clases


LINQ to SQL.

• Los alumnos realizan operaciones de consultas y actualizacion utilizando el modelo


de clases LINQ to SQL.

CIBERTEC CARRERAS PROFESIONALES


132

1 MODELO RELACIONAL DE OBJETOS


La visión sobre el acceso a datos de Microsoft soporta una familia de productos y
servicios para que los clientes obtengan valor de todos los datos, desde su
nacimiento hasta su archivo. Una plataforma de datos tan completa debe tener
las siguientes características:

• Datos en todas las capas. Una plataforma de datos completa ofrece gestión
de datos y acceso a servicios de datos en cualquier lugar.
• Datos de todos los tipos. La visión de acceso a datos de Microsoft concibe un
almacén integrado capaz de almacenar y gestionar datos de todos esos tipos,
garantizar su seguridad, permitir búsquedas y consultas sobre ellos,
analizarlos, consultarlos, sincronizarlos, etc.
• Acceso a datos uniforme. Aunque las aplicaciones en diferentes capas
requieren diferentes clases de gestión de los servicios de datos, todas esperan
(requieren) una uniformidad significativa en lo relativo al entorno de desarrollo
de aplicaciones (modelos de programación y herramientas).
• Visión completa del negocio. Gira alrededor de la tecnología que puede
permitir a nuestros clientes recoger, limpiar, almacenar y preparar sus datos de
negocio para el proceso de toma de decisiones. Gira también alrededor de las
experiencias que los Usuarios del Negocio y los Trabajadores de la Información
tendrán al acceder, analizar, visualizar y generar informes a partir de los datos
mientras recopilan la información necesaria para sus decisiones.
• Servicios de datos en todos los sitios. Las aplicaciones invierten un
esfuerzo significativo en el desarrollo de servicios como la seguridad de datos,
la sincronización, la seriación para el intercambio de datos (o para servicios
Web), análisis y generación de informes a partir de los datos en todas las
capas, sobre abstracciones que sean cercanas a la perspectiva de las
aplicaciones.

1.1 MODELO CONCEPTUAL DE OBJETOS: LINQ Y ADO.NET ENTITIES


El exponer vistas de cliente a través de un Proveedor de Datos ADO.NET
permite mantener el modelo de programación familiar de ADO.NET,
aprovechando la inversión en código, herramientas y conocimiento existente y
dicho proveedor pasa a formar parte del popular conjunto de Proveedores de
Datos disponibles.
1.1.1 ADO.NET Entities: aprovecha la inversión realizada en ADO.NET
agregándole la habilidad de escribir aplicaciones contra un esquema
conceptual enriquecido llamado "Entity Data Model", en lugar de utilizar
un esquema relacional de base de datos. El Entity Data Model (EDM)
extiende el modelo de datos relacional con Entity-Relationships (ER)
para modelar conceptos del mundo real como Herencia (autos y
camiones son vehículos), Relaciones (los clientes tienen órdenes), y
miembros complejos (calle, ciudad, región y código postal compuestos
como una sola propiedad "dirección" de un cliente).
1.1.2 LINQ: "Language INtegrated Query" y, como su nombre lo indica,
integra conceptos de consultas directamente en los lenguajes de
programación, permitiendo que el código de acceso a datos sea
verificado por el compilador y las herramientas de desarrollador, como
Intellisense para hacer que los desarrolladores escriban queries. Esto,
junto con conceptos de modelos conceptuales (como Entidades),
contribuye a reducir el abismo entre aplicaciones y datos.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 133

2 MODELO DE OBJETOS: LINQ


Hablando más formalmente, LINQ es una combinación de extensiones a los
lenguajes y librerías de código manejado que permiten expresar de manera
uniforme y extensible las consultas sobre secuencias de datos provenientes de
las más disímiles fuentes.

2.1 VENTAJAS QUE APORTA LINQ A LA PROGRAMACION


• Reduce las diferencias entre los modelos que proponen los lenguajes de
propósito general (hoy orientados a objetos) y los que ofrecen los lenguajes
de consulta específicos a fuentes de datos: SQL o XPath/XQuery.
En particular, los proveedores LINQ se encargan de generar las sentencias
SQL a partir de las expresiones de consulta que utilicemos en nuestros
programas.
• LINQ permite elevar el nivel de abstracción y claridad de la programación, es
decir, indicamos únicamente qué se desea obtener, dejando a un motor de
evaluación de expresiones los detalles sobre cómo lograr ese objetivo.
• A la hora de expresar sus consultas, el programador podrá aprovechar todas
las facilidades que el compilador y el entorno integrado ofrecen, con
importantes beneficios para la productividad. Las ventajas aquí son de dos
tipos diferentes:
 Seguridad mejorada, gracias a la verificación de sintaxis y de
tipos por parte de los compiladores.
 Disponibilidad de ayuda IntelliSense dentro de Visual Studio
2008 u otros entornos de desarrollo.

2.2 PROVEEDORES LINQ PREDEFINIDOS


En función de la fuente de datos que se desee consultar, el programador
deberá “enchufar” el proveedor correspondiente, agregando una referencia al
ensamblado en el que dicho proveedor está implementado. La tabla de la figura
3 lista los proveedores LINQ incorporados “de serie” a .NET Framework 3.5:
• LINQ to Objects, para consultar arrays y colecciones de objetos en
memoria.
• LINQ to XML, para consultar y actualizar documentos XML.
• LINQ to DataSets, para consultar y actualizar conjuntos de datos.
• LINQ to SQL y LINQ to Entities, para consultar y actualizar bases de datos
relacionales.

CIBERTEC CARRERAS PROFESIONALES


134

3 LINQ to SQL
LINQ To SQL es el componente específico de LINQ que proporciona la
infraestructura de runtime necesaria para utilizar datos relacionales como objetos y
poder definir consultas sobre dichos objetos, es decir, habilita la consulta de
contenedores de datos relacionales sin tener que abandonar la sintaxis o el
entorno de tiempo de compilación. Para hacer posible esto, LINQ To SQL se
apoya en las siguientes características clave:
• Las innovaciones del lenguaje (C# 3.0 y VB 9.0), así como en las
características propias de LINQ (consultas integradas en el lenguaje).
• Mapping del esquema de la BD en clases, propiedades, métodos, etc. La
correspondencia que LINQ To SQL hace entre los elementos de un esquema
de una BD y los elementos correspondientes a nivel del CLR es el siguiente:

• Persistencia, que habilita el control automático de cambios en la BD, y la


actualización de datos a través de sentencias T-SQL.
• Integración de la información del esquema de la BD en metadatos del
CLR, las tablas se tratan como colecciones, los datos (columnas) son descritos
en clases, la conexión a la BD y los resultados están tipados, etc.

En la práctica, LINQ To SQL provee de los mecanismos necesarios para


encapsular y utilizar en nuestras aplicaciones la definición (completa o no) de un
cierto esquema relacional, y poder definir consultas LINQ sobre las clases
mapeadas. El esquema de la arquitectura de LINQ To SQL nos permitirá
comprender mejor las ideas expuestas:

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 135

3.1 MODELANDO UNA BASE DE DATOS CON LINQ to SQL


Visual Studio 2008 viene con un diseñador de LINQ to SQL que nos aporta
una forma fácil de modelar y visualizar una base de datos como un modelo de
objeto de LINQ to SQL: DataContext y las Clases Entitities.

3.1.1 DataContext es el encargado de hacer la interface entre las entidades


que son representadas y el programa. Es el origen de todas las
entidades asignadas en una conexión de base de datos. Realiza un
seguimiento de los cambios realizados en todas las entidades
recuperadas y mantiene una "memoria caché de identidad" que
garantiza que las entidades que se recuperan más de una vez se
representan utilizando la misma instancia de objeto.

3.1.2 CLASE ENTIDAD (ENTITY CLASS) LINQ to SQL nos permite modelar
clases que mapeen una base de datos. Estas clases son típicamente
conocidas como “Clases Entidad” y a las instancias se las conoce como
“Entidades”. Las clases entidad mapean a tablas de una base de datos.
Las propiedades de una clase entidad normalmente mapean las
columnas de la tabla. Cada instancia de una clase entidad representa a
una fila de una tabla de la base de datos.

Las clases entidad definidas por LINQ to SQL no tienen que derivar de
una clase base específica, lo que significa que pueden heredar de
cualquier objeto que queramos. Todas las clases creadas por el
diseñador de LINQ to SQL se definen como “clases parciales” con lo que
podemos, opcionalmente, añadir propiedades adicionales, métodos y
eventos.

CIBERTEC CARRERAS PROFESIONALES


136

3.2 CONSULTANDO LA BASE DE DATOS CON LINQ to SQL


Una vez que tenemos definido nuestras clases del modelo de datos,
podemos consultar y obtener fácilmente datos de nuestra base de datos.
LINQ to SQL nos permite esto usando la sintáxis de consultas de LINQ sobre
la clase DataContext que creamos con el diseñador LINQ to SQL.

En la selección, basta con que escriba una consulta LINQ en su propio


lenguaje de programación y, después, la ejecuta para recuperar los
resultados. LINQ to SQL convierte todas las operaciones necesaria en las
operaciones SQL con las que está familiarizado.

Por ejemplo: listar los clientes y visualizarlos en el DataGridView.

Dim db As New DataDBVentasDataContext


Dim cliente = From c In db.tb_clientes
Me.DataGridView1.DataSource = cliente

Una de las cosas que nos aporta LINQ to SQL es que nos da una total
flexibilidad en cómo consultar nuestros datos, y podemos aprovecharnos de
las asociaciones que hicimos cuando modelamos las clases de LINQ to SQL
para hacer consultas más naturales y ricas sobre la base de datos.

3.3 ACTUALIZANDO LA BASE DE DATOS CON LINQ to SQL


Cuando definimos nuestro modelo de datos, el diseñador LINQ to SQL creó
una clase llamada DataContext que proporciona todo lo necesario para poder
consultar/actualizar la base de datos.

Cuando creamos consultas y obtenemos objetos, LINQ to SQL estará


pendiente de los cambios o actualizaciones que les hagamos a los objetos.
Podemos hacer tantas consultas y cambios como queramos usando la clase
DataContext de LINQ to SQL, sabiendo que dichos cambios serán
supervisados a la vez.

El seguimiento de cambios de LINQ to SQL ocurre en el lado del


consumidor - y NO en la base de datos. Es decir, no estamos
consumiendo ningún recurso de la base de datos mientras lo
usemos, tampoco tenemos que cambiar/instalar nada en la base
de datos para que esto funcione.

Después de realizar los cambios que queramos a los objetos que hemos
obtenido con LINQ to SQL, podemos llamar al método “SubmitChanges()”
de nuestro DataContext para guardar los cambios en nuestra base de datos.
Con esto, LINQ to SQL, creara y ejecutará las sentencias SQL apropiadas
para actualizar la base de datos.

Cuando llamamos al método SubmitChanges(), LINQ to SQL crea y ejecuta


las sentencias UPDATE de SQL necesarias para modificar los productos a
los que hemos modificado la propiedad ReorderLevel.

3.3.1 Añadiendo un registro


Podemos añadir un producto a la base de datos creando un nuevo
objeto, inicializando sus propiedades y añadirlo a la colección de
nuestro DataContext.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 137

Cuando llamemos a SubmitChanges() se añadirá una nueva fila


en la tabla de clientes.
En el ejemplo siguiente agregue un nuevo cliente a la tabla
tb_clientes utilizando el método InsertOnSubmit.

Dim cliente As New tb_clientes


cliente.IdCliente = TXTCODIGO.Text
cliente.NombreCia = TXTNOMBRE.Text
cliente.Direccion = TXTDIRECCION.Text
cliente.idpais = ComboBox1.SelectedValue
cliente.Telefono = TXTFONO.Text
Data.tb_clientes.InsertOnSubmit(cliente)
Data.SubmitChanges()

3.3.2 Eliminando registros


De la misma forma que añadimos un nuevo registro a la base de datos
añadiendo un objeto a la colección del DataContext, también podemos
borrar productos borrándolos de esa misma colección:

En el ejemplo siguiente, recupera el cliente cuyo IDCliente es


98128. A continuación se llama a DeleteOnSubmit para quitar ese
objeto de la colección. Finalmente, se llama a SubmitChanges
para transmitir la eliminación a la base de datos.

Dim cliente = From cli In Data.tb_clientes _


Where cli.IdCliente = “98128” Select cli
Data.tb_clientes.DeleteOnSubmit(cliente.First)
Data.SubmitChanges()

3.3.3 Actualizando registros


Para realizar una operación Update en una entrada de base de datos,
primero recupere el elemento y modifíquelo directamente en el modelo
de objetos. Después de haber modificado el objeto, llame a
SubmitChanges en DataContext para actualizar la base de datos.
En el ejemplo siguiente recupere el cliente cuyo IdCliente es
“ALFKI”. A continuación, la direccion se cambia a "London -
Metro". Finalmente, se llama a SubmitChanges.

Dim cliente = From cli In Data.tb_clientes Where


cli.IdCliente = “ALFKI”Select cli
Dim updatecliente As New tb_clientes
updatecliente = cliente.FirstOrDefault
updatecliente.Direccion = "London - Metro"
Data.SubmitChanges()

3.4 OBTENER DATOS CON PROCEDIMIENTOS ALMACENADOS


LINQ to SQL es muy flexible, y puede usare para crear un modelo de datos
cuyos objetos sean independientes del esquema de la base de datos, y
puede encapsular lógica de negocio que funcionan tanto si se usa SQL
generado dinámicamente o a través de procedimientos almacenados.
LINQ to SQL puede mapear procedimientos almacenados con la clase
DataContext que nos permitirá obtener los mismos objetos llamando a un
procedimiento almacenado.

CIBERTEC CARRERAS PROFESIONALES


138

3.4.1 Pasos para mapear un procedimiento almacenado en LINQ to SQL.


a) Abra la ventana explorador de servidores de VS 2008 y miramos a
los procedimientos almacenados de nuestra base de datos.
b) Arrastre y suelte desde el explorador de servidores al diseñador de
LINQ to SQL. Automáticamente se creará un nuevo método en la
clase DataContext.

Métodos:
Procedimientos
almacenados

3.4.2 Llamada de un procedimiento almacenados


Una vez que hemos seguido los pasos para mapear el procedimiento
almacenado en la clase DataContext, es muy fácil de usar. Todo lo que
tenemos que hacer es llamarlo para obtener los resultados.

En el ejemplo siguiente ejecute el procedimiento almacenado


usp_clientes y visualice los resultados en un control
DataGridView1.

Dim data As New DataVentasDataContext


Me.DataGridView1.DataSource = data.usp_Clientes

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 139

LABORATORIO 10.1
CONSULTA DE PEDIDOS POR CLIENTE Y AÑO
En este escenario vamos a listar los pedidos por un cliente y año, el cual seleccione un
cliente desde un ComboBox e ingrese el año desde el control TextBox y al presionar el
botón Consulta visualice los pedidos por cliente seleccionado y año ingresado.
1. Ingrese a Visual Studio 2005.
2. Seleccione File->New->Project.
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “Windows Application”.
- En “Name” coloque “appLINQ”.
- En “Location” coloque “C:\CursoPOOII”.
4. Agregue un nuevo elemento en el proyecto de Windows; seleccione la plantilla
Clases de LINQ to SQL; asigne el nombre DataVentas.dbml.

Seleccione la plantilla
para el manejo de las
tablas como clases.

5. Desde el explorador de
servidor arrastre las
tablas hacia el
diseñador llamado
DataVentas.dbml y
establecer la
asociación entre las
tablas tb_clientes y
tb_pedidoscabe, tal
como se muestra.

6. Sobre el Form1.vb, cree la siguiente interfase de usuario:

CIBERTEC CARRERAS PROFESIONALES


140

Control Nombre Propiedad Valor


Button1 BtnConsulta Text Consulta
Label1 Label1 Text Consulta de Pedidos por Cliente y
Año
Label2 Label2 Text Cliente
Label3 Label3 Text Año
ComboBox ComboBox1
TextBox txtAño
DataGridView DataGridView1

7. En la ventana de código, defina la instancia de DataVentasDataContext a nivel


Formulario.

Private Data As New DataVentasDataContext

8. En el evento Load del Formulario, defina una variable clientes que almacene
los registros de la tabla tb_clientes para enlazar al control ComboBox1.

Dim cliente = From cli In Data.tb_clientes

Me.ComboBox1.DataSource = cliente
Me.ComboBox1.DisplayMember = "NombreCia"
Me.ComboBox1.ValueMember = "IdCliente"

9. En el evento Click del button BtnConsulta, declare la variable pedidos para


realizar la consulta de “pedidos” por el cliente y año.

Dim pedidos = From pedido In Data.tb_pedidoscabe _


Where pedido.IdCliente = ComboBox1.SelectedValue.ToString
And pedido.FechaPedido.Year=Val(TXTAÑO.Text) Select pedido

Me.DataGridView1.DataSource = pedidos

10. Guarda la aplicación y ejecute. Al seleccionar un cliente e ingresar el año


desde el TextBox listaremos los pedidos del cliente y año.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 141

LABORATORIO 10.2
CONSULTA DE PEDIDOS POR EMPLEADOS ENTRE FECHAS
En este escenario vamos a listar los pedidos por un empleado entre dos fechas, donde
al seleccionar un empleado desde un ComboBox e ingrese dos fechas desde controles
TextBoxes y al presionar el botón Consulta visualice los pedidos por empleado
seleccionado y entre dos fechas.

1. En el DataContext DataVentasDataContext agregue la tabla tb_empleados.


2. En el proyecto appLINQ, agregue un formulario;dibuje la siguiente interfaz:

Control Nombre Propiedad Valor


Button BtnConsulta Text Consulta
Label Label1 Text Consulta de Pedidos por
Empleado
Label Label2 Text Empleado
Label Label3 Text Fecha 1
Label Label4 Text Fecha2
ComboBox ComboBox1
TextBox txtFecha1
TextBox txtFecha2
DataGridView DataGridView1
3. En la ventana de código, defina la instancia de DataVentasDataContext a nivel
Formulario.
Private Data As New DataVentasDataContext

4. En el evento Load del Formulario, defina una variable empleado que


almacene los registros de la tabla tb_empleados para enlazar al control
ComboBox1.
Dim empleado = From emp In Data.tb_empleados
Me.ComboBox1.DataSource = empleado
Me.ComboBox1.DisplayMember = "Nombre"
Me.ComboBox1.ValueMember = "Idempleado"

5. En el evento Click del button BtnConsulta, declare la variable pedidos para


realizar la consulta de “pedidos” por el empleado entre dos fechas.

Dim pedidos = From pedido In Data.tb_pedidoscabe _


Where pedido.IdEmpleado = ComboBox1.SelectedValue.ToString
And pedido.FechaPedido >= CDate(TXTFECHA1.Text) And
pedido.FechaPedido <= CDate(TXTFECHA2.Text
Me.DataGridView1.DataSource = pedidos

CIBERTEC CARRERAS PROFESIONALES


142

6. Guarda la aplicación y ejecute. Al seleccionar un empleado e ingresar las


fechas desde los controles TextBoxes listaremos los pedidos del empleado
entre dos fechas.

LABORATORIO 10.3
ACTUALIZACION DE CLIENTES UTILIZANDO LINQ to SQL
En este escenario vamos a actualizar los clientes utilizando LINQ to SQL; para esto
vamos a programar las operaciones de Agregar un clientes, modificar los datos de un
cliente y eliminar un registro de cliente por su código utilizando el modelo de objetos
LINQ to SQL.

1. En el DataContext
DataVentas agregue
la tabla tb_paises y
establezca la
asociación en la tabla
tb_clientes.

2. En el proyecto appLINQ, agregue un formulario;dibuje la siguiente interfaz:

3. En la ventana de código, defina la instancia de DataVentasDataContext a nivel


Formulario.
Private Data As New DataVentasDataContext

4. En la ventana de código, defina el procedimiento Clientes para listar los


clientes y visualizarlos en el DataGridView1.

Sub Clientes()
Dim clientes = From cliente In Data.tb_clientes
Me.DataGridView1.DataSource = clientes
End Sub

5. En el evento Load del Formulario, listar los países en el control ComboBox1 y


listar los clientes en el DataGridView.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 143

Dim paises = From pais In Data.tb_paises


Me.ComboBox1.DataSource = paises
Me.ComboBox1.DisplayMember = "NombrePais"
Me.ComboBox1.ValueMember = "IdPais"
'Cargar los clientes en el DataGrid
Clientes()

6. Codifique el evento Click del botón Agregar para insertar un registro a la tabla
tb_clientes y actualizando a la base de datos.
'instancia de la clase tb_clientes
Dim cliente As New tb_clientes
cliente.IdCliente = TXTCODIGO.Text
cliente.NombreCia = TXTNOMBRE.Text
cliente.Direccion = TXTDIRECCION.Text
cliente.idpais = ComboBox1.SelectedValue
cliente.Telefono = TXTFONO.Text
'agrega el cliente a la clase y actualiza a la base de datos
Data.tb_clientes.InsertOnSubmit(cliente)
Data.SubmitChanges()
'listar los clientes
Clientes()

7. Codifique el evento Click del botón Modificar, para actualizar los datos de un
cliente seleccionado y actualizando a la base de datos.

Dim cliente = From cli In Data.tb_clientes Where _


cli.IdCliente = TXTCODIGO.Text Select cli
'si no existe, salir del procedimiento
If cliente.Count = 0 Then Exit Sub
Dim updatecliente As New tb_clientes
updatecliente = cliente.FirstOrDefault
updatecliente.IdCliente = TXTCODIGO.Text
updatecliente.NombreCia = TXTNOMBRE.Text
updatecliente.Direccion = TXTDIRECCION.Text
updatecliente.idpais = ComboBox1.SelectedValue.ToString
updatecliente.Telefono = TXTFONO.Text
Data.SubmitChanges()
'listar los clientes
Clientes()

8. Codifique el evento Click del botón Eliminar para eliminar un cliente por su
código y actualizando la base de datos.
Dim cliente = From cli In Data.tb_clientes _
Where cli.IdCliente = TXTCODIGO.Text Select cli
If cliente.Count = 1 Then
'eliminar el primero objeto de los clientes
Data.tb_clientes.DeleteOnSubmit(cliente.First)
Data.SubmitChanges()
'listar loc clientes
Clientes()
End If

9. Guarde y ejecute el programa para realizar la actualización de los clientes.

CIBERTEC CARRERAS PROFESIONALES


144

LABORATORIO 10.4
CONSULTA DE PEDIDOS ENTRE FECHAS CON
PROCEDIMIENTOS ALMACENADOS Y LINQ to SQL
En este escenario vamos ejecutar un procedimiento almacenado donde liste los
pedidos entre fechas. Para ello, definimos el procedimiento almacenado y agregamos
el procedimiento como método al DataContext.

1. En el DataContext DataVentas agregue el procedimiento almacenado


usp_pedidos_fecha, tal como se muestra.

Procedimiento
almacenado
usp_pedidos_Fecha
agregado como método.

2. En el proyecto agregue el formulario para ejecutar la consulta.

3. Codifique el evento Click del botón Consulta, donde se ejecuta el método


usp_pedidos_Fechas al ingresar las fechas.
Dim data As New DataVentasDataContext
Dim f1 As Date = CDate(TXTFECHA1.Text)
Dim f2 As Date = CDate(TXTFECHA2.Text)
Me.DataGridView1.DataSource = data.usp_pedidos_Fechas(f1, f2)

4. Guarde y ejecute el formulario, ingresa dos fechas, al presionar el botón


Consulta, listamos los pedidos entre las fechas.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 145

Autoevaluación

1. ¿Qué es el modelo relacional de Objetos?


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

2. Explique el modelo LINQ.


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

3. ¿Cuáles son los proveedores de LINQ?


_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

4. Explique el objeto DataContext y la clase Entity.

_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________

5. Implemente un Programa que permita el ingreso o actualización de


empleados a la base de datos. En esta aplicación se deberá
desarrollar los siguientes procesos:
• Ingresar los datos del usuario e ingresar la imagen: opcional.
• Actualizar los datos de los usuarios donde se procederá a
actualizar su imagen, en caso de no tener agregar la imagen.

CIBERTEC CARRERAS PROFESIONALES


146

Resumen

 LINQ es una combinación de extensiones a los lenguajes y librerías de código


manejado que permiten expresar de manera uniforme y extensible las consultas
sobre secuencias de datos provenientes de las más disímiles fuentes.

 La tabla de los proveedores LINQ incorporados “de serie” a .NET Framework 3.5:
o LINQ to Objects, para consultar arrays y colecciones de objetos en memoria.
o LINQ to XML, para consultar y actualizar documentos XML.
o LINQ to DataSets, para consultar y actualizar conjuntos de datos.
o LINQ to SQL y LINQ to Entities, para consultar y actualizar bases de datos
relacionales.

 LINQ To SQL es el componente específico de LINQ que proporciona la


infraestructura de runtime necesaria para utilizar datos relacionales como objetos y
poder definir consultas sobre dichos objetos, es decir, habilita la consulta de
contenedores de datos relacionales sin tener que abandonar la sintaxis o el
entorno de tiempo de compilación.

 El diseñador de LINQ to SQL nos aporta una forma fácil de modelar y visualizar
una base de datos como un modelo de objeto de LINQ to SQL: DataContext y las
Clases Entitities.

 El DataContext es el origen de todas las entidades asignadas en una conexión de


base de datos. Realiza un seguimiento de los cambios realizados en todas las
entidades recuperadas y mantiene una "memoria caché de identidad" que
garantiza que las entidades que se recuperan más de una vez se representan
utilizando la misma instancia de objeto.

 Las clases entidad mapean a tablas de una base de datos. Las propiedades de
una clase entidad normalmente mapean las columnas de la tabla. Cada instancia
de una clase entidad representa a una fila de una tabla de la base de datos.

 http://msguayaquil.com/blogs/julioc/archive/2007/07/27/la-evoluci-243-n-
de-las-apis-de-acceso-a-datos-de-microsoft-parte-ii.aspx
Página referente a la evolución de APIs: LINQ

 http://thinkingindotnet.wordpress.com/2007/07/13/linq-to-sql-4%c2%aa-
parte-actualizando-la-base-de-datos/
Página referente a la actualización de datos utilizando LINQ to SQL

 http://thinkingindotnet.wordpress.com/2007/08/17/linq-to-sql-parte-6-
obtener-datos-con-procedimientos-almacenados/
Página referente al manejo de procedimientos almacenado en LINQ to
SQL

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 147

UNIDAD DE
APRENDIZAJE

4
SEMANA

11

ADO.NET ENTITY FRAMEWORK


LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET utilizan una
plataforma de acceso a datos, para mapear un modelo conceptual de tipo entidad-relación
apoyándonos en un entorno visual integrado con Visual Studio, y realizar consultas a través
del nuevo lenguaje de consultas integrado.

TEMARIO

• Modelo Relacional de Objetos, introducción.

• LINQ: arquitectura, DataContext.

• Consultas y actualización de datos utilizando LINQ to SQL.

• ADO.NET Entity FrameWork.

• Acceso a datos utilizando EntityClient Provider; administración de los objetos Entity:


EntityConnection, EntityCommand, EntityDataReader, EntityTransaction.

• Acceso a datos utilizando Servicios de Objetos y LINQ to Entity

ACTIVIDADES PROPUESTAS

• Los alumnos conocen las plataformas a acceso a datos del ADO.NET Entity
FrameWork.

• Los alumnos realizan operaciones de acceso a datos utilizando EntityClient


Provider.

CIBERTEC CARRERAS PROFESIONALES


148

1 ¿QUÉ ES ADO.NET ENTITY FRAMEWORK?


Para definir al Entity Framework nos basaremos en una definición del modelo
entidad-relacion. En el modelo entidad-relacion tal y como lo conocemos,
tenemos que implementar un conjunto de clases que definen el modelo
conceptual de la base de datos y tenemos que definir la capa de acceso a datos,
de tal manera que sea esta la encargada de acceder a la base de datos y mapear
los datos en las clases creadas para tal efecto.

El Entity Framework nos permite trabajar con los objetos definidos a partir del
modelo de datos sin tener que preocuparnos de la capa de acceso a datos ya que
él se encarga automáticamente de su persistencia.

2 COMPONENTES DEL ADO.NET ENTITY FRAMEWORK


Entity Framework permite a los desarrolladores escribir menos código de acceso a
datos, reduce el mantenimiento, condensa la estructura de datos de forma más
manejable (y menos normalizada) y facilita la persistencia de los datos.

Entity Framework genera un modelo


conceptual para el que los
desarrolladores pueden escribir código.
Se puede interaccionar directamente un
nuevo proveedor de datos llamado
EntityClient y un nuevo lenguaje
(parecido a T-SQL) llamado Entity SQL.
EntityClient tiene un modelo parecido a
los objetos conocidos de ADO.NET,
usando objetos de EntityConnection y
EntityCommand para devolver un
DbDataReader.

Los Servicios del Objeto permite a los


desarrolladores sacar partido de las clases generadas del modelo conceptual
mediante un objeto ObjectQuery con Entity SQL o mediante LINQ to Entities.

3 MODELO DE DATOS DE ENTIDADES

El núcleo de Entity Framework se encuentra en sus modelos. Entity Framework


admite un modelo de almacén lógico que representa el esquema relacional de una
base de datos. La forma en la que una base de datos relacionales almacena los
datos suele ser distinta de la forma en la que una aplicación los usa.
Entity Framework llena el hueco entre los modelos usando una capa de
asignación. Por lo tanto, hay tres capas en el modelo de Entity Framework:
• Capa conceptual.- definida mediante un archivo .CSDL (Conceptual
Schema Definition Language, un archivo XML con información relativa a las
entidades del modelo), el cuál incluye las entidades y las relaciones tal y
como la capa de negocio de la aplicación las conoce.
• Capa de asignación.- definida con MSL (Mapping Schema Language),
establece el mapeo entre las entidades del modelo conceptual y sus
correspondencias con la BD.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 149

• Capa lógica.- definida con SSDL (Store Schema Definition Language), y


representa el esquema de la BD.

Entity Framework proporciona los medios para definir estas capas mediante los
archivos XML. Esto proporciona un nivel de abstracción que permite a los
desarrolladores programar para el modelo conceptual en lugar del modelo
relacional.

3.1 DEFINIENDO EN ENTITY DATA MODEL (EDM)


El primer paso para trabajar con ADO.NET Entity Framework pasa por crear
un modelo de entidades a partir de un cierto esquema de Base de Datos.
a) Añadir al proyecto un elemento de tipo ADO.NET Entity Data Model.

Selecciona la
plantilla ADO.NET
Entity Data Model.

b) Especificar la opción de generación del EDM (a partir de una BD o bien un


EDM vacío.
Selecciona
Generar desde
la base de datos
para trabajar una
base de datos.

CIBERTEC CARRERAS PROFESIONALES


150

c) Especificar la cadena de conexión a la BD (puede ser un archivo físico o


bien una instancia de SQL Server).

Conexión a la
base de datos del
app.config.

Nombre de la
conexión de
entidad a
almacenar en el
app.config.

d) Especificar que objetos de la BD queremos que formen de nuestro EDM


(en este caso, tablas y procedimientos almacenados).

Seleccione
las tablas o
procedures
de la base
de datos.

e) Al finalizar se construye el modelo de entidad de datos, tal como se


muestra en la figura: ModelVentas.edmx.

Modelo de
Entidades de
datos: EDM

Entidades
almacenadas en
el modelo EDM

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 151

f) En el archivo App.Config el asistente agrega la conexión a la base de datos


llamada “DBVentasEntities” cuyo NameSpace es System.Data.EntityClient.

<connectionStrings>
<add name="DBVentasEntities"
connectionString="metadata=res://*/ModelVentas.csdl|res://*/Mo
delVentas.ssdl|res://*/ModelVentas.msl;provider=System.Data.Sq
lClient;provider connection string=&quot;Data Source=.;Initial
Catalog=DBVentas;Integrated
Security=True;MultipleActiveResultSets=True&quot;"
providerName="System.Data.EntityClient" />
</connectionStrings>

3.3 ACCESO AL MODELO DE DATOS


Las tres técnicas principales que puede usar para interactuar con un EDM:

• Escritura de consultas de Entity SQL con el proveedor EntityClient.


• Escritura de consultas de Entity SQL con Servicios de objeto.
• Escritura de consultas de Entity con LINQ.

3.3.1 Entity SQL con el proveedor EntityClient.- El proveedor


EntityClient define clases y mapea datos para interactuar con
modelos de entidades de datos. EntityClient transforma las
operaciones de las entidades hacia operaciones directas a la
base de datos.
La escritura de código con la API de EntityClient le ofrece el
control más granular de las tres técnicas. Puede crear un objeto
EntityConnection para conectar al EDM, escribir una consulta en
Entity SQL, ejecutarla con un EntityCommand, y devolver los
resultados a través de un EntityDataReader.

Using cn As New EntityConnection("Name=DBVentasEntities")


Dim cmd As New EntityCommand("Select cli.Nombrecia
from DBVentasEntities.tb_clientes as cli",cn)
cn.Open()
Dim dr As EntityDataReader = _
cmd.ExecuteReader(CommandBehavior.SequentialAccess)
While dr.Read
Me.ComboBox1.Items.Add(dr("NombreCia"))
End While
dr.Close()
End Using

3.3.2 Entity SQL con Servicio de objeto.- Esta técnica se aleja de la


interacción directa con el proveedor de EntityClient. Usted usaría
ObjectContext y ObjectQuery<T> para publicar las consultas en
el EDM.
Using entidad As New DBVentasEntities
Dim cliente As ObjectQuery(Of tb_clientes) = _
entidad.CreateQuery(Of tb_clientes)( _
"Select VALUE cli From tb_clientes as cli")
For Each r As tb_clientes In cliente
Me.ComboBox1.Items.Add(r.NombreCia)
Next
End Using

CIBERTEC CARRERAS PROFESIONALES


152

3.3.3 Entity SQL con LINQ.- La versión de ADO.NET 3.5 incluye una
capa que permite exponer los datos de la base de datos como
objetos .NET, permitiendo a los desarrolladores formular consultas
contra una base de datos directamente desde el lenguaje de
programación utilizado para crear la lógica de negocio. Esta
capacidad se conoce como LINQ to Entities.
Using entidades As New DBVentasEntities
Dim query = From c In entidades.tb_clientes _
Where c.NombreCia Like "M%" Select c
For Each c As tb_clientes In query
ComboBox1.Items.Add(c.NombreCia)
Next
End Using

4 PROVEEDOR DE ENTIDAD DE DATOS: ENTITYCLIENT

EntityClient se parece mucho a los proveedores ADO.NET, y permite a los


desarrolladores ejecutar consultas en términos de EDM mediante objetos
Connection, Command y DataReader. También agrega el motor de vistas de
cliente para asignar el modelo de dominio, definido en términos de EDM, al
esquema subyacente de la base de datos relacional.

EntityClient permite a los desarrolladores, cuando sea necesario, trabajar en


entidades en forma de filas y columnas mediante cadenas de consulta ESQL sin
tener que generar clases para representar el esquema conceptual.
La principal ventaja de Entity SQL es su flexibilidad. Su sintaxis basada en
cadenas se presta fácilmente a la generación de consultas dinámicas. Esto puede
ser muy útil cuando se necesita crear una consulta ad hoc.
La escritura de código con la API de EntityClient le ofrece el control más granular
de las tres técnicas. Puede crear un objeto EntityConnection para conectar al
EDM, escribir una consulta en Entity SQL, ejecutarla con un EntityCommand, y
devolver los resultados a través de un EntityDataReader.

4.1 PRINCIPALES OBJETOS DEL ENTITYCLIENT

Clase Descripción
EntityCommand Comando que ejecuta una sentencia hacia el
modelo de entidad de datos.
EntityConnection Contiene la referencia al EMD y la conexion al
origen de datos.
EntityConnectionStringBuilder Maneja y crea la cadena de conexion utilizada
por EntityClient.
EntityDataReader Leer los registros del origen de datos.
EntityParameter Parámetro de un EntityCommand.
EntityProviderFactory Representa un conjunto de métodos para crear
o implementer las clases del origen de datos.
EntityTransaction Transacción para un EntityCommand.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 153

4.2 CONEXIÓN A UNA BASE DE DATOS: ENTITYCONNECTION


El objeto EntityConnection permite conectarse con un determinado origen
de datos mediante una cadena de conexión en la que se proporciona la
información de autenticación necesaria.

4.2.1 Definición de la cadena de conexión


Cuando implementamos el modelo de entidad de datos EDM, a través
del asistente, se crea la cadena de conexión, la cual se almacena en el
archivo App.Config:
<connectionStrings>
<add name="DBVentasEntities"
connectionString="metadata=res://*/ModelVentas.csdl|res://*/Mod
elVentas.ssdl|res://*/ModelVentas.msl;provider=System.Data.SqlC
lient;Data Source=.;Initial Catalog=DBVentas;Integrated
Security=True; MultipleActiveResultSets=True"
providerName="System.Data.EntityClient" />
</connectionStrings>

A partir de la publicación de la conexión, definimos al objeto de conexión


EntityConnection:

Imports System.Data.EntityClient
. . .
Dim cn As New EntityConnection("Name=DBVentasEntities")

El siguiente ejemplo muestra como conectarse a la base de datos


DBVentas utilizando la cadena de conexión almacenada en el archivo
App.Config.

Dim cn As New EntityConnection("Name=DBVentasEntities")


‘o a traves de la Estructura Using
Using cn As New EntityConnection("Name=DBVentasEntities")
. . .
End Using

Using: Un bloque Using garantiza la eliminación de uno o más de


tales recursos cuando su código termina de usarlos. Esto los pone a
disposición de otro código para que los pueda utilizar.

4.3 TRABAJAR CON EL ENTITYCOMMAND


El proveedor EntityClient posee una clase que permite ejecutar consultas
sobre el modelo de entidad de datos: EntityCommand. La clase
EntityCommand tiene 4 métodos que permite utilizar para ejecutar
sentencias SQL:

EntityCommand Descripción
ExecuteScalar Ejecuta una consulta que retorna un valor.
ExecuteReader Ejecuta una consulta que retorna un conjunto de
datos a un DataReader.
ExecuteNonQuery Ejecuta una Sentencia para actualizar los datos.

CIBERTEC CARRERAS PROFESIONALES


154

4.3.1 Ejecutar una consulta en la base de datos


1. Instancia el objeto EntityConnection
2. Instancia el objeto EntityCommand. En el constructor especificar la
sentencia sql que se va a ejecutar y la conexión.
3. Especifique la propiedad CommandType. Si ejecuta una sentencia
SQL el valor del CommandType es CommandType.Text; si ejecuta
un procedimiento almacenado el valor será
CommandType.StoredProcedure.
4. Llame al método Open del objeto Conexión.
5. Ejecute el método del objeto Command, asignando su resultado a una
variable o control.

El siguiente ejemplo permite ejecutar una consulta que retorne el


número de clientes almacenadas en la base de datos DBVentas.

Using cn As New EntityConnection("Name=DBVentasEntities")


Dim cmd As New EntityCommand( _
"Select count(cli.idcliente) from
DBVentasEntities.tb_clientes as cli", cn)
cmd.CommandType = CommandType.Text
cn.Open()
TextBox1.Text = cmd.ExecuteScalar
End Using

4.4 TRABAJAR CON EL ENTITYDATAREADER


El proveedor EntityClient posee una clase que permite recuperar las filas:
EntityDataReader. Con el EntityDataReader puede aumentar el rendimiento
de la aplicación tanto al recuperar datos en cuanto están disponibles como al
almacenar (de forma predeterminada) una fila cada vez en memoria, lo que
reduce la sobrecarga del sistema.

4.4.1 Recuperación de datos mediante EntityDataReader


La recuperación de datos mediante EntityDataReader implica crear una
instancia del objeto Command, para lo cual se llama al método
Command.ExecuteReader a fin de recuperar filas de un origen de
datos. En el ejemplo se muestra cómo se utiliza un EntityDataReader,
donde command representa un objeto EntityCommand válido.

'Definir el Objeto CmdReader


Dim CmdReader As New EntityCommand

'cargará los datos al ejecutar el Metodo ExecuteReader


Dim reader As EntityDataReader=CmdReader.ExecuteReader()

El método Read del objeto EntityDataReader permite obtener una fila a


partir de los resultados de una consulta.
Para tener acceso a cada columna de la fila devuelta, puede pasar a
EntityDataReader el nombre o referencia numérica de la columna en
cuestión. Sin embargo, el mejor rendimiento se logra con los métodos
que ofrece el EntityDataReader y que permiten tener acceso a los
valores de las columnas en sus tipos de datos nativos (GetDateTime,
GetDouble, GetGuid, GetInt32, etc).

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 155

En el ejemplo de código siguiente se repite por un objeto


DataReader y se devuelven dos columnas de cada fila.

Using cn As New EntityConnection("Name=DBVentasEntities")


Dim cmd As New EntityCommand("Select cli.Nombrecia
from DBVentasEntities.tb_clientes as cli",cn)
cn.Open()
Dim dr As EntityDataReader = _
cmd.ExecuteReader(CommandBehavior.SequentialAccess)
Do While reader.Read
str += reader(0) + vbTab + reader.GetString(1)
Loop
'Terminado el proceso cerrar el reader
dr.Close()
End Using

4.4.2 Cerrar el EntityDataReader


Siempre debe llamar al método Close cuando haya terminado de utilizar
el objeto EntityDataReader. Tenga en cuenta que mientras está abierto
un EntityDataReader, éste utiliza de forma exclusiva el objeto
Connection.

LABORATORIO 11.1
CONSULTA DE DATOS UTILIZANDO ENTITY PROVIDER
En este escenario vamos a desarrollar un aplicativo el cual permita listar los clientes
que se encuentra administrado en el modelo de entidad de datos (EDM).
A continuación sigua los siguientes pasos para realizar este proceso.

1. Ingrese a Visual Studio 2005.


2. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”
- En “Templates” elija “Windows Application”
- En “Name” coloque “appEntidades11”
- En “Location” coloque “C:\CursoPOOII”
3. Agregar un Item al Proyecto: tipo Modelo de Entidad de datos.

Selecciona la
plantilla ADO.NET
Entity Data Model

CIBERTEC CARRERAS PROFESIONALES


156

4. Selecciona Generar desde la base de datos para definir el modelo.


Selecciona
Generar desde
la base de datos
para trabajar una
base de datos

6. Especifica la cadena de
conexión a la BD y
FINALIZAR.

Conexión a la
base de datos del
app.config

Nombre de la
conexión de
entidad a
almacenar en el
app.config

7. Especificar que objetos de la BD queremos que formen de nuestro EDM (en


este caso, tablas y procedimientos almacenados).

8. Al finalizar se construye el modelo de entidad de datos, tal como se muestra en


la figura: Model1.edmx

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 157

9. Diseña el formulario para listar los registros de los clientes.

Control ListView

10. Defina la librería para trabajar con los objetos Entity.


Imports System.Data.EntityClient

11. En el evento Load del Formulario ejecutamos un objeto Command para


recuperar los registros de tb_clientes, almacenándolos en el DataReader.

'conexión definida por el app.config: DBVentasEntities


Using cn As New EntityConnection("Name=DBVentasEntities")
'VALUE retorna todos los valores de cada fila
Dim cmd As New EntityCommand( "Select VALUE cli from
DBVentasEntities.tb_clientes as cli", cn)
cn.Open()
'Retornar los registros en forma secuencial
Dim dr As EntityDataReader = _
cmd.ExecuteReader(CommandBehavior.SequentialAccess)
'Mientras se lea el registro
While dr.Read
Dim it As New ListViewItem(dr("IdCliente").ToString)
it.SubItems.Add(dr("NombreCia"))
it.SubItems.Add(dr("Direccion"))
it.SubItems.Add(dr("idpais"))
Me.ListView1.Items.Add(it)
End While
dr.Close()
End Using

12. Grabe el proyecto y ejecute el aplicativo para realizar las pruebas.

CIBERTEC CARRERAS PROFESIONALES


158

LABORATORIO 11.2
CONSULTA DE PEDIDOS ENTRE DOS FECHAS
En este escenario vamos a consultar los pedidos entre dos fechas. Al seleccionar las
fechas en los controles ComboBox, listar los pedidos entre las fechas seleccionadas.
1. Agregue un formulario al proyecto, diseñe el formulario tal como se muestra.

2. Importe la librería para trabaja con la librería EntityClient Provider.


Imports System.Data.EntityClient

3. Defina la variable de conexión a nivel Formulario.

Private cn As New EntityConnection("Name=DBVentasEntities")

4. En el evento Load del formulario, cargue las fechas en los ComboBoxes.

'instancia del contexto DBVentasEntities


Dim db As New DBVentasEntities
'configurar el ComboBox1 y ComboBox2
Me.ComboBox1.DataSource = db.tb_pedidoscabe
Me.ComboBox1.DisplayMember = "FechaPedido"
Me.ComboBox2.DataSource = db.tb_pedidoscabe
Me.ComboBox2.DisplayMember = "FechaPedido"

5. Defina, en el evento Click del botón Consulta, el proceso para listar los pedidos
entre dos fechas seleccionadas por ComboBoxes.

Dim cmd As New EntityCommand( _


"Select VALUE p from DBVentasEntities.tb_pedidoscabe As p
Where p.FechaPedido>=@f1 AND p.FechaPedido<=@f2", cn)
'defina los parametros de la consulta: f1 y f2
cmd.Parameters.Add("f1", DbType.DateTime).Value =
CDate(ComboBox1.Text)
cmd.Parameters.Add("f2", DbType.DateTime).Value =
CDate(ComboBox2.Text)
cn.Open()
'retorna los registros en forma secuencial de la consulta
Dim dr As EntityDataReader =
cmd.ExecuteReader(CommandBehavior.SequentialAccess)

Me.ListView1.Items.Clear()
cn.Close()

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 159

. . .
While dr.Read
Dim it As New ListViewItem(dr("IdPedido").ToString)
it.SubItems.Add(dr("IdCliente"))
it.SubItems.Add(dr("FechaPedido"))
it.SubItems.Add(dr("FechaEntrega"))
Me.ListView1.Items.Add(it)
End While
dr.Close()
cn.Close()
6. Grabe el proyecto y ejecute la aplicación.

LABORATORIO 11.3
ACTUALIZACION DE CLIENTES
En este escenario vamos a actualizar los datos de los clientes utilizando los objetos
del Modelo de Entidad de Datos DBVentasEntities.
1. Agregue un formulario al proyecto, diseñe el formulario tal como se muestra.

Control Nombre Propiedad Valor


Button BtnLimpiar Text LIMPIAR
Button BtnAgregar Text AGREGAR
Button BtnModificar Text MODIFICAR
Button BtnEliminar Text ELIMINAR
Label Label1 Text Mantenimiento de Clientes
Label Label2 Text Código
Label Label3 Text Nombre
Label Label4 Text Dirección
Label Label5 Text País
Label Label6 Text Fono
TextBox TxtCodigo
TextBox TxtNombre
TextBox TxtDireccion
TextBox TxtFono
ComboBox ComboBox1
DataGridView DataGridView1

2. Defina la instancia de DBVentasEntities a nivel formulario


Private DB As New DBVentasEntities

CIBERTEC CARRERAS PROFESIONALES


160

3. En el evento Load del formulario, configura el ComboBox con la entidad tb_paises


y liste los clientes en el DataGridView1.

'configura el combobox con la entidad tb_paises


Me.ComboBox1.DataSource = DB.tb_paises
Me.ComboBox1.DisplayMember = "NombrePais"
Me.ComboBox1.ValueMember = "idpais"
'listar los clientes en el DataGridView1
Me.DataGridView1.DataSource = DB.tb_clientes.ToList

4. En el botón grabar se procederá a Grabar un nuevo cliente a la entidad tb_clientes,


actualizando los datos en el Contexto DBVentasEntities DB.

'definir la instancia de tb_clientes


Dim cliente As New tb_clientes
'asigne los valores a la instancia cliente
cliente.IdCliente = Me.txtcodigo.Text
cliente.NombreCia = Me.txtnombre.Text
cliente.Direccion = Me.txtdireccion.Text
cliente.idpais = Me.ComboBox1.SelectedValue
cliente.Telefono = Me.txtfono.Text
'añadir cliente a la entidad tb_clientes
DB.AddTotb_clientes(cliente)
'actualizar los cambios
DB.SaveChanges()
DataGridView1.DataSource = DB.tb_clientes.ToList

5. En el botón modificar se procederá a actualizar los datos de un cliente


seleccionado, observe que los datos se actualiza en la entidad tb_clientes del
contexto DBVentasEntities.
'asigne el objeto tb_cliente seleccionado del DataGridView1
Dim cliente As tb_clientes = _
DB.tb_clientes.ToList.ElementAt(DataGridView1.CurrentRow.Index)
'asigne los datos a actualizar
cliente.NombreCia = Me.txtnombre.Text
cliente.Direccion = Me.txtdireccion.Text
cliente.idpais = Me.ComboBox1.SelectedValue
cliente.Telefono = Me.txtfono.Text
'actualizar los cambios
DB.SaveChanges()
Me.DataGridView1.DataSource = DB.tb_clientes.ToList

6. En el botón eliminar se elimina el objeto cliente seleccionado desde el


DataGridView1 y se actualizará en el contexto DBVentasEntities.

Dim cliente As tb_clientes = DB.tb_clientes.ToList.ElementAt( _


DataGridView1.CurrentRow.Index)
'eliminar el objeto y actualizar los cambios
DB.DeleteObject(cliente)
DB.SaveChanges()

Me.DataGridView1.DataSource = DB.tb_clientes.ToList

7. Grabe y ejecute la aplicación para comprobar sus procesos.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 161

Autoevaluación

1. ¿Qué es el modelo relacional de objetos?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

2. Explique cada una de las capas del modelo de entidad de datos.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

3. ¿Qué es el ADO.NeT Entity Provider?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

4. Explique cada una de las clases que integran el Entity Provider.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

5. ¿Cómo se conecta a una base de datos utilizando el EntityConnection?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

CIBERTEC CARRERAS PROFESIONALES


162

Resumen

 El Entity Framework permite a los desarrolladores escribir menos código de acceso


a datos, reduce el mantenimiento, condensa la estructura de datos de forma más
manejable (y menos normalizada) y facilita la persistencia de los datos.

 Hay hay tres capas en el modelo de Entity Framework:


o Capa conceptual.- definida mediante un archivo .CSDL (Conceptual
Schema Definition Language, un archivo XML con información relativa a las
entidades del modelo), el cuál incluye las entidades y las relaciones tal y
como la capa de negocio de la aplicación las conoce.
o Capa de asignación.- definida con MSL (Mapping Schema Language),
establece el mapeo entre las entidades del modelo conceptual y sus
correspondencias con la BD.
o Capa lógica.- definida con SSDL (Store Schema Definition Language), y
representa el esquema de la BD.

 Las tres técnicas principales que puede usar para interactuar con un EDM:
• Escritura de consultas de Entity SQL con el proveedor EntityClient
• Escritura de consultas de Entity SQL con Servicios de objeto
• Escritura de consultas de Entity con LINQ.

 El proveedor EntityClient define clases y mapea datos para interactuar con


modelos de entidades de datos. EntityClient transforma las operaciones de las
entidades hacia operaciones directas a la base de datos.

 La versión de ADO.NET 3.5 incluye una capa que permite exponer los datos de la
base de datos como objetos .NET, permitiendo a los desarrolladores formular
consultas contra una base de datos directamente desde el lenguaje de
programación utilizado para crear la lógica de negocio. Esta capacidad se conoce
como LINQ to Entities.

 EntityClient se parece mucho a los proveedores ADO.NET, y permite a los


desarrolladores ejecutar consultas en términos de EDM mediante objetos
Connection, Command y DataReader. También agrega el motor de vistas de
cliente para asignar el modelo de dominio, definido en términos de EDM, al
esquema subyacente de la base de datos relacional.

 Si desea conocer mas acerca del tema, visite las siguientes paginas:

 http://msdn.microsoft.com/es-ar/library/bb738679(en-us).aspx
Página referente al marco de los objetos de entidad

 http://msdn.microsoft.com/es-ar/library/system.data.entityclient(en-
us).aspx
Página referente al ADO.NET Entity Provider

 http://msdn.microsoft.com/es-es/magazine/cc507640.aspx
Página referente al modelo de Entidad

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 163

UNIDAD DE
APRENDIZAJE

4
SEMANA

12

ADO.NET ENTITY FRAMEWORK


LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET utilizan una
plataforma de acceso a datos, para mapear un modelo conceptual de tipo entidad-relación
apoyándonos en un entorno visual integrado con Visual Studio, y realizar consultas a través
del nuevo lenguaje de consultas integrado.

TEMARIO

• Modelo Relacional de Objetos, introducción.

• LINQ: arquitectura, DataContext.

• Consultas y actualización de datos utilizando LINQ to SQL

• ADO.NET Entity FrameWork.

• Acceso a datos utilizando EntityClient Provider; administración de los objetos Entity:


EntityConnection, EntityCommand, EntityDataReader, EntityTransaction.

• Acceso a datos utilizando Servicios de Objetos y LINQ to Entity.

ACTIVIDADES PROPUESTAS

• Los alumnos realizan operaciones de consulta utilizando los servicios de objetos


con entidades.

• Los alumnos realizan operaciones de actualización de datos utilizando los servicios


de objetos con entidades.

CIBERTEC CARRERAS PROFESIONALES


164

1 ADO.NET ENTITY FRAMEWORK: SERVICIOS DE OBJETOS


Los Servicios de Objeto son un componente del Marco de Entidad que le permite
consultar, insertar, actualizar, y suprimir datos, expresados como fuerte escrito
CLR los objetos que son los casos de tipos de entidad.

Los Servicios de Objeto apoyan tanto al Lenguaje de consulta integrada (LINQ)


como al Entity SQL Query sobre los tipos que son definidos en un Modelo de
Datos de Entidad (EDM).

Los Servicios de Objeto materializan datos devueltos como objetos, y actualizan


cambios de objeto a la fuente de datos. Esto también proporciona instalaciones de
rastrear cambios, enlazar objetos al origen de datos (data source).

Los Servicios de Objeto son puestos en práctica por clases en el Sistema. Data.
Objects y Sistema. Data. Objects. DataClasses.

1.1 OBJECT CONTEXT


ObjectContext es la puerta de enlace a EntityConnection para Servicios de
objeto. Ofrece acceso al EDM a través del EntityConnection subyacente.
Por ejemplo, puede tener acceso a las entidades a través de ObjectContext,
interrogar a ObjectContext para averiguar información acerca del estado de
objetos y crear consultas de ObjectQuery<T> con el método CreateQuery.

Otro de los objetivos de ObjectContext es permitir que los objetos obtengan


información de actualización sobre las entradas de la base de datos. Por
ejemplo, puede usar los métodos de ObjectContext para agregar entidades a
ObjectContext, eliminar entidades, manipular entidades y, por último, guardar
los cambios de las entidades en la base de datos (a través del método
SaveChanges).

Una instancia de la clase ObjectContext encapsula:


• Una conexion a la base de datos, en el formulario de un objeto
EntityConnection.
• Metadata que describe el modelo, en el formulario de un objeto
MetadataWorkspace .
• Un objeto ObjectStateManager que manejo objetos durante las
operaciones de creación, actualización yate, y eliminación.

2 CONSULTA DE DATOS COMO OBJETOS


Los Servicios de Objeto le permiten usar el Lenguaje de consulta integrada
(LINQ), Entity SQL, o query bulider para ejecutar consultas contra un Modelo de
Datos de Entidad (EDM) y retornar datos como objetos.Para realizar consulta al
modelo trabajamos con la clase ObjectQuery.

2.1 LA CLASE OBJECTQUERY


La clase genérica ObjectQuery representa una consulta que retornar una
colección de cero a más objetos de entidad tipeadas. Un ObjectQuery siempre
pertenece a un ObjectContext. Este contexto provee la conexión y la
información de la metadata que es requerido para definir y ejecutar una

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 165

consulta. Un ObjectContext tipeado incluye un conjunto de propiedades que


retornar instancias de ObjectQuery tipeados. Hay una de esas propiedades
para cada entidad en el modelo. Esas propiedades hacen mas fácil crear e
instanciar un ObjectQuery tipeado. El ObjectQuery es ejecutado en los
siguientes escenarios:
• Cuando es recuperado sus objetos dentro de un For Each.
• Cuando es asignado para poblar en una colección List collection.
• Cuando se ejecuta el método Execute.
• Cuando se ejecuta un operador del LINQ query tal como First or Any.

La siguiente consulta retorna los objetos tb_pedidoscabe, almacenando los


objetos en un LIST y visualizando los objetos en un DataGridView.

Dim db As New DBVentasEntities


Dim lista As ObjectQuery(Of tb_pedidoscabe) = db.tb_pedidoscabe
Me.DataGridView1.DataSource = lista.ToList

2.2 MÉTODO PARA CONSTRUIR CONSULTAS EN OBJECTQUERY


La clase ObjectQuery soporta consultas para LINQ to Entities y Entity SQL en
el modelo de entidad de datos (EDM). ObjectQuery también implementa un
conjunto de métodos para construir consultas que puede ser usado para
construir comando de consultas que son equivalente a Entity SQL. Los
métodos para construir métodos de ObjectQuery:

Método ObjectQuery Descripción

Distinct Retorna objeto no repetido.


Except Retorna objetos excluidos de otra consulta.
GroupBy Retorna objetos agrupados por un criterio.
OrderBy Retorna objetos ordenados.
Select Retorna conjunto de objetos definiendo las columnas.
Skip Especifica el número de resultados de la consulta.
Top Retorna el primer objeto de la consulta.
Retorna objetos producto de la unión de dos
Union
consultas.
Retorna un conjunto de objetos filtrados por una
Where
condición.

En el siguiente ejemplo listamos el registro de cliente cuyo código sea ALFKI


'defina la instancia del modelo
Dim db As New DBVentasEntities
Al igual queun
'definir Entity SQL, LINQ que
ObjectQuery tampoco admiteuna
resuelva la sintaxis directa
consulta de para
clientes
'a través de la condición del idcliente
Dim ls As ObjectQuery(Of tb_clientes)=db.CreateQuery(Of tb_clientes) _
("Select VALUE c From tb_clientes As c Where c.idcliente=’ALFKI’")
'listar los resultados
Me.DataGridView1.DataSource = lista.ToList

CIBERTEC CARRERAS PROFESIONALES


166

3 TRABAJANDO CON OBJETOS


Trabajar con los objetos del modelo de entidad de datos implica utilizar la clase
Object Services para crear, cambiar y eliminar objetos dentro del Object Context.
Así como manejar las excepciones dentro del origen de datos y enlazar los
objetos a los controles.

3.1 ADICIONANDO, MODIFICANDO Y ELIMINANDO OBJETOS


Los objetos dentro del ObjectContext son instancias de los tipos de entidades
que representan los datos dentro del origen de datos. Puede modificar, crear y
eliminar objetos dentro del ObjectContext y el Object Services realizar los
cambios de esos objetos. Cuando se ejecuta el método SaveChanges, el
Object Services genera y ejecuta los commandos que funcionan como las
sentencias insert, update, or delete sobre el origen de datos.

3.1.1 Agregando Objetos


Cuando quieres agregar data en el origen de datos, debes crear una
instancia del tipo de la Entidad y añadir el objeto al ObjectContext. Antes
de agregar un nuevo objeto, debes asignar, primero, a todas las
propiedades que no soporten valores null.
Considere utilizan el método CreateObjectName para crear una nueva
instancia de un tipo de entidad. El modelo de entidad de datos (EDM)
incluye este método en cada clase que son generados como tipos de
entidad; para crear una instancia de un objeto utilizando este método,
asigne a todas las propiedades de la clase que no puede ser null.

El siguiente ejemplo utiliza el método Createtb_clientes para crear una


instancia de la clase tb_clientes.

Dim cliente As tb_clientes = _


Tb_clientes.Createtb_clientes("ABC","CIBERTEC","San Isidro", _
"001","123456"")

Puede agregar nuevos objetos dentro de un ObjectContext invocando al


método AddObject o llamando al método AddToEntitySetName.

El siguiente ejemplo utiliza el método AddTotb_clientes para agregar un


objeto dentro del ObjectContext DBVentasEntities (db).

'definir la instancia de tb_clientes


Dim cliente As New tb_clientes
'asigne los valores a la instancia cliente
cliente.IdCliente = "ABC1"
cliente.NombreCia = "CIBERTEC-UPC"
cliente.Direccion = ("San Isidro"
cliente.idpais = ("001"
cliente.Telefono = ("234567"
'añadir cliente al ObjectContext
DB.AddTotb_clientes(cliente)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 167

3.1.2 Modificando Objetos


Cuando realizas cambios de un objeto a una propiedad escalar, compleja
o de navegación y llamas al método SaveChanges, los datos
actualizados son enviados al origen de datos.

Los Object Services realizar cambios a los objetos que son adjuntados al
ObjectContext utilizando una instancia del IEntityChangeTracker.
Las consultas retornan objetos en el estado Unchanged. El Modelo de
entidad de datos ejecuta métodos para realizar los cambios asignando a
cada propiedad de la entidad.

En el siguiente ejemplo asigne un valor a la propiedad idpais de la


entidad tb_clientes.
Set(ByVal value As String)
Me.OnStatusChanging(value)
Me.ReportPropertyChanging("Status")
Me._Status = StructuralObject.SetValidValue(value)
Me.ReportPropertyChanged("Status")
Me.OnStatusChanged()
End Set

3.1.3 Eliminando Objetos


Llamar al método DeleteObject del modelo ObjectContext para
especificar el objeto de la eliminación. La fila no es borrada desde el
origen de datos hasta ejecutar el método SaveChanges.
Las siguientes consideraciones se aplican cuando eliminamos objetos:
• Cuando un objeto es eliminado, cualquier relación a otros objetos
también es eliminado.
• Cuando dos objetos están relacionados, eliminando un objeto padre
eliminar todos sus objetos hijos. Este resultado se aplica habilitando la
propiedad CascadeDelete.
• Llamando al método DeleteObject para un objeto que ya ha sido
eliminado.

En el ejemplo eliminamos el primer cliente de la entidad tb_clientes


ejecutando el método DeleteObject.

Dim cliente As tb_clientes = DB.tb_clientes.First


'eliminar el objeto y actualizar los cambios
DB.DeleteObject(cliente)

3.2 SALVANDO CAMBIOS Y MANEJANDO CONCURRENCIAS


Cuando ejecutamos el método SaveChange, el Object Service trata de
combinar los cambios en el origen de datos. Cuando existen conflictos en los
cambios realizados al origen de datos al ejecutar el método SaveChanges,
se desencadena la concurrencia OptimisticConcurrencyException.
Cuando agregamos un objeto al ObjectContext a través del método
SaveChanges, puede generar un UpdateException cuando un objeto
agregado al ObjectContext no puede creado satisfactoriamente en el origen
de datos.

CIBERTEC CARRERAS PROFESIONALES


168

El siguiente ejemplo actualizamos los cambios de la entidad tb_clientes.

Try
'realizar los cambios, el cual puede causar conflicto
Dim n As Integer = context.SaveChanges()
Messagebox.Show("Registros Actualizados:" & n)
Catch ex As OptimisticConcurrencyException
'en caso existe conflict, refrescar los cambios los
'objetos antes del cambios.
context.Refresh(RefreshMode.ClientWins, orders)
'salvar los cambios.
context.SaveChanges()
Messagebox.Show(" Se ha desencanado un
OptimisticConcurrencyException, se grabó los cambios")
End Try

4 ENLAZANDO OBJETOS A LOS CONTROLES


Los Object Services permiten enlazar controles tales como ComboBox, ListView,
and DataGridView a un EntityCollection o un ObjectResult el cual es retornado
cuanod se ejecuta un ObjectQuery. En ambas clase Entity Framework se
implementa la interface IListSource para datos enlazados. Todos los objetos de
entidad derivados desde una clase base StructuralObject, el cual implementa
INotifyPropertyChanged.

Para enlazar objetos a los controles Windows Form control, asignar la propiedad
DataSource del control al EntityCollection o al ObjectResult que es retornado
cuando se ejecute el método Execute de un objeto ObjectQuery object.

El siguiente ejemplo enlazamos EntityCollection a un control DataGridView.

'Enlazar la data de productos al DataGridView.


Me.DataGridView1.DataSource = db.tb_productos

LABORATORIO 12.1
CONSULTA DE DATOS UTILIZANDO ENTITY PROVIDER
En este escenario vamos a desarrollar un aplicativo el cual permita filtrar todos los
productos por su nombre; donde al ingresar los primeros caracteres del nombre del
producto, visualice los productos que se encuentra administrado en el modelo de
entidad de datos (EDM).
A continuación sigua los siguientes pasos para realizar este proceso.

1. Ingrese a Visual Studio 2005


2. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”
- En “Templates” elija “Windows Application”.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 169

- En “Name” coloque “appEntidades12”.


- En “Location” coloque “C:\CursoPOOII”.
3. Agregar un Item al Proyecto: tipo Modelo de Entidad de datos.

Selecciona la
plantilla ADO.NET
Entity Data Model.

4. Selecciona Generar desde la base de datos para definir el modelo.

Selecciona
Generar desde
la base de datos
para trabajar una
base de datos.

5. Especifica la cadena de
conexión a la BD y
FINALIZAR.

Conexión a la
base de datos del
app.config.

Nombre de la
conexión de
entidad a
almacenar en el
app.config.

6. Especificar que objetos de la BD queremos que formen de nuestro EDM (en


este caso, tablas y procedimientos almacenados).

CIBERTEC CARRERAS PROFESIONALES


170

7. Al finalizar se construye el modelo de entidad de datos, tal como se muestra en


la figura: Model1.edmx

8. Diseña el formulario para listar los registros de los clientes.

Control Nombre Propiedad Valor


Button BtnConsulta Text CONSULTA
Label Label1 Text Consulta de Productos
Label Label2 Text Nombre
TextBox TxtNombre
DataGridView DataGridView1

9. Defina la librería para trabajar con los objetos Entity.


Imports System.Data.EntityClient

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 171

10. En el evento Load del Formulario ejecutamos un objeto Command para


recuperar los registros de tb_clientes, almacenándolos en el DataReader.

Dim nombre As String = Me.txtnombre.Text + "%"


'definir la instancia del modelo
Dim db As New DBVentasEntities

'definir la consulta de productos a través del object query


Dim lista As ObjectQuery(Of tb_productos) = db.CreateQuery( _
Of tb_productos)("Select VALUE p From tb_productos as p Where
p.NombreProducto LIKE '" + nombre + "'")

'listar
Me.DataGridView1.DataSource = lista.ToList

11. Grabe el proyecto y ejecute el aplicativo para realizar las pruebas.

LABORATORIO 12.2
CONSULTA DE PEDIDOS ENTRE DOS FECHAS
En este escenario vamos a consultar los pedidos entre dos fechas. Al seleccionar las
fechas en los controles ComboBox, listar los pedidos entre las fechas seleccionadas.
1. Agregue un formulario al proyecto, diseñe el formulario tal como se muestra.

2. Importe la librería para trabaja con la librería Objects.


Imports System.Data.Objects

3. Defina la variable de contexto a nivel Formulario.

Dim db As New DBVentasEntities

CIBERTEC CARRERAS PROFESIONALES


172

4. En el evento Load del formulario, cargue las fechas en los ComboBoxes.

'configurar el ComboBox1 y ComboBox2


Me.ComboBox1.DataSource = db.tb_pedidoscabe
Me.ComboBox1.DisplayMember = "FechaPedido"
Me.ComboBox1.ValueMember = "FechaPedido"
Me.ComboBox2.DataSource = db.tb_pedidoscabe
Me.ComboBox2.DisplayMember = "FechaPedido"
Me.ComboBox2.ValueMember = "FechaPedido"

5. Defina, en el evento Click del botón Consulta, el proceso para listar los pedidos
entre dos fechas seleccionadas por ComboBoxes.

'definir la consulta de productos a través del object query


Dim lista As ObjectQuery(Of tb_pedidoscabe) = _
db.CreateQuery(Of tb_pedidoscabe)( _
"Select VALUE p From tb_pedidoscabe as p " + _
"Where p.FechaPedido BetWeen @f1 AND @f2", _
New ObjectParameter("f1", ComboBox1.SelectedValue), _
New ObjectParameter("f2", ComboBox2.SelectedValue))

'listar
Me.DataGridView1.DataSource = lista.ToList

6. Grabe el proyecto y ejecute la aplicación.

LABORATORIO 12.3
ACTUALIZACION DE CLIENTES
En este escenario vamos a actualizar los datos de los clientes utilizando los objetos
del Modelo de Entidad de Datos DBVentasEntities.

1. Agregue un formulario al proyecto, diseñe el formulario tal como se muestra.

Control Nombre Propiedad Valor


Button BtnLimpiar Text LIMPIAR
Button BtnAgregar Text AGREGAR
Button BtnModificar Text MODIFICAR
Button BtnEliminar Text ELIMINAR

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 173

Label Label1 Text Mantenimiento de Clientes


Label Label2 Text Codigo
Label Label3 Text Nombre
Label Label4 Text Direccion
Label Label5 Text Pais
Label Label6 Text Fono
TextBox TxtCodigo
TextBox TxtNombre
TextBox TxtDireccion
TextBox TxtFono
ComboBox ComboBox1
DataGridView DataGridView1

2. Defina la instancia de DBVentasEntities a nivel formulario.


Private DB As New DBVentasEntities

3. En el evento Load del formulario, configura el ComboBox con la entidad tb_paises


y liste los clientes en el DataGridView1.

'configura el combobox con la entidad tb_paises


Me.ComboBox1.DataSource = DB.tb_paises
Me.ComboBox1.DisplayMember = "NombrePais"
Me.ComboBox1.ValueMember = "idpais"
'listar los clientes en el DataGridView1
Me.DataGridView1.DataSource = DB.tb_clientes.ToList

4. En el botón grabar se procederá a Grabar un nuevo cliente a la entidad tb_clientes,


actualizando los datos en el Contexto DBVentasEntities DB.
'definir el tb_clientes
Dim cliente As tb_clientes = tb_clientes.Createtb_clientes( _
Me.txtcodigo.Text, Me.txtnombre.Text, Me.txtdireccion.Text, _
Me.ComboBox1.SelectedValue, Me.txtfono.Text)
'añadir cliente a la entidad tb_clientes
DB.AddTotb_clientes(cliente)
'actualizar los cambios
Try
DB.SaveChanges()
Me.DataGridView1.DataSource = DB.tb_clientes.ToList
Catch ex As UpdateException
MessageBox.Show(ex.Message)
End Try

5. En el botón modificar se procederá a actualizar los datos de un cliente


seleccionado, observe que los datos se actualiza en la entidad tb_clientes.
'asigne el objeto tb_cliente seleccionado del DataGridView1
Dim cliente As tb_clientes = _
DB.tb_clientes.ToList.ElementAt(DataGridView1.CurrentRow.Index)
'asigne los datos a actualizar
cliente.NombreCia = Me.txtnombre.Text
cliente.Direccion = Me.txtdireccion.Text
cliente.idpais = Me.ComboBox1.SelectedValue
cliente.Telefono = Me.txtfono.Text
'actualizar los cambios
DB.SaveChanges()
Me.DataGridView1.DataSource = DB.tb_clientes.ToList

CIBERTEC CARRERAS PROFESIONALES


174

6. En el botón eliminar se elimina el objeto cliente seleccionado desde el


DataGridView1 y se actualizará en el contexto DBVentasEntities.

Dim cliente As tb_clientes = DB.tb_clientes.Where( _


"c.idcliente='" + txtcodigo.Text + "'").First

DB.DeleteObject(cliente)
DB.SaveChanges()

Me.DataGridView1.DataSource = DB.tb_clientes.ToList

7. En el evento CellClick del DataGridView1, visualizamos los datos del registro al


seleccionar el Cliente.

Me.txtcodigo.Text = DataGridView1.CurrentRow.Cells(0).Value
Me.txtnombre.Text = DataGridView1.CurrentRow.Cells(1).Value
Me.txtdireccion.Text = DataGridView1.CurrentRow.Cells(2).Value
Me.txtfono.Text = DataGridView1.CurrentRow.Cells(4).Value
ComboBox1.SelectedValue=DataGridView1.CurrentRow.Cells(3).Value

8. Grabe y ejecute la aplicación para comprobar sus procesos.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 175

Autoevaluación

1. ¿Qué es el Servicio de objetos?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

2. ¿Qué es el Object Context?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

3. Explique la funcionalidad de la clase Object Query.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

4. Explique las operaciones de actualización del ObjectQuery.


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

5. ¿Cómo salvamos los objetos y manejamos la concurrencia?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________

CIBERTEC CARRERAS PROFESIONALES


176

Resumen

 Los Servicios de Objeto materializan datos devueltos como objetos, y actualizan


cambios de objeto a la fuente de datos. Esto también proporciona instalaciones de
rastrear cambios, enlazar objetos al origen de datos (data source).

 ObjectContext es la puerta de enlace a EntityConnection para Servicios de objeto.


Ofrece acceso al EDM a través del EntityConnection subyacente.
Por ejemplo, puede tener acceso a las entidades a través de ObjectContext,
interrogar a ObjectContext para averiguar información acerca del estado de objetos
y crear consultas de ObjectQuery<T> con el método CreateQuery.

 La clase genérica ObjectQuery representa una consulta que retornar una


colección de cero a más objetos de entidad tipeadas. Un ObjectQuery siempre
pertenece a un ObjectContext. Este contexto prove la conexión y la información de
la metadata que es requerido para definir y ejecutar una consulta.

 Cuando quieres agregar data en el origen de datos, debes crear una instancia del
tipo de la Entidad y añadir el objeto al ObjectContext. Antes de agregar un nuevo
objeto, debes asignar, primero, a todas las propiedades que no soporten valores
null.

 Los Object Services realizar cambios a los objetos que son adjuntados al
ObjectContext utilizando una instancia del IEntityChangeTracker.
Las consultas retornan objetos en el estado Unchanged. El Modelo de entidad de
datos ejecuta métodos para realizar los cambios asignando a cada propiedad de
la entidad para crear la lógica de negocio. Esta capacidad se conoce como LINQ
to Entities.

 El método DeleteObject del modelo ObjectContext para especificar el objeto de


la eliminación. La fila no es borrada desde el origen de datos hasta ejecutar el
método SaveChanges.

 Si desea conocer mas acerca del tema, visite las siguientes paginas:

 http://msdn.microsoft.com/es-ar/library/bb738470(en-us).aspx
Página referente a las actualizaciones de los servicios de objetos

 http://geeks.ms/blogs/ciin/archive/2008/01/25/ado-net-entity-framework-
linq-to-entities-entity-sql-y-entity-services-i.aspx
Página referente al los servicios de objetos y entidades

 http://msdn.microsoft.com/es-es/magazine/cc507640.aspx
Página referente al modelo de Entidad

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 177

UNIDAD DE
APRENDIZAJE

5
SEMANA

13

OPERACIONES CON XML

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET


resuelven operaciones de lectura y edición de datos en documentos XML
utilizando la arquitectura DOM, así como la evaluación de expresiones XPath
mediante XPathNavigator.

TEMARIO

o Proceso de lectura y escritura un DataSet utilizando un archivo XML

o Proceso de carga y lectura de XML Document en un DOM.

o Grabación y modificación de datos en un archivo XML.

o Proceso para seleccionar datos XML mediante XPathNavigator.

o Proceso para evaluar expresiones XPath utilizando XPathNavigator.

ACTIVIDADES PROPUESTAS

• Los alumnos guardan y leen datos en XML en un DataSet utilizando XML


Schema.
• Los alumnos manejan los métodos WriteXml y ReadXml.
• Los alumnos manejan los datos XML utilizando DOM.
• Los alumnos manejan el objeto XmlDocument en un DOM para grabar y
modificar los datos de un archivo XML utilizando DOM.

CIBERTEC CARRERAS PROFESIONALES


178

1 XML
El lenguaje de marcado extensible (XML) es un lenguaje que proporciona un formato
para describir datos. Con ello se facilita la realización de declaraciones de contenido
más precisas y la obtención de resultados de búsqueda más significativos en varias
plataformas. Además, XML permite la separación de la presentación de datos.

XML es un subconjunto de SGML optimizado para la entrega a través de Web. Su


definición está recogida en el Consorcio W3C. Gracias a esta estandarización, se
garantiza que los datos estructurados son uniformes e independientes entre los
distintos proveedores y aplicaciones. En XML se usan hojas de estilos, como el
lenguaje XSL (Extensible Stylesheet Language, lenguaje de hojas de estilos
extensible) y CSS (Cascading Style Sheets, hojas de estilos en cascada) para mostrar
los datos en un explorador.

2 UTILIZACIÓN DE XML EN UN DATASET


Con ADO.NET es posible llenar un DataSet a partir de una secuencia o un
documento XML. Se puede utilizar la secuencia o el documento XML para
suministrar datos al DataSet, información de esquema o ambas cosas.

En una representación XML de un DataSet, los datos se escriben en XML y el


esquema, si está incluido en línea en la representación, se escribe utilizando el
lenguaje de definición de esquemas XML (XSD). XML y el esquema XML
proporcionan un formato cómodo para transferir el contenido de un DataSet a y
desde clientes remotos.

2.1 MODO DE SALVAR UN DATASET CON DATOS XML


La representación XML del DataSet puede ser escrito a un Archivo, un Stream,
un XmlWriter o una cadena. Esas elecciones proveen de gran flexibilidad de
cómo transportar el XML del DataSet.
Para obtener la representación XML del DataSet como una cadena,
utilice el método GetXml como se muestran en el siguiente ejemplo:

Dim XmlStr as String = Ds.Getxml()

El método Getxml() retorna la representación del DataSet sin esquema


(Schema). Para escribir la información del esquema desde el DataSet (como
XML Schema) a una cadena, utilice GetXmlSchema.

Para escribir un DataSet en un archivo, una secuencia o XmlWriter, utilice el


método WriteXml. El primer parámetro que se pasa a WriteXml es el destino
del resultado XML. En tabla se muestran las opciones de XmlWriteMode

Opción Descripción
Escribe el contenido del DataSet como datos XML sin un
IgnoreSchema
esquema XML.

Escribe el contenido del Dataset como datos XML con la


WriteSchema
estructura relacional como un esquema XML.

Escribe el DataSet completo como un DiffGram incluyendo los


DiffGram
valores originales y actuales.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 179

A continuación se muestra cómo escribir la representación XML de un


DataSet en un archivo:
• Definir un Archivo FileStream y un Objeto StreamWriter.
• Referenciar al StreamWriter. Al FileStream.
• Definir el DataSet dsxml.
• Escribir desde el DataSet al StreamWriter, de tipo WriteSchema.

Dim savefile As New SaveFileDialog


savefile.Filter = "Archivo XML|*.xml"
If savefile.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim sfile As New System.IO.StreamWriter(savefile.FileName)
Dim dsxml As New DsFacturas
dsxml.WriteXml(sfile, XmlWriteMode.WriteSchema)
sfile.Close()
End If

2.2 MODO DE ASIGNAR COLUMNAS A ELEMENTOS, ATRIBUTOS Y


TEXTO XML
Se puede especificar cómo se representará en XML una columna de una
tabla, si se utiliza la propiedad ColumnMapping del objeto DataColumn. En
la siguiente tabla, se muestran los distintos valores de MappingType para la
propiedad ColumnMapping de una columna de tabla y el código XML
resultante.

Tipo Descripción

Valor Predeterminado. La columna se escribe como un elemento


XML, donde ColumnName es el nombre del elemento y el
Element contenido se escribe como el texto, ejemplo:
<ColumnName>Texto</ColumnName>

La columna se escribe como atributo XML del elemento XML


Attribute para la fila actual, ejemplo:
<RowElement ColumnName=”texto” />

El contenido de la columna se escribe como texto en el elemento


SimpleContent XML del a fila actual, ejemplo:
<RowElement> Texto </RowElement>

Hidden La columna no se escribe en el resultado XML.

2.4 DATARELATIONS ANIDADAS


En una representación relacional de datos, las tablas individuales contienen
filas que están relacionadas entre sí por una columna o un conjunto de
columnas. En el DataSet, la relación entre tablas se implementa mediante una
DataRelation. En la representación jerárquica de los datos proporcionada por
XML, las relaciones primaria-secundaria se representan mediante elementos
primarios que contienen elementos secundarios anidados.
Al establecer la propiedad Nested de una DataRelation como true, las filas
secundarias de la relación se anidan dentro de la columna primaria cuando se
escriben como datos XML o cuando se sincronizan con un
XmlDataDocument.

CIBERTEC CARRERAS PROFESIONALES


180

La propiedad Nested de la DataRelation es false de manera


predeterminada.

Dim ds As New DataSet


Dim da As New SqlDataAdapter("Select * from clientes", cn)
da.Fill(ds, "Clientes")
da = New SqlDataAdapter("Select * from dbo.fac_cabe", cn)
da.Fill(ds, "f")
Dim drel As New DataRelation("r1", ds.Tables("clientes"). _
Columns("cli_codigo"),ds.Tables("f").Columns("cli_codigo"))
'Agregar la relacion
drel.Nested = True
ds.Relations.Add(drel)
Dim sw As New System.IO.StreamWriter("C:\xmldata.xml")
ds.WriteXml(sw)
sw.Close()

2.5 FORMA DE CARGAR UN DATASET DESDE UN XML


Para rellenar un DataSet con datos XML, utilice el método ReadXml del objeto
DataSet. El método ReadXml lee desde un archivo, una secuencia o un
XmlReader y toma como argumentos el origen de XML y un argumento
XmlReadMode opcional.
El método ReadXml lee el contenido de la secuencia o el documento XML y
carga datos en el DataSet. También, crea el esquema relacional del DataSet
dependiendo del XmlReadMode especificado y de si ya existe o no un
esquema relacional.
La siguiente tabla describe las opciones de los argumentos de
XmlReadMode.

Modo Descripción
Valor predeterminado. Examina el código XML y elige la opción mas
apropiada en el orden:
Auto 1. Si el codigo XML es DiffGram, utiliza DiffGram.
2. Si el DataSet contiene un esquema XML, utiliza ReadSchema.
3. Si el DataSet no contiene esquema, utiliza InferSchema.
Si el DataSet ya contiene esquema, se agregan nuevas tablas del
ReadSchema esquema en línea al esquema existente en el DataSet. Si el DataSet
no contiene esquema de una tabla, no se leerá ningún dato.
Pasa por alto cualquier esquema en línea y carga los datos en el
IgnoreSchema
esquema del DataSet existente.
Pasa por alto cualquier esquema en línea, deduce el esquema por
InferShema
la estructura de datos XML y carga los datos.
Lee un DiffGram y agrega los datos al esquema actual. DiffGram
DiffGram combina las filas nuevas con las filas existentes en las que
coinciden los valores de identificador.
Sigue leyendo varios fragmentos de XML hasta llegar al final de la
Fragment
secuencia.

En el presente ejemplo, vamos a cargar en un DataSet llamado ds, desde


una secuencia xml: xmldata.
Dim ds As New DataSet
ds.ReadXml("C:\xmldata.xml", XmlReadMode.ReadSchema)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 181

En el siguiente ejemplo vamos a cargar una cadena xml que contiene


algunos de los distritos de Lima para convertirla en un DataSet y
visualizarla en un DataGridView:
a. Definir e instanciar un DataSet.
b. Definir un DataTable y agregarle dos columnas: id y nombre.
c. Agregar la Tabla al DataSet.
d. Definir una cadena xmlData y asignarle una estructura xml, observen la
estructura <dt></dt>, es la tabla; <id>01</id> campo1 y
<nombre>Lima</nombre> campo 2.
e. Definir un objeto StringReader y asignarle el valor de xmlData.
f. Ejecutar el Metod ReadXml del DataSet, utilizando el Stream y el
esquema de tipo ReadSchema. Visualizar la Tabla.
Dim dataSet As DataSet = New DataSet
Dim dataTable As DataTable = New DataTable("dt")
dataTable.Columns.Add("id", Type.GetType("System.String"))
dataTable.Columns.Add("nombre", Type.GetType("System.String"))
dataSet.Tables.Add(dataTable)
Dim xmlData As String
xmlData= "<XmlDS><dt><id>01</id><nombre>Lima</nombre></dt>"
xmlData += "<dt><id>02</id><nombre>Lince</nombre></distrito>"
xmlData += "<dt><id>03</id><nombre>Ate</nombre></dt></XmlDS>"
Dim xmlSR As New System.IO.StringReader(xmlData)
dataSet.ReadXml(xmlSR, XmlReadMode.ReadSchema)
Me.DGVendedor.DataSource = dataSet.Tables(0)

3 MANEJO DEL ESQUEMA DE UN DATASET


3.1 FORMA DE GUARDAR LA INFORMACION DEL ESQUEMA DEL
DATASET COMO UN ESQUEMA XML
Puede escribir el Esquema de un DataSet (tablas, columnas, relaciones y
constraints) como XML. El esquema XSD permite transportarlos con o sin data
relacional en un Documento XML. XML Schema puede ser escrito en un File,
Stream, XmlWriter, una cadena generando un DataSet Tipeado.
Para escribir el Esquema del un DataSet como XML Schema, utilice el
metodo WriteSchema de DataSet.
El siguiente ejemplo muestra como escribe el esquema XML del DataSet al
archivo distritos.xsd creado por un FileStream.
Dim filedistrito As New
System.IO.FileStream("C:\distritos.xsd", IO.FileMode.Create)
dataSet.WriteXmlSchema(filedistrito)
filedistrito.Close()

3.2 FORMA DE CARGAR LA INFORMACION DE ESQUEMA DE


DATASET DESDE UN ESQUEMA XML
El esquema de un DataSet (sus tablas, columnas, relaciones y restricciones)
se puede definir mediante programación, crear mediante los métodos Fill o
FillSchema de un DataAdapter o cargar desde un documento XML.

CIBERTEC CARRERAS PROFESIONALES


182

Para cargar información de esquema de un DataSet desde un documento


XML puede utilizar el método ReadXmlSchema o InferXmlSchema del
DataSet.
3.2.1 ReadXmlSchema
Para cargar el esquema de un DataSet desde un documento XML sin
cargar ningún dato, puede utilizar el método ReadXmlSchema del
DataSet. ReadXmlSchema crea el esquema del DataSet definido
mediante el esquema del lenguaje de definición de esquemas XML (XSD).

Mientras que ReadXmlSchema carga o deduce únicamente el esquema de


un DataSet, el método ReadXml del DataSet carga o deduce el esquema y
los datos contenidos en el documento XML.

En el ejemplo, se muestra cómo cargar el esquema de un DataSet


desde un documento XML utilizando un objeto
System.IO.StreamReader.

Imports System.IO
Dim xmlStream As New StreamReader("C:\distritos.xsd")
Dim ds As New DataSet
dataSet.ReadXmlSchema(xmlStream)
xmlStream.Close()

3.2.2 InferXmlSchema
También, puede indicar al DataSet que deduzca su esquema a partir de un
documento XML mediante el método InferXmlSchema del DataSet.
InferXmlSchema funciona del mismo modo que ReadXml con un
XmlReadMode de InferSchema (carga datos y deduce el esquema) y
ReadXmlSchema, si el documento que se lee no contiene ningún
esquema en línea. Sin embargo, InferXmlSchema ofrece la posibilidad
adicional de especificar que se pasen por alto determinados espacios de
nombres XML cuando se deduzca el esquema.

Por ejemplo, tomemos el siguiente código XML:

<NewDataSet xmlns:od="urn:schemas-microsoft-
com:officedata">
<Categories>
<CategoryID od:adotype="3">1</CategoryID>
<CategoryName od:maxLength="15" od:adotype="130">
Beverages</CategoryName>
<Description od:adotype="203">Gaseosas</Description>
</Categories>
<Products>
<ProductID od:adotype="20">1</ProductID>
<ReorderLevel od:adotype="3">10</ReorderLevel>
<Discontinued od:adotype="11">0</Discontinued>
</Products>
</NewDataSet>

Para asegurarse de que el esquema inferido pasa por alto los


atributos especificados en los elementos XML, utilice el método
InferXmlSchema y especifique que se debe pasar por alto el espacio
de nombres XML para officedata, como se muestra en el siguiente
ejemplo:

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 183

Dim dataSet As New DataSet


dataSet.InferXmlSchema("input_od.xml", New String[]
{"urn:schemas-microsoft-com:officedata"})

4 MODELO DE OBJETOS DE DOCUMENTO XML (DOM)


La clase modelo de objetos de documento XML (DOM) es una representación en la
memoria de un documento XML. DOM permite leer, manipular y modificar un
documento XML mediante programación. La clase XmlReader también lee XML,
aunque proporciona acceso de sólo avance y de sólo lectura sin almacenamiento
en memoria caché.

A continuación se muestran datos XML:

<?xml version="1.0"?>
<books>
<book>
<author>Carson</author>
<price format="dollar">31.95</price>
<pubdate>05/01/2001</pubdate>
</book>
<pubinfo>
<publisher>MSPress</publisher> <state>WA</state>
</pubinfo>
</books>

En la ilustración siguiente se muestra cómo se estructura la memoria cuando se


leen estos datos XML en la
estructura DOM.
Dentro de la estructura de los
documentos XML, cada círculo
de esta ilustración representa
un nodo, que se denomina
objeto XmlNode. El objeto
XmlNode es el objeto básico
del árbol de DOM.
La clase XmlDocument, que
extiende la clase XmlNode,
admite métodos para realizar
operaciones en el documento en conjunto. Además, la clase XmlDocument
proporciona un medio para ver y manipular los nodos de todo el documento XML.
Las clases XmlNode y XmlDocument han mejorado el rendimiento y la capacidad
de uso y disponen de métodos y propiedades para realizar lo siguiente:
• Obtener acceso y modificar nodos específicos de DOM, como nodos de
elemento, de referencia de entidad, etc.
• Recuperar nodos completos, además de la información que contiene el nodo,
como el texto de un nodo de elemento.

5 CARGA DE UN XMLDOCUMENT EN UN ARBOL DOM


La información en Xml es leído en la memoria desde diferente formato. Puede ser
leído desde una cadena, un stream, a URL, un text reader o una clase derivada
desde el XmlReader.
XmlDocument tiene dos métodos para cargar XML, el método Load carga en la
memoria; el método LoadXml leer los datos desde una cadena.

CIBERTEC CARRERAS PROFESIONALES


184

El XmlDocument es cargada utilizando el método Load y un parámetro de un


XmlReader. El método Load acepta los siguientes parámetros:
• Stream
• String
• TextReader
• XmlReader
El método Load solo checkea si el XMl esta bien formado.

El siguiente ejemplo carga un documento XML llamado “book.xml” y


validarlo contra un documento de esquema XML llamado “book.xsd”.

Dim doc as New XmlDocument()


Dim settings as New XmlReader Settings()
Settings.Schemas.Add(Nothing, “book.xsd”)
Settings.validationType=ValidationType.Schema
Dim reader as XmlReader=XmlReader.Create(“book.xml”, settings)
doc.Load(reader)

El siguiente ejemplo carga datos XML directamente desde una cadena.

Dim doc As New XmlDocument()


doc.LoadXml("<book genre='novel' ISBN='1-861001-57-5'>" & _
"<title>Pride And Prejudice</title></book>")
‘Guardar el documento a un Archivo.
doc.Save("data.xml")

5.1 PROPIEDADES Y MÉTODOS DEL XMLDOCUMENT


A continuación mostramos los métodos más importantes del XMLDocument.

Nombre Descripción

Agrega el nodo especificado al final de la lista


AppendChild
de nodos secundarios de este nodo.
Clone Crea un duplicado de este nodo.
CreateAttribute Crea objeto XmlAttribute con nombre especificado.
CreateDocumentType Devuelve un nuevo objeto XmlDocumentType.
CreateElement Sobrecargado. Crea un objeto XmlElement.
Crea un nuevo objeto XPathNavigator para
CreateNavigator
desplazarse por este documento.
CreateNode Sobrecargado. Crea un objeto XmlNode.
CreateTextNode Crea un objeto XmlText con el texto especificado.
CreateXmlDeclaration Crea nodo XmlDeclaration con valores específicos.
Obtiene el XmlElement con el identificador
GetElementById
especificado.
Devuelve un objeto XmlNodeList que contiene una
GetElementsByTagName lista de todos los elementos descendientes que
coinciden con el nombre especificado.
Proporciona funcionalidad para la iteración de
GetEnumerator
estilo "foreach" en los nodos de XmlNode.
Inserta el nodo especificado inmediatamente detrás
InsertAfter
del nodo de referencia igualmente especificado.
Inserta el nodo especificado inmediatamente antes
InsertBefore
del nodo de referencia igualmente especificado.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 185

Load Sobrecargado. Carga los datos XML especificados.


LoadXml Carga el documento XML desde un archivo.
Quita todos los atributos y nodos secundarios del
RemoveAll
nodo actual.
RemoveChild Quita el nodo secundario especificado.
Save Guarda el documento XML en archivo especificada.
Selecciona una lista de nodos que coinciden con la
SelectNodes
expresión XPath.
Selecciona el primer XmlNode que coincide con la
SelectSingleNode
expresión XPath.
Devuelve una clase String que representa la clase
ToString
Object actual.
Guarda el nodo XmlDocument en el XmlWriter
WriteTo
especificado.

Las propiedades más importantes del XMLDocument.

Nombre Descripción

Obtiene un objeto XmlAttributeCollection que contiene


Attributes
los atributos de este nodo.

BaseURI Obtiene el URI base del nodo actual.

ChildNodes Obtiene todos los nodos secundarios del nodo.

DocumentElement Obtiene el XmlElement raíz del documento.

FirstChild Obtiene el primer nodo secundario del nodo.

Obtiene un valor que indica si este nodo tiene nodos


HasChildNodes
secundarios.

Obtiene o establece los valores concatenados del nodo


InnerText
y de todos sus nodos secundarios.

Obtiene o establece el marcado que representa los


InnerXml
nodos secundarios del nodo actual.

Item Obtiene el elemento secundario especificado.

LastChild Obtiene el último nodo secundario del nodo.

Obtiene el identificador URI de espacio de nombres de


NamespaceURI
este nodo.

Obtiene el objeto XmlNameTable asociado a esta


NameTable
implementación.

NodeType Obtiene el tipo del nodo actual.

Obtiene el marcado que representa este nodo y todos


OuterXml
sus nodos secundarios.

Obtiene el nodo primario de este nodo, en los nodos


ParentNode
que pueden tener nodos primarios.

Obtiene o establece el objeto XmlSchemaSet asociado


Schemas
con este objeto XmlDocument.

Value Obtiene o establece el valor del nodo.

CIBERTEC CARRERAS PROFESIONALES


186

5.2 LECTURA DE DATOS XML UTILIZANDO DOM


EL DOM es una representación en la memoria de un documento XML. DOM
permite leer, manipular y modificar un documento XML mediante programación,
así como la navegación y edición de un documento.
La clase XmlDataDocument extiende XmlDocument y permite datos
estructurados para almacenar, recuperar y manipular a través de un DataSet
relacional. Esta clase permite componentes mezclar XML y vistas relacionales de
la data. Para leer datos en XML utilizando DOM, puede recuperar las secciones
de un documento recuperando los nodos del documento.

5.3 ACCEDIENDO A LA COLECCIÓN DE NODES EN


NAMEDNODEMAPS Y NODELISTS
Puede actualizar un conjunto de nodos y colocar en una colección ordenada o no
ordenada.
Cuando coloca un conjunto de nodos en una colección no ordenada, el conjunto
es llamado un NamedNodeMap por la W3C. Puede recuperar la data ordenada
por el nombre o índex en este tipo de colección. Colocar un conjunto de nodes
en una colección ordenada es llamado NodeList y la data puede recuperarse por
un índice de base cero (zero-based).
NamedNodeMaps es implementado por la clase XmlNamedNodeMap y
NodeList es implementado por la clase XmlNodeList.

5.4 RECUPERACIÓN DE NODOS DESORDENADOS POR ÍNDICE


XmlNamedNodeMap controla un conjunto de nodos desordenado con la
capacidad de hacer referencia a los mismos mediante su nombre o índice. Hay
tres métodos o propiedades que devuelven un XmlNamedNodeMap:
• XmlElement.Attributes.
• XmlDocumentType.Entities.
• XmlDocumentType.Notations.
La propiedad XmlDocumentType.Entities obtiene la colección de nodos
XmlEntity declarada en la declaración de tipo de documento. Esta colección se
devuelve como XmlNamedNodeMap y se puede recorrer en iteración mediante
la propiedad Count. También se puede mostrar información de entidad.

5.5 RECUPERACIÓN DE NODOS ORDENADOS POR ÍNDICE


La nodeList incluida en .NET Framework se denomina XmlNodeList. Los
métodos y propiedades que devuelve una XmlNodeList son los siguientes:
• XmlNode.ChildNodes.
• XmlDocument.GetElementsByTagName.
• XmlElement.GetElementsByTagName.
• XmlNode.SelectNodes.

XmlNodeList tiene una propiedad Count que se puede utilizar para escribir
bucles y recorrer en iteración los nodos de XmlNodeList.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 187

En el presente ejemplo, visualizaremos los nombres de los clientes que


se almacenan en el archivo xmldata.xml, donde este archivo ha sido
cargado desde la tabla de clientes.
Dim doc As New XmlDocument
doc.Load("C:\xmldata.xml") 'Recupera los Clientes
Dim root As XmlElement = doc.DocumentElement
Dim elemList As XmlNodeList = _
root.GetElementsByTagName("cli_nombre")
For i As Integer =0 To elemList.Count - 1
ListBox1.Items.Add(elemList.ItemOf(i).InnerXml)
Next

El metodo GetEnumerator permite la colección de nodos en el XmlNodeList:


For each nombre as xmlNode in elemList
'Visualizar los nombre de los Clientes.
ListBox1.Items.Add(nombre.InnerXml)
Next

5.6 ACCEDIENDO A LOS CHILD NODES


La propiedad XmlNode.ChildNodes es un XmlNodeList que contiene todos los
nodos hijos del node. Si no hay nodos hijos, el XmlNodeList retorna vacío.

En este ejemplo, retornamos los child node del elemento root.


Dim doc As New XmlDocument
doc.Load("C:\books.xml")
' Recupera todos los títulos de books
Dim root As XmlElement = doc.DocumentElement
If root.HasChildNodes Then Pregunta si
For i As Integer = 0 To root.ChildNodes.Count - 1 tiene Nodos
ListBox1.Items.Add(root.ChildNodes(i).InnerXml) hijos
Next
End If

5.7 RECUPERACIÓN DE LOS ATRIBUTOS EN UNA COLECCIÓN


Para obtener todos los atributos de un nodo de elemento en una colección, llame
a la propiedad XmlElement.Attributes. Los métodos y propiedades disponibles
en la colección incluyen, los disponibles en la asignación de nodo especificada,
además de los métodos y propiedades específicos de la clase
XmlAttributeCollection, como la propiedad ItemOf o el método Append. Para
buscar el número de atributos de un elemento, obtenga el
XmlAttributeCollection y utilice la propiedad Count para saber cuántos nodos
XmlAttribute hay en la colección.
El siguiente ejemplo de muestra cómo recuperar una colección de
atributos y cómo utilizar el método Count, además se muestra cómo
recuperar un solo atributo de la colección y mostrar su valor.
Dim docbook As New XmlDocument()
docbook.LoadXml("<book genre='novel' ISBN='1-861001-57-5'>" & _
"<title>Pride And Prejudice</title></book>")
Dim myElement As XmlElement = docbook.DocumentElement
Dim at As XmlAttributeCollection = myElement.Attributes
Dim str As String = ""
For i As Integer = 0 To attrColl.Count - 1
str = str + attrColl.ItemOf(i).Name + ":"
str = str + attrColl.ItemOf(i).Value.ToString + vbCrLf
Next
MessageBox.Show(str)

CIBERTEC CARRERAS PROFESIONALES


188

5.8 RECUPERACIÓN DE UN NODO DE ATRIBUTO INDIVIDUAL


El método XmlElement.GetAttributeNode devuelve un objeto de tipo
XmlAttribute. Una vez que se tiene el objeto XmlAttribute, todos los métodos y
propiedades de la clase están disponibles en ese objeto, como OwnerElement.

Dim doc As XmlDocument = New XmlDocument()


doc.LoadXml( _
"<book gr='terror' ISBN='1-857-5' misc='sale item'>" & _
"<title>Dracula</title><price>40.95</price></book>") Pregunto si
If doc.DocumentElement.HasAttributes Then tiene
' Mover a un elemento atributos.
Dim root As XmlElement = doc.DocumentElement
' Recuperar un atributo
Dim at As XmlAttribute = root.GetAttributeNode("ISBN") Recupero el
Dim at1 As XmlAttribute = root.GetAttributeNode("misc") valor del
' Visualizar el valor de los atributos atributo
Dim atV As String = at.InnerXml + vbCrLf + at1.InnerXml ISBN en at.
MessageBox.Show(atV)
End If

6 CREACIÓN DE UN DOCUMENTO XML EN UN ARBOL DOM


Existen dos métodos para crear un XML:
• Definir la instancia de XmlDocument sin parámetros.
• Definir la instancia de XmlDocument y pasarle un XmlNameTable como
parámetro.
Dim docbook As New XmlDocument()
DEFINICIÓN DE LA DECLARACIÓN XML
Un documento XML debe tener una declaración XML y un elemento raíz (root). La
clase XmlDocument tiene un metodo CreateXmlDeclaration que permite crear la
declaración CML, tiene los siguientes parámetros; Versión la versión debe ser”1.0”
, Encoding, el valor del atributo encoding, por defecto es UTF-8 y graba el
XmlDocument un archivo, stream y un conjunto de cadenas.
Los atributos son expuestos en el nodo XmlDeclaration y no como un nodo
XmlAttribute.
Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml("<book genre='novel' ISBN='1-861001-57-5' misc='sale
item'><title>The Ell cartero</title><price>14.95</price></book>")
Dim xmldec As XmlDeclaration = _
doc.CreateXmlDeclaration("1.0", Nothing, Nothing)
Dim root As XmlElement = doc.DocumentElement
doc.InsertBefore(xmldec, root)
doc.Save("C:\libros.xml")

La declaracion Definir el
es insertada XmlDeclation
antes del nodo. .

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 189

Al ejecutar el Proceso, la estructura Xml se visualiza:

<?xml version="1.0"?>
<book genre="novel" ISBN="1-861001-57-5" misc="sale item">
<title>The Handmaid's Tale</title>
<price>14.95</price>
</book>

7 MODIFICAR DATOS XML UTILIZANDO DOM


Puede modificar un documento insertando nuevos nodos. Los nodos insertados
creados recientemente, existirán en el mismo documento o puede ser importado
desde otro documento.

7.1 CREACIÓN DE NUEVOS NODOS EN EL DOM


Para crear el nodo, proporcione el método con un nombre cuando sea preciso,
y el contenido y otros parámetros para aquellos nodos que tengan contenido.
Los siguientes métodos crean un nodo apropiado.
• CreateCDataSection.
• CreateComment.
• CreateDocumentFragment.
• CreateDocumentType.
• CreateElement.
• CreateNode.
• CreateProcessingInstruction.
• CreateSignificantWhitespace.
• CreateTextNode.
• CreateWhitespace.
• CreateXmlDeclaration.
Otros tipos de nodos tienen más requisitos aparte de que se proporcionen datos
a los parámetros.
Una vez creados los nuevos nodos, hay disponibles varios métodos para
insertarlos en el árbol. En la tabla se enumeran los métodos con una
descripción de dónde aparece el nuevo nodo en el Modelo de objetos de
documento (DOM).

Método Colocación del nodo


InsertBefore Insertado antes del nodo de referencia.

InsertAfter Insertado después del nodo de referencia.

AppendChild Agrega el nodo al final de la lista de nodos secundarios del nodo especificado.

PrependChild Agrega el nodo al principio de la lista de nodos secundarios del nodo


especificado.

Append Agrega un nodo XmlAttribute al final de la colección de atributos asociada a un


elemento.

CIBERTEC CARRERAS PROFESIONALES


190

7.2 CÓMO QUITAR NODOS DEL DOM


Para quitar un nodo del Modelo de objetos de documento XML (DOM), utilice el
método RemoveChild para quitar un nodo específico. Cuando se quita un nodo,
el método quita el subárbol que pertenece al nodo que se está quitando; es
decir, no se trata de un nodo hoja.
Para quitar varios nodos del DOM, utilice el método RemoveAll para quitar
todos los atributos y nodos secundarios, si es preciso, del nodo actual.

En el siguiente ejemplo, eliminamos el primer elemento: <title>

Dim doc As XmlDocument = New XmlDocument()


doc.LoadXml("<book genre='novel' ISBN='1-861001-57-5' misc='sale
item'>"<title>El cartero</title><price>14.95</price></book>")
Dim node As XmlNode = doc.DocumentElement
node.RemoveChild(node.FirstChild)

7.3 MODIFICACIÓN DE NODOS, CONTENIDO Y VALORES EN UN


DOCUMENTO XML
Existen muchas formas de modificar los nodos y el contenido de un documento.
Puede:
• Cambiar el valor de los nodos utilizando la propiedad Value.
• Modificar un conjunto completo de nodos reemplazando los nodos por nodos
nuevos. Para ello, utilice la propiedad InnerXml.
• Reemplazar los nodos existentes por nuevos nodos utilizando el método
RemoveChild.
• Modificar el contenido eliminando un intervalo de caracteres utilizando el
método DeleteData en los tipos de nodos que heredan de
XmlCharacterData.
Una técnica muy sencilla para cambiar el valor de un nodo consiste en
utilizar node.Value = "new value". En la siguiente tabla se enumeran los
tipos de nodos en los que funciona esta línea de código y qué datos se
cambian exactamente para ese tipo de nodo.

Tipo de nodo Datos cambiados


Attribute El valor del atributo.

CDATASection El contenido de CDATASection.

Comment El contenido del comentario.

ProcessingInstruction El contenido, sin incluir el destino.

Text El contenido del texto.

XmlDeclaration El contenido de la declaración, sin incluir el marcado <?xml y ?>.

Whitespace El valor del espacio en blanco. Puede establecer este valor en uno de
los cuatro caracteres de espacio en blanco XML reconocidos: space,
tab, CR, o LF.

SignificantWhitespace El valor del espacio en blanco significativo. Puede establecer este valor
en uno de los cuatro caracteres de espacio en blanco XML reconocidos:
space, tab, CR, o LF.

Cualquier tipo de nodo que no se incluya en la tabla no es un tipo de nodo válido


para establecer un valor en él. Al establecer un valor en cualquier otro tipo de
nodo, se inicia una InvalidOperationException.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 191

La propiedad InnerXml cambia el marcado de los nodos secundarios del nodo


actual. Al establecer esta propiedad, los nodos secundarios se reemplazan por el
contenido analizado de la cadena especificada. InnerXml elimina las
declaraciones de espacios de nombres redundantes. Al utilizar los métodos
ReplaceData y RemoveChild, los métodos devuelven el nodo eliminado o
reemplazado. Luego, este nodo se puede volver a insertar en cualquier lugar del
modelo de objetos de documento (DOM) XML. El método ReplaceData realiza
dos comprobaciones de validación en el nodo que se va a insertar en el
documento.

8 GRABACIÓN DE UN DOCUMENTO XML

Cuando cargue y guarde un XmlDocument, el documento guardado puede ser


diferente al original de varias formas:
• Si la propiedad PreserveWhitespace se establece en true antes de llamar al
método Save, en el resultado se conserva el espacio en blanco del documento;
sin embargo, si la propiedad es false, XmlDocument, se aplica sangría
automáticamente al resultado.
• De manera predeterminada, el carácter de la comilla que se utiliza delante y
detrás de los valores de los atributos se cambia por la comilla doble. Puede
utilizar la propiedad QuoteChar en XmlTextWriterpara establecer el carácter
de la comilla como doble o simple.
• De manera predeterminada, se expanden las entidades de caracteres
numéricos como &#123.
• No se conserva la marca de orden de bytes del documento de entrada. UCS-2
se guarda como UTF-8 a menos que cree explícitamente una declaración XML
en la que se especifique otra codificación.
• La declaración XmlDeclaration sólo se escribe si hay alguna en el documento
y la codificación que se utiliza al escribir el documento es la misma que la del
nodo de la declaración.

8.1 ESCRIBIR UNA DECLARACIÓN XMLDECLARATION


Los miembros XmlDocument y XmlDeclaration de OuterXml, InnerXml y
WriteTo, además de los métodos XmlDocument de Save y WriteContentTo,
crean una declaración XML.
Para las propiedades XmlDocument de OuterXml, InnerXml, y los métodos
Save, WriteTo y WriteContentTo, la codificación escrita en la declaración XML
se obtiene del nodo XmlDeclaration.

Si no hay codificación en el nodo XmlDeclaration, la codificación no se


escribe en la declaración XML.

Dim doc As New XmlDocument()


Dim tw As XmlTextWriter = New XmlTextWriter("out.xml", Nothing)
doc.Load("text.xml")
doc.Save(tw)

CIBERTEC CARRERAS PROFESIONALES


192

LABORATORIO 13.1
GRABAR UN DATASET EN UN ARCHIVO XML
En este escenario, se solicita guardar la información de los clientes en un Archivo
XML. En dicho proceso se podrá realizar un filtro de los clientes por su nombre y los
registros resultados se deberán almacenar en un archivo XML.
1. Ingrese a Visual Studio 2005.
2. Seleccione File->New->Project.
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “WindowsApplication”.
- En “Name” coloque “appFacturacion06”.
- En “Location” coloque “C:\CursoPOOII”.
4. Arrastre los controles necesarios para diseñar el siguiente formulario como se
muestra en la figura: (Label, TextBox, Button y DataGriView).

5. Cambie los valores de las siguientes propiedades de los controles:

Control Propiedad Valor


TextBox1 Name txtCliente
Label1 Text Cliente
Button1 Name BtnXml
DataGridView1

6. Haga doble clic sobre el formulario para ingresar a la ventana de código.


Importe el namespace System.Data.SqlClient.

Imports System.Data.SqlClient

7. Dentro de la clase Form1 (Form1.vb), declare la conexión cn.


Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=BDFactura; integrated security=true")

8. Defina la función MisClientes, el cual filtrará los clientes por su nombre.


Function MisClientes(ByVal n As String) As DataTable
Dim dt As New DataTable
Dim da As New SqlDataAdapter("Select * from Clientes Where
cli_nombre like '" + n + "%'", cn)
da.Fill(dt)
Return dt
End Function

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 193

9. Dentro del evento Load del Form1, cargue el DataSet con la función

Me.DataGridView1.DataSource = MisClientes(Space(0))

10. Dentro del evento TextChanged del TextBox txtcliente, filtramos los clientes por
su nombre, donde utilizaremos la funcion MisClientes.

Me.DataGridView1.DataSource = MisClientes(txtcliente.Text)

11. Guarde los clientes en un Archivo XML, en el evento click del bóton BtnXml se
realizará dicho proceso. Se observa que utilizaremos una ventana de diálogo
que guardará el archivo XML.

Dim dsconsulta As New DataSet


dsconsulta.Tables.Add(CType(Me.DataGridView1.DataSource, DataTable))
Dim sv As New SaveFileDialog
sv.Filter = "Archivos XML|*.xml"
If sv.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim swriter As New System.IO.StreamWriter(sv.FileName)
dsconsulta.WriteXml(swriter, XmlWriteMode.WriteSchema)
swriter.Close()
End If
dsconsulta.Dispose()

12. Guarde la aplicación y ejecute. Compruebe la ejecución de la consulta

LABORATORIO 13.2
CARGAR UN DATOS CON DATOS XML
En este escenario aprenderemos a trabajar con archivos XML y visualizar los datos en
un DataSet, para ello se tiene un archivo xml llamado xmldata.xml.
1. Añada un Nuevo Formulario al Proyecto.
2. Sobre el Form2.vb, cree la siguiente interface de usuario:

CIBERTEC CARRERAS PROFESIONALES


194

3. Haga doble clic sobre el formulario para ingresar a la ventana de código.


Importe el namespace System.Data.SqlClient.
Imports System.Data.SqlClient

4. Dentro de la clase Form1 (Form1.vb), declare la conexión cn y un DataSet ds.


Private cn As New SqlConnection("Server=(local)\SQLEXPRESS;
DataBase=BDFactura; integrated security=true")
Private ds As New DataSet
5. Defina la función MisClientes, el cual filtrará los clientes por su nombre.
Function MisClientes(ByVal n As String) As DataTable
Dim dt As New DataTable
Dim da As New SqlDataAdapter("Select * from Clientes Where
cli_nombre like '" + n + "%'", cn)
da.Fill(dt)
Return dt
End Function

6. Dentro del evento click del botón Buscar Archivo XML, se abrirá un archivo de
tipo XML. Para esto utilice un cuadro de diálogo OpenFileDialog se leerá su
contenido y se guardará las tablas en el DataSet. Luego, procedemos a
mostrar las tablas que están en el DataSet en un ListBox: lbTablas.

Dim op As New OpenFileDialog


op.Filter = "Archivo xml|*.xml"
If op.ShowDialog = Windows.Forms.DialogResult.OK Then
ds.Tables.Clear()
Dim sw As New System.IO.StreamReader(op.FileName)
ds.ReadXml(sw)
sw.Close()
For Each dt As DataTable In ds.Tables
LbTablas.Items.Add(dt.TableName)
Next
End If
7. Dentro del evento SelectedIndexChanged del ListBox, se visualizará los
registros de la tabla que se ha seleccionado en el ListBox1.

If ListBox1.SelectedIndex > -1 Then


Me.DataGridView1.DataSource = ds.Tables(ListBox1.Text)
End If

8. Guarde la aplicación y ejecute. Compruebe la ejecución de la consulta.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 195

LABORATORIO 13.3
ACTUALIZACIÓN DE VALORES DE UN ARCHIVO XML
En este escenario, tenemos un archivo xml llamado “articulos.xml” donde almacena la
información de los precios de los artículos que vende y distribuye la empresa, se
solicita que los precios se incrementen en 10% con respecto a su valor original.
1. Ingrese a Visual Studio 2005.
2. Seleccione File->New->Project.
3. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “Windows Application”.
- En “Name” coloque “appFacturacion09”.
- En “Location” coloque “C:\CursoPOOII”.
4. En la parte superior de la clase, importar el namespace System.Xml.
5. Diseñe el Formulario.

Control Propiedad Valor


Button1 Text Buscar
Button1 Name BtnBuscar
Button2 Text Incrementar Precio
Button2 Name BtnIncrementarPrecio
DataGridView1

6. Declare, a nivel de Clase Form, un DataSet para cargar los datos de un archivo
XML, además definir una variable llamada filexml que almacenara la ubicación
del archivo de artículos.

Private ds As New DataSet


Dim filexml As String

7. En el botón buscar, procedemos a buscar un archivo XML utilizando un cuadro


de diálogo, cargamos el archivo en el DataSet y lo visualizamos en el
DataGridView.

CIBERTEC CARRERAS PROFESIONALES


196

Definir un
Dim op As New OpenFileDialog
StreamReader
op.Filter = "Archivo xml|*.xml"
If op.ShowDialog = Windows.Forms.DialogResult.OK Then para leer el
filexml = op.FileName archivo xml en
ds.Tables.Clear() filexml.
Dim sw As New System.IO.StreamReader(filexml)
ds.ReadXml(sw)
DataGridView1.DataSource = ds.Tables(0) Leer en el
sw.Close() DataSet el
End If StreamReader
y se visualiza
en DataGrid.
8. En el botón Incrementar precio, realizamos los siguientes procesos
a. Defina la instancia de un XmlDocument llamado myXml.
b. Cargue al XmlDocument myXml con el archivo xml en filexml.
c. Ejecute el procedimiento IncrementarPrecio, enviando como parámetro
al DocumentElement de myxml.
d. Si esta correcto el proceso, se abrirá un cuadro de diálogo para
guardar los precios actualizados en un archivo xml, donde se ejecutara
el método Save del objeto XmlDocument myXml.
e. Si ocurre una excepción: Catch, se lanzará una excepción donde se
visualizará el error de la excepción.

Try
Dim myXml As New XmlDocument() ' Crear un XmlDocument
myXml.Load(filexml)
IncrementarPrecio(myXml.DocumentElement)
Dim sdialog As New SaveFileDialog
sdialog.Filter = "Archivo XML|*.xml"
If sdialog.ShowDialog = Windows.Forms.DialogResult.OK Then
myXml.Save(sdialog.FileName)
End If
MessageBox.Show("Actualizado en " + sdialog.FileName)
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try

9. A continuación definimos el procedimiento IncrementarPrecio teniendo como


parámetro un XmlNode.
a. Pregunte si el node se llama art_precio: node.Name.
b. Si es así, capture el node en node.FirstChild.
c. Declare una variable price que recibira el valor de node: node.Value.
d. Declare una variable newprice que recibirá el valor incrementado de
price y el valor del nodo se le asigna newprice.
e. Este proceso continuará mientras el nodo (node) no este vacío,
entonces avanzara al siguiente nodo: node.NextSibling.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 197

Public Sub IncrementarPrecio (ByVal node As XmlNode)


If (node.Name = "art_precio") Then
node = node.FirstChild
Dim price As Decimal = System.Decimal.Parse(node.Value)
' Incrementar el precio de los libros en 10% mas
Dim newprice As String
newprice = CType(price*(New Decimal(1.1)), Decimal).ToString
node.Value = newprice
End If
node = node.FirstChild
While Not node Is Nothing
IncreasePrice(node)
node = node.NextSibling
End While
End Sub

10. Guarde el Proyecto, compruebe la ejecución del proceso.

LABORATORIO 13.4
LECTURA DE UN ARCHIVO XML
En este escenario vamos a leer cualquier archivo xml que este almacenado donde se
visualizará su estructura, así como los valores de los nodos.

1. Agrega un nuevo formulario al proyecto, cree la siguiente interfaz.

alor
tnBuscar
uscar
txml
2. Importar el
namespace System.Xml y el nameSpace System.IO.
3. En el botón buscar, se realizará la búsqueda de un archivo xml almacenando
su estructura en un XmlTextReader llamado xmlreader, a continuación,
ejecute el procedimiento FormatXml.

Dim op As New OpenFileDialog


op.Filter = "Archivo xml|*.xml"
If op.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim xmlreader As New XmlTextReader(op.FileName)
FormatXml(xmlreader, op.FileName)
End If
4. El método FormatXml, evalúa el tipo de nodo donde ejecutará el proceso
FormatXml según el tipo de nodo.

Private Sub FormatXml(ByVal r As XmlTextReader, ByVal fn As String)


While r.Read()
Select Case (r.NodeType)
Case XmlNodeType.DocumentType: Format(r, "DocumentType")
Case XmlNodeType.Element : Format(r, "Element")
Case XmlNodeType.Text : Format(r, "Text")
CIBERTEC End Select CARRERAS PROFESIONALES
End While
End Sub
198

5. El método Format imprimirá la estructura del nodo, sus elementos y sus


valores, tal como se muestra.

Private Sub Format(ByRef r As XmlTextReader, ByVal Tipo As String)


' Formato de salida
Dim str As String = r.Depth.ToString & " " & _
r.AttributeCount.ToString & vbCrLf
Dim i As Integer
For i = 0 To reader.Depth - 1
str += Strings.Chr(9)
Next
str += Tipo & "<" & r.Name & ">" & r.Value
'Visualiza los valores de los atributos del nodo actual
If (r.HasAttributes) Then
str += " Atributos:"
Dim j As Integer
For j = 0 To r.AttributeCount - 1
str += r(j).ToString
Next
End If
str += vbCrLf
txtxml.Text += str
End Sub

6. Guarde el proyecto y ejecute la aplicación.

Autoevaluación

1. ¿Cuál es el método que permite guardar un DataSet como Datos XML? Defina
sus opciones.

2. ¿Cómo se puede guardar DataRelations Anidadas? Explique con un ejemplo

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 199

3. ¿Cuál es el método que permite cargar un DataSet desde un archivo XML?


Explique cada uno de sus opciones

4. ¿Cuándo utilizamos WriteXmlSchema? Explique.

5. ¿Cuál es la diferencia entre un ReadXmlSchema y el InferXmlSchema?


Explique.

6. ¿Cómo se leen los datos XML utilizando DOM?

7. ¿Cuáles son los métodos que permite recuperar los nodos ordenados?

8. ¿Cuales son los métodos que permiten recuperar loas atributos de una
colección?

9. ¿Cómo se crea una declaración XML?

10. Implemente un Programa donde almacene los registros de


facturas de un artículo seleccionado; al seleccionar un
artículo en un control de lista, visualice las facturas
registradas. Almacene dichos resultados en un archivo
XML.

Resumen
 Con ADO.NET es posible llenar un DataSet a partir de una secuencia o un
documento XML. Se puede utilizar la secuencia o el documento XML para
suministrar datos al DataSet, información de esquema o ambas cosas.

 Para escribir un DataSet en un archivo, una secuencia o XmlWriter, utilice el


método WriteXml, el cual utiliza dos parámetros: el destino del resultado XML y el
modo de escritura que puede ser:
o DiffGram
o IgnoreSchema
o WriteSchema
 Para facilitar el anidamiento de objetos en un DataSet, el DataRelation expone una
propiedad Nested. Al establecer la propiedad Nested de una DataRelation como
true, las filas secundarias de la relación se anidan dentro de la columna primaria

CIBERTEC CARRERAS PROFESIONALES


200

cuando se escriben como datos XML o cuando se sincronizan con un


XmlDataDocument.

 Para rellenar un DataSet con datos XML, utilice el método ReadXml del objeto
DataSet. El método ReadXml lee desde un archivo, una secuencia o un
XmlReader y toma como argumentos el origen de XML y un argumento
XmlReadMode que es opcional.

 La clase XmlDataDocument extiende XmlDocument y permite datos


estructurados para almacenar, recuperar y manipular a través de un DataSet
relacional. Esta clase permite componentes mezclar XML y vistas relacionales de
la data.

 Un documento XML debe tener una declaración XML y un elemento raíz (root). La
clase XmlDocument tiene un metodo CreateXmlDeclaration que permite crear la
declaración CML, tiene los siguientes parámetros: Versión la versión debe
ser”1.0”, Encoding, el valor del atributo encoding, por defecto es UTF-8.

 Si desea consultar mas acerca de estos temas puede consultar las siguientes
paginas:

 http://msdn2.microsoft.com/es-es/library/84sxtbxh(VS.80).aspx
Página referente a utilizar datos XML en un DataSet

 http://msdn2.microsoft.com/es-es/library/7sfkwf9s(VS.80).aspx
Página referente a la relación de datos anidados

 http://msdn2.microsoft.com/es-es/library/atchhx4f(VS.80).aspx
Página referente a cargar información de datos en un DataSet

 http://msdn2.microsoft.com/es-es/library/azsy1tw2(VS.80).aspx
Página referente a la lectura de un documento XML en DOM

 http://msdn2.microsoft.com/es-es/library/hk61a712(VS.80).aspx
Página referente al acceso de atributos en DOM

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 201

UNIDAD DE
APRENDIZAJE

5
SEMANA

14

CONSULTA XML UTILIZANDO XPATH

LOGRO DE LA UNIDAD DE APRENDIZAJE

Al término de la unidad, los alumnos mediante aplicaciones Windows .NET


resuelven operaciones de lectura y edición de datos en documentos XML
utilizando la arquitectura DOM, así como la evaluación de expresiones XPath
mediante XPathNavigator.

TEMARIO

o Proceso de lectura y escritura un DataSet utilizando un archivo XML.

o Proceso de carga y lectura de XML Document en un DOM.

o Grabación y modificación de datos en un archivo XML.

o Proceso para seleccionar datos XML mediante XPathNavigator.

o Proceso para evaluar expresiones XPath utilizando XPathNavigator.

ACTIVIDADES PROPUESTAS

• Los alumnos realizan consultas y navegación por los nodos de un


Documento XML.
• Los alumnos realizan evaluaciones de expresiones XPath utilizando
XPathNavigator.
• Los alumnos editan los datos XML utilizando XPathNavigator.

CIBERTEC CARRERAS PROFESIONALES


202

1. PROCESAMIENTO DE DATOS XML CON EL MODELO XPATH


El espacio de nombres System.Xml proporciona una representación mediante
programación de documentos XML, fragmentos, nodos o conjuntos de nodos en
memoria utilizando las clases XmlDocument o XPathDocument.

La clase XPathDocument proporciona una representación en memoria rápida y de


sólo lectura de un documento XML utilizando el modelo de datos XPath. La clase
XmlDocument proporciona una representación en memoria editable de un
documento XML mediante la implementación de la parte principal del nivel 1 del
Modelo de objetos de documento (DOM) y el nivel 2 de la parte principal del DOM
del W3C. Ambas clases implementan la interfaz IXPathNavigable y devuelven un
objeto XPathNavigator que se utiliza para seleccionar, evaluar, desplazarse y, en
algunos casos, editar los datos XML subyacentes.

1.1 LECTURA DE DATOS XML CON XPATHDOCUMENT y


XMLDOCUMENT
La clase XPathDocument proporciona una representación en memoria
rápida y de sólo lectura de un documento XML utilizando el modelo de
datos XPath. Estos constructores permiten leer un documento XML
utilizando el objeto Stream, TextReader o XmlReader, así como la ruta
string a un archivo XML.

Dim Doc As New XPathDocument(”C:\book.xml”)

La clase XmlDocument es una representación en memoria editable de un


documento XML (W3C) y el nivel 2 de la parte principal del DOM. Puede
crear un objeto XmlDocument nuevo llamando al constructor de la clase
XmlDocument sin ningún parámetro.
Utilice el método Load para cargar datos XML en el objeto XmlDocument
desde un objeto Stream, TextReader o XmlReader, así como la ruta
string a un archivo XML.

Dim document As New XmlDocument()


document.Load ("books.xml")

1.2 CREAXION DEL OBJETOS XPATHNAVIGATOR


Después de haber leído un documento XML en un XPathDocument o
XmlDocument, puede crear un objeto XPathNavigator para seleccionar,
evaluar, desplazarse y, en algunos casos, editar los datos XML
subyacentes.
Las clases XPathDocument y XmlDocument, además de la clase
XmlNode, implementan la interfaz IXPathNavigable del espacio de
nombres System.Xml.XPath. Como resultado, las tres clases proporcionan
un método CreateNavigator que devuelve un objeto XPathNavigator.

Dim document As New XPathDocument()


Dim navegador As New XpathNavegator= document.CreateNavigator

1.2.1 Edición de documentos XML con XPathNavigator


La clase XPathNavigator se puede utilizar para editar un documento
XML en algunos casos, basándose en el objeto que lo ha creado.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 203

La clase XPathDocument es de sólo lectura, mientras que la clase


XmlDocument es editable. La propiedad CanEdit de la clase
XPathNavigator especifica si un objeto XPathNavigator puede editar
datos XML.
En la tabla se describe el valor de la propiedad CanEdit por clase.
Implementación de IXPathNavigable Valor CanEdit
XPathDocument False
XmlDocument Trae

1.2.3 Desplazamiento de XPathNavigator de un nodo a otro en XML


El código siguiente muestra la misma estructura de un formulario XML
tradicional.

<Basket>
<Item Desc="Uber Drill 9000">
<Category />
</Item>
<Item />
</Basket>

1.2.4 Selección de datos XML con XPathNavigator


La clase XPathNavigator tiene un conjunto de métodos que se
utilizan para seleccionar un conjunto de nodos de un objeto
XPathDocument o XmlDocument utilizando una expresión XPath.
Una vez seleccionado, puede iterar por el conjunto de nodos
seleccionado.

1.2.5 Métodos de selección de XPathNavigator


La clase XPathNavigator tiene métodos para seleccionar nodos
primarios, secundarios y descendientes más rápido que con XPath.

1.2.6 Selección de nodos con expresiones XPath


Para seleccionar un conjunto de nodos con una expresión XPath,
utilice uno de los siguientes métodos de selección.
• Select
• SelectSingleNode
Cuando se llama a estos métodos, éstos devuelven un conjunto de
nodos por los que puede desplazarse libremente utilizando un objeto

CIBERTEC CARRERAS PROFESIONALES


204

XPathNodeIterator o un objeto XPathNavigator en el caso de que


haya un solo nodo seleccionado.
El desplazamiento por un objeto XPathNodeIterator no afecta a la
posición del objeto XPathNavigator que se ha utilizado para crearlo.
El objeto XPathNavigator que devuelven los métodos
SelectSingleNode se sitúa en el único nodo devuelto y tampoco
afecta a la posición del objeto XPathNavigator que se ha utilizado
para crearlo.
Ejemplo, creamos un XPathNavigator a partir del
XPathDocument, utilizamos el método Select para seleccionar
todos los <book> que sean elementos hijos de <bookstore> en
el objeto XPathDocument y el uso del objeto
XPathNodeIterator para iterar por los nodos seleccionados.

Dim document As New XPathDocument("books.xml")


Dim navigator As XPathNavigator=document.CreateNavigator()
Dim nod As XPathNodeIterator= _
Navigator.Select("/bookstore/book")
Dim Str As String
While nod.MoveNext()
Str += nodes.Current.Name + vbCrLF
End While
MessageBox.Show(Str)

1.2.7 Uso el método SelectSingleNode para Seleccionar un Nodo.


El metodo SelectSingleNode selecciona el primer nodo que coincida
con la consulta XPath en el objeto XPatnNavigator.

En el siguiente ejemplo seleccionamos el primer elemento


<title>

Dim document As New XPathDocument("books.xml")


Dim nav As XPathNavigator = document.CreateNavigator()
Dim nod As XpathNavigator = _
Nav.SelectSingleNode("/bookstore/book/title")
MessageBox.Show(nod.InnerXml)

1.3 EVALUAR EXPRESIONES XPATH CON XPATHNAVIGATOR


XPathNavigator incluye el método Evaluate para evaluar una expresión
XPath. El método Evaluate toma una expresión XPath, la evalúa y
devuelve un tipo XPath del W3C de tipo booleano, numérico, de cadena o
de conjunto de nodos basándose en el resultado de expresión XPath.
El método Evaluate toma una expresión XPath, la evalúa y devuelve un
resultado con tipo de tipo booleano (Boolean), numérico (Double), de
cadena (String) o de conjunto de nodos (XPathNodeIterator).

Por ejemplo, el método Evaluate se podría utilizar en un método


matemático. El siguiente código de ejemplo calcula el precio total de
todos los libros del archivo books.xml.

Dim document As New XPathDocument("C:\books.xml")


Dim nav As XPathNavigator = document.CreateNavigator()
Dim query As XPathExpression = nav.Compile("sum(//price/text())")
Dim total As Double = CType(nav.Evaluate(query), Double)
MessageBox.Show(total.toString)

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 205

El método Evaluate tiene una sobrecarga que toma dos parámetros:


o XPathExpression expresión a ser evaluada.
o XPathNodeIterator nodos seleccionados que seran evaluados.

En el ejemplo, se evalúa la expresión XPathExpression y devuelve


un valor de tipo Double mediante el nodo Current de
XPathNodeIterator como nodo de contexto.
Dim document As New XPathDocument("C:\books.xml")
Dim nav As XPathNavigator = document.CreateNavigator()
Dim nodes As XpathNodeIterator = nav.Select("//book")
Dim query As XPathExpression = _
nodes.Current.Compile("sum(descendant::price)")
Dim total As Double = CType(nav.Evaluate(query,nodes), Double)
MessageBox.Show(total.toString)

1.4 EXPRESIONES XPATH COMPILADAS


XPathExpression representa consulta XPath compilada devuelta desde el
método Compile estático de la clase XPathExpression o desde el método
Compile de la clase XPathNavigator.

1.4.1 La clase XPathExpression


Una consulta XPath compilada que representa a XPathExpression es
útil si esa misma consulta XPath se utiliza más de una vez.
Compilado, el objeto XPathExpression se puede utilizar como entrada
en los siguientes métodos de la clase XPathNavigator dependiendo
del tipo devuelto desde la consulta XPath.
• XPathNavigator.Evaluate(.XPathExpression)
• XPathNavigator.Evaluate(XPathExpression,XPathNodeIterator)
• Matches
• Select
• SelectSingleNode
En la tabla se describe cada uno de los tipos de valores devueltos de
XPath del W3C, sus equivalencias en Microsoft .NET Framework y con
qué métodos se puede utilizar el objeto XPathExpression.
Tipo de valor
devuelto de Tipo equivalente en
XPath del W3C .NET Framework Descripción Métodos

Node set XPathNodeIterator Colección no ordenada de nodos Select o Evaluate


sin duplicados creados en el orden
del documento.

Boolean Boolean Un valor true o false. Evaluate o


Matches

Number Double Número punto flotante. Evaluate

String String Una secuencia de caracteres UCS. Evaluate

1.4.2 La propiedad ReturnType


Compilada la consulta XPath en un objeto XPathExpression, puede
utilizar la propiedad ReturnType del objeto XPathExpression para
determinar qué devuelve la consulta XPath.

CIBERTEC CARRERAS PROFESIONALES


206

La propiedad ReturnType devuelve uno de los siguientes valores de


enumeración XPathResultType que representan los tipos de valores
devueltos de XPath del W3C.
• Any
• Boolean
• Error
• Navigator
• NodeSet
• Number
• String

En el ejemplo, se utiliza el XPathExpression para devolver un


número y un conjunto de nodos desde el archivo books.xml. La
propiedad ReturnType de cada objeto XPathExpression, así
como los resultados de los métodos Evaluate y Select.
Dim document As New XPathDocument("books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
' Retorna un número.
Dim query1 As XPathExpression = _
navigator.Compile("bookstore/book/price/text()*10")
Dim number As Double = CType(navigator.Evaluate(query1), Double)
' Retorna un Nodo.
Dim query2 As XPathExpression = _
navigator.Compile("bookstore/book/price")
MessageBox.Show(query2.ReturnType.toString)
Dim nodes As XPathNodeIterator = navigator.Select(query2)
nodes.MoveNext()

1.5 EXPRESIONES XPATH DE MAYOR RENDIMIENTO


Para mejorar el rendimiento, utilice la expresión XPath lo más específica
posible en las consultas. Por ejemplo, si el nodo book es un nodo
secundario del nodo bookstore y el nodo bookstore es el elemento
superior de un documento XML, es más rápido utilizar la expresión XPath
/bookstore/book que //book. La expresión XPath //book examinará cada
nodo del árbol XML para identificar nodos coincidentes.
Además, el uso de métodos de desplazamiento por conjuntos de nodos
que proporciona la clase XPathNavigator, puede producir una mejora del
rendimiento con respecto a los métodos de selección que proporciona la
clase XPathNavigator en los casos en los que los criterios de selección
sean sencillos.

Por ejemplo, si tiene que seleccionar el primer nodo secundario del


nodo actual, es más rápido utilizar el método MoveToFirst que la
expresión XPath child::*[1] y el método Select.

Dim document As New XPathDocument("books.xml")


Dim nav As XPathNavigator = document.CreateNavigator()
' Seleccionar todos los atributos ISBN
Dim exp As XPathExpression=nav.Compile("bookstore/book/@bk:ISBN")
Dim nsmgr As New XmlNameSpaceManager(nav.NameTable)
Nsmgr.AddNameSpace("bk","urn:samples")
Exp.SetContext(nsmgr)
' Visualizamos la selección
Dim iterator As XPathNodeIterator = nav.Select(exp)
While iterator.MoveNext()
MessageBox.Show (iterator.Current.toString)
End While

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 207

2. EDICIÓN DE DATOS XML CON XPATHNAVIGATOR


La clase XPathNavigator proporciona métodos para insertar, modificar y quitar
nodos y valores de un documento XML contenido en un objeto XmlDocument.
Para poder utilizar cualquiera de estos métodos para insertar, modificar y quitar
nodos y valores, el objeto XPathNavigator debe ser editable, es decir, su
propiedad CanEdit debe ser true.

2.1 INSERCION DE DATOS XML CON XPATHNAVIGATOR


La clase XPathNavigator incluye un conjunto de métodos que se utilizan
para insertar nodos de atributos, secundarios y relacionados en un
documento XML. Para utilizar estos métodos, el objeto XPathNavigator
debe ser editable, es decir, su propiedad CanEdit debe ser true.

La clase XPathNavigator incluye los siguientes métodos para insertar


nodos relacionados.
• InsertAfter
• InsertBefore
• InsertElementAfter
• InsertElementBefore
Los métodos InsertAfter e InsertBefore aceptan un objeto string,
XmlReader, o un objeto XPathNavigator que contiene el nodo relacionado
para agregarlos como parámetros. Ambos métodos también devuelven un
objeto XmlWriter que se utiliza para insertar nodos relacionados.
Los métodos InsertElementAfter e InsertElementBefore insertan un solo
nodo relacionado antes y después del nodo en el que está situado
actualmente un objeto XPathNavigator, utilizando como parámetros el
prefijo de espacio de nombres, el nombre local, el identificador URI de
espacio de nombres y el valor especificado.
Dim document As XmlDocument = New XmlDocument()
document.Load("C:\books.xml")
Dim nav As XPathNavigator = document.CreateNavigator()
nav.MoveToChild("bookstore", "http://www.contoso.com/books")
nav.MoveToChild("book", "http://www.contoso.com/books")
nav.MoveToChild("price", "http://www.contoso.com/books")
'Inserta un elemento despues de price
nav.InsertAfter("<pages>100</pages>")
nav.MoveToParent()
MessageBox.Show(nav.OuterXml)

2.2 INSERCION DE NODOS SECUNDARIOS


XPathNavigator incluye métodos para insertar nodos secundarios.
• AppendChild
• PrependChild
• AppendChildElement
• PrependChildElement
Los métodos AppendChild y PrependChild aceptan un objeto string,
XmlReader o un objeto XPathNavigator que contiene el nodo secundario,
para agregarlos como parámetros. Ambos métodos también devuelven un
objeto XmlWriter que se utiliza para insertar nodos secundarios.
Los métodos AppendChildElement y PrependChildElement insertan un
solo nodo secundario al final y al principio de la lista de nodos secundarios
del nodo en el que se encuentra situado actualmente un objeto

CIBERTEC CARRERAS PROFESIONALES


208

XPathNavigator, utilizando como parámetros el prefijo de espacio de


nombres, el nombre local, el identificador URI de espacio de nombres y el
valor especificado.

En el ejemplo, se agrega un nuevo elemento secundario pages a


la lista de elementos secundarios del primer elemento book en
Books.xml.
Dim document As XmlDocument = New XmlDocument()
document.Load("C:\books.xml")
Dim navig As XPathNavigator = document.CreateNavigator()
navig.MoveToChild("bookstore", "http://www.contoso.com/books")
navig.MoveToChild("book", "http://www.contoso.com/books")
navig.AppendChild("<pages>100</pages>")
MessageBox.Show(navigator.OuterXml)

2.3 INSERCION DE NODOS DE ATRIBUTOS


XPathNavigator incluye métodos para insertar nodos de atributos.
• CreateAttribute
• CreateAttributes
Estos métodos insertan nodos de atributos en el nodo de elementos en el
que está situado actualmente un objeto XPathNavigator.
El método CreateAttribute crea un nodo de atributos en el nodo de
elementos en el que está situado actualmente un objeto XPathNavigator,
utilizando como parámetros el prefijo de espacio de nombres, el nombre
local, el identificador URI de espacio de nombres y el valor especificado. El
método CreateAttributes devuelve un objeto XmlWriter que se utiliza para
insertar nodos de atributos.

En el ejemplo se crean nuevos atributos discount y currency en el


elemento secundario price del primer elemento book de Books.xml
utiliza el objeto XmlWriter devuelto desde el método
CreateAttributes.

Dim document As XmlDocument = New XmlDocument()


document.Load("C:\books.xml")
Dim navig As XPathNavigator = document.CreateNavigator()
navig.MoveToChild("bookstore", "http://www.contoso.com/books")
navig.MoveToChild("book", "http://www.contoso.com/books")
navig.MoveToChild("price", "http://www.contoso.com/books")

Dim attributes As XmlWriter = navigator.CreateAttributes()


attributes.WriteAttributeString("discount", "1.00")
attributes.WriteAttributeString("currency", "USD")
attributes.Close()
navigator.MoveToParent()
MessageBox.Show(navigator.OuterXml)

2.4 OPERACIONES DE LA COPIA DE NODOS


XPathNavigator como XmlWriter pueden copiar nodos en un objeto
XmlDocument desde un XmlReader existente o XPathNavigator.
Los métodos AppendChild, PrependChild, InsertBefore y InsertAfter
de la clase XPathNavigator tienen sobrecargas que pueden aceptar
como parámetro un objeto XPathNavigator o un objeto XmlReader.
El método WriteNode de la clase XmlWriter tiene sobrecargas que
pueden aceptar un objeto XmlNode, XmlReader o XPathNavigator.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 209

En el siguiente ejemplo se copian todos los elementos book de un


documento a otro llamado newbooks.xml.
Dim document As XmlDocument = New XmlDocument()
document.Load("C:\books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", String.Empty)
Dim newBooks As XPathDocument = New XPathDocument("C:\newBooks.xml")
Dim newBooksNavigator As XPathNavigator = newBooks.CreateNavigator()
Dim nav As XPathNavigator
For Each nav In newBooksNavigator.SelectDescendants("book","",False)
navigator.AppendChild(nav)
Next
document.Save("C:\newBooks.xml")

2.5 MODIFICACION DE DATOS CON XPATHNAVIGATOR


Incluye métodos para modificar nodos y valores en un documento XML.
Para utilizar estos métodos, el objeto XPathNavigator debe ser editable,
es decir, su propiedad CanEdit debe ser true.

2.5.1 Modificación de nodos


Para cambiar el valor de un nodo consiste en utilizar los métodos
SetValue y SetTypedValue de la clase XPathNavigator.
En la tabla se enumeran los efectos de estos métodos en diferentes
tipos de nodos.
XPathNodeType Datos cambiados

Root No admitido.
Element El contenido del elemento.
Attribute El valor del atributo.
Text El contenido del texto.
ProcessingInstruction El contenido, sin incluir el destino.
Comment El contenido del comentario.
Namespace No admitido.

2.5.2 Modificación de valores sin información de tipos


El método SetValue simplemente inserta el valor string sin
información de tipos, que se pasa como parámetro, como valor del
nodo en el que se encuentra situado actualmente el objeto
XPathNavigator.
En el siguiente ejemplo, el método SetValue se utiliza para
actualizar todos los elementos price del archivo books.xml.

Dim document As XmlDocument = New XmlDocument()


document.Load("C:\Books.xml")
Dim nav As XPathNavigator = document.CreateNavigator()
Dim manager As New XmlNamespaceManager(nav.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")
For Each nv As XPathNavigator In nav.Select("//bk:price", manager)
If nv.Value = "8.99" Then nv.SetValue("9.99")
Next
MessageBox.Show(nav.OuterXml)

CIBERTEC CARRERAS PROFESIONALES


210

2.5.3 Modificación de atributos


Los métodos SetValue y SetTypedValue pueden utilizarse para
modificar nodos de atributos con y sin información de tipos.

En el ejemplo se cambia el valor del atributo genre del primer


elemento book en el archivo books.xml.

Dim document As XmlDocument = New XmlDocument()


document.Load("C:\books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", String.Empty)
navigator.MoveToChild("book", String.Empty)
navigator.MoveToAttribute("genre", String.Empty)
navigator.SetValue("non-fiction")
navigator.MoveToRoot()
MessageBox.Show(navigator.OuterXml)

2.6 QUITAR DATOS XML CON XPATHNAVIGATOR


XPathNavigator incluye métodos que utiliza para quitar nodos y valores de
un documento XML. Para utilizar estos métodos, XPathNavigator debe ser
editable, es decir, su propiedad CanEdit debe ser true.

2.6.1 Cómo quitar nodos


XPathNavigator incluye el método DeleteSelf para eliminar el nodo
actual situado un objeto XPathNavigator de un documento XML.
Eliminado un nodo con el método DeleteSelf, ya no se puede llegar a
él desde la raíz del objeto XmlDocument.
La operación de eliminación no afecta a la posición de ningún objeto
XPathNavigator situado en el nodo eliminado. Estos objetos
XPathNavigator son válidos en el sentido de que se pueden mover en
el subárbol eliminado, pero no se pueden mover al árbol del nodo
principal utilizando los métodos normales de desplazamiento por
conjuntos de nodos de la clase XPathNavigator.
En el ejemplo, se elimina el elemento price del primer elemento
book del archivo books.xml utilizando el método DeleteSelf.
La posición del objeto XPathNavigator después de eliminar el
elemento price se encuentra en el elemento book primario.
Dim document As XmlDocument = New XmlDocument()
document.Load("C:\Books.xml")
Dim nav As XPathNavigator = document.CreateNavigator()

nav.MoveToChild("bookstore", "http://www.contoso.com/books")
nav.MoveToChild("book", "http://www.contoso.com/books")
nav.MoveToChild("price", "http://www.contoso.com/books")

nav.DeleteSelf()
Console.WriteLine("Posicion despues eliminar:{0}", navigator.Name)
MessageBox.Show(navigator.OuterXml)

2.6.2 Cómo quitar valores


XPathNavigator incluye los métodos SetValue y SetTypedValue para
quitar valores con y sin información de tipos de un documento XML.
2.6.3 Cómo quitar valores sin información de tipos

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 211

El método SetValue simplemente inserta el valor string sin


información de tipos, que se pasa como parámetro, como valor del
nodo en el que se encuentra situado actualmente el objeto
XPathNavigator. Al pasar una cadena vacía al método SetValue, se
quita el valor del nodo actual.
En el siguiente ejemplo, se quita el valor del elemento price del
primer elemento book en el archivo contosoBooks.xml
utilizando el método SetValue.
Dim document As XmlDocument = New XmlDocument()
document.Load("C:\Books.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
navigator.MoveToChild("bookstore", "http://www.contoso.com/books")
navigator.MoveToChild("book", "http://www.contoso.com/books")
navigator.MoveToChild("price", "http://www.contoso.com/books")

navigator.SetValue("")
navigator.MoveToRoot()
MessageBox.Show(navigator.OuterXml)

3 GUARDAR UN DOCUMENTO XML


La Clase XmlDocument, tiene el metod Save que permite guardar el contexto
de un XmlDocument.
Dim doc As New XmlDocument()
doc.Load("book.xml")
doc.Save("news.xml")

Si carga un XmlDocument y al grabarlo, puede se diferente del original, se


puede seguir los siguientes caminos:

• Si la propiedad PreserveWhitespace se establece en true antes de


llamar al método Save, en el resultado se conserva el espacio en
blanco del documento; sin embargo, si la propiedad es false,
XmlDocument, se aplica sangría automáticamente al resultado.
• Todos los espacios en blanco entre los atributos se reducen a un
carácter de un solo espacio.
• Se cambia el espacio en blanco entre los elementos. Se conserva el
espacio blanco importante, pero no se conserva el poco importante. Sin
embargo, cuando se guarda el documento, se utiliza el modo
XmlTextWriter Sangría de manera predeterminada para imprimir con
claridad el resultado con el fin de que sea más legible.
• De manera predeterminada, el carácter de la comilla que se utiliza
delante y detrás de los valores de los atributos se cambia por la comilla
doble. Puede utilizar la propiedad QuoteChar en XmlTextWriterpara
establecer el carácter de la comilla como doble o simple.
• De manera predeterminada, se expanden las entidades de caracteres
numéricos como &#123.
• No se conserva la marca de orden de bytes del documento de entrada.
UCS-2 se guarda como UTF-8 a menos que cree explícitamente una
declaración XML en la que se especifique otra codificación.
• Si desea escribir XmlDocument en un archivo o una secuencia, el
resultado escrito es el mismo que el contenido del documento. Es decir,
la declaración XmlDeclaration sólo se escribe si hay alguna en el

CIBERTEC CARRERAS PROFESIONALES


212

documento y la codificación que se utiliza al escribir el documento es la


misma que la del nodo de la declaración.

3.1 ESCRIBIR EL CONTENIDO DE UN DOCUMENTO CON LA


PROPIEDAD OUTERXML
La propiedad OuterXml es una extensión de Microsoft de los estándares
del Modelo de objetos de documento (DOM) XML del W3C (World Wide
Web Consortium). La propiedad OuterXml se utiliza para obtener el
marcado de todo el documento XML o tan sólo el de un nodo y sus nodos
secundarios. OuterXml devuelve el marcado que representa el nodo en
concreto y todos sus nodos secundarios.
El siguiente ejemplo de código muestra cómo guardar un
documento por completo como una cadena.

Dim mydoc As New XmlDocument()


Mydoc.Load("book.xml")
' Ahora grabamos el documento auna variable String "xml".
Dim xml As String = mydoc.OuterXml

El siguiente ejemplo muestra cómo guardar el elemento de


documento.

Dim xml As String = mydoc.DocumentElement.OuterXml

3.2 ESCRIBIR UNA DECLARACION XMLDECLARATION

Los miembros XmlDocument y XmlDeclaration de OuterXml, InnerXml y


WriteTo, además de los métodos XmlDocument de Save y
WriteContentTo, crean una declaración XML.
Para las propiedades XmlDocument de OuterXml, InnerXml, y los
métodos Save, WriteTo y WriteContentTo, la codificación escrita en la
declaración XML se obtiene del nodo XmlDeclaration. Si no existe ningún
nodo XmlDeclaration, XmlDeclaration no se escribe. Si no hay
codificación en el nodo XmlDeclaration, la codificación no se escribe en la
declaración XML.
Los métodos System.Xml.XmlDocument.Save(System.IO.TextWriter) y
System.Xml.XmlDocument.Save(System.Xml.XmlWriter) siempre
escriben una declaración XmlDeclaration. Estos métodos toman la
codificación del sistema de escritura que está escribiendo. Es decir, el valor
de codificación en el sistema de escritura sobrescribe la codificación en el
documento y en la declaración XmlDeclaration.

Por ejemplo, el siguiente código no escribe una codificación en la


declaración XML que se encuentra en el archivo de salida out.xml.

Dim doc As New XmlDocument()


Dim tw As XmlTextWriter = New XmlTextWriter("out.xml", Nothing)
doc.Load("text.xml")
doc.Save(tw)

Para el método Save, la declaración XML se escribe utilizando el método


WriteStartDocument en la clase XmlWriter. Por lo tanto, al sobrescribir el

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 213

método WriteStartDocument, cambia la forma de escribir el principio del


documento.
Para los miembros XmlDeclaration de OuterXml, WriteTo e InnerXml, si
no se establece la propiedad Encoding, no se escribe la codificación. De lo
contrario, la codificación escrita en la declaración XML es la misma que la
que se encuentra en la propiedad Encoding.

LABORATORIO 14.1
En este escenario se carga un objeto XPathDocument con los datos XML encontrados
en el archivo productos.xml, crea un objeto XPathNavigator para una presentación de
los datos y, a continuación, realizamos un conjunto de operaciones por el documento.

Ingrese a Visual Studio 2005.


1. Seleccione File->New->Project.
2. Elija las siguientes opciones:
- En “Proyect Types” elija “Visual Basic”.
- En “Templates” elija “WindowsApplication”.
- En “Name” coloque “appFacturacion 14”.
- En “Location” coloque “C:\CursoPOOII”.

3. En el Form1 del proyecto, construya la siguiente interfaz:

Controles Propiedad Valor

Label1 Text Productos

ListView1

Button1 Name BtnListado

Button2 Name BtnCantidad

Button3 Name BntInventario

Button4 Name BtnNoStock

Button5 Name BtnBuscar

CIBERTEC CARRERAS PROFESIONALES


214

4. Defina las librería para el manejo de los archivos XML

5. Defina el procedimiento para el botón Listado el cual permita buscar el archivo


XML y listar los nodos en el ListView1.

Defina un
XMLDocument para
cargar el archivo XML

Defina un
XpathNavigator del
XMLDocument, ubique
en el 1er Nodo

Proceso para realizar


el desplazamiento por
el XpathNavigator del
XMLDocument,
visualizando los
valores de los nodos
en el ListView1

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 215

6. Defina el procedimiento en el botón Cantidad Productos para mostrar en un


cuadro de diálogo, la cantidad de productos que se han listado

Defina un
XMLDocument para
cargar el archivo XML.

El XpathExpression
evalúa la expresión
para contar los
productos,
visualizando el
resultado en el
MessageBox.

7. Defina el procedimiento en el botón Inventario para mostrar en un cuadro de


diálogo, el total cantidad disponibles de productos almacenados

Defina un
XMLDocument para
cargar el archivo XML.

El XpathExpression
evalúa la expresión
para sumar el campo
stock, visualizando el
resultado en el
MessageBox.

CIBERTEC CARRERAS PROFESIONALES


216

8. Defina el procedimiento en el botón NO TIENEN STOCK, que permita


visualizar todos los productos que no tienen stock.

Defina un
XMLPathNodeIterator
que almacene los
nodos cuyo stock=0

Para listar los productos


de stock cero, realice un
desplazamiento por el
XpathNodeIterator para
obtener los productos sin
stock.

9. Defina el procedimiento del botón BUSCAR, donde al ingresar el código del


producto por un InputBox, visualice su descripción.

Defina un
XMLPathNodeIterator
que almacene la
descripción del código
a buscar en el método
Select del
XPathNavigator.

Listar la descripción del


producto buscado,
visualizando el resultado
en el MessageBox.

CARRERAS PROFESIONALES CIBERTEC


PROGRAMACIÓN ORIENTADA A OBJETOS II 217

Autoevaluación
1. ¿Qué es el XPathNavigator?
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

2. ¿Cómo evaluar las expresiones utilizando XPathNavigator?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

3. ¿Qué es el XPathExpression, qué valores retornar?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
______________________________________________

4. ¿Cómo editar datos utilizando XPathNavigator?


__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
____________________________________

5. ¿Cuáles son los métodos para insertar atributos? Explique cada uno.
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
__________________________________________________________________
____________________________________

CIBERTEC CARRERAS PROFESIONALES


218

Resumen
 La clase XPathDocument proporciona una representación en memoria rápida
y de sólo lectura de un documento XML utilizando el modelo de datos XPath.

 Las clases XPathDocument y XmlDocument, además de la clase XmlNode,


implementan la interfaz IXPathNavigable del espacio de nombres
System.Xml.XPath. Como resultado, las tres clases proporcionan un método
CreateNavigator que devuelve un objeto XPathNavigator.

 XPathExpression representa consulta XPath compilada devuelta desde el


método Compile estático de la clase XPathExpression o desde el método
Compile de la clase XPathNavigator.

 XPathNavigator incluye métodos para insertar nodos de atributos.


o CreateAttribute
o CreateAttributes
 Estos métodos insertan nodos de atributos en el nodo de
elementos en el que está situado actualmente un objeto
XPathNavigator.

 XPathNavigator incluye métodos para modificar nodos y valores en un


documento XML. Para utilizar estos métodos, el objeto XPathNavigator debe
ser editable, es decir, su propiedad CanEdit debe ser true. Para cambiar el
valor de un nodo consiste en utilizar los métodos SetValue y SetTypedValue
de la clase XPathNavigator.

 XPathNavigator incluye el método DeleteSelf para eliminar el nodo actual


situado un objeto XPathNavigator de un documento XML. Eliminado un nodo
con el método DeleteSelf, ya no se puede llegar a él desde la raíz del objeto
XmlDocument.

 La Clase XmlDocument, tiene el metod Save que permite guardar el contexto


de un XmlDocument.

 Se desea realizar consultas referentes al Tema:

 http://msdn2.microsoft.com/es-es/library/87274khy(VS.80).aspx
Página referente al procesamiento de datos XML con el modelo de
datos XPath

 http://msdn2.microsoft.com/es-es/library/439wyfyh(VS.80).aspx
Página referente al desplazamiento por nodos de espacios de nombres
y atributos con XPathNavigator
 http://msdn2.microsoft.com/es-es/library/sb9ca14t(VS.80).aspx
Página referente a la edición de datos en XML

 http://msdn2.microsoft.com/es-es/library/xws54wwx(VS.80).aspx
Página referente a como quitar datos XML con XPathNavigator

CARRERAS PROFESIONALES CIBERTEC

También podría gustarte