Download adonet - WordPress.com

Document related concepts
no text concepts found
Transcript
Diapositiva 1
Día 5:
Accediendo a los Datos con
ADO.NET
1
Diapositiva 2
Objetivos para el día
„ Al
final de este día, usted podrá:
„
Describir los objetos en el modelo de objetos ADO.NET
„
Acceder y modificar los datos de una base de datos
utilizando DataSets
„
Utilizar las clases ADO.NET
„
Trabajar con Datos XML
2
Diapositiva 3
Contenidos del día
„ 1.
Arquitectura de ADO.NET
„ 2.
Accediendo a los datos
„ 3.
Leyendo y escribiendo datos XML
3
Diapositiva 4
1. Arquitectura de ADO.NET
Preguntas de la sección
„
Preguntas
„
¿Qué es ADO.NET?
„
¿Cuáles son las clases en el modelo
ADO.NET?
4
Diapositiva 5
ADO.NET
„ ADO.NET
es un conjunto de clases que permiten a
las aplicaciones basadas en .NET leer y actualizar la
información en las bases de datos y otros almacenes
de datos. Puede acceder a estas clases a través del
espacio de nombre System.Data de .NET
Framework.
„ ADO.NET
proporciona un acceso consistente a una
amplia gama de fuentes de datos, incluyendo las
bases de datos Microsoft SQL Server™, las bases
de datos que cumplen con OLE DB, las fuentes no
relacionales como Microsoft Exchange Server y los
documentos XML
5
ADO.NET
La mayoría de las aplicaciones requieren algún tipo de acceso a los datos. Las
aplicaciones Web se necesitan integrar con las bases de datos centrales, los
almacenes de datos XML o las bases de datos locales de escritorio. La
tecnología de acceso a datos ADO.NET permite un acceso sencillo y poderoso
a los datos, maximizando el uso de los recursos del sistema.
Acceso a una base de datos desconectada
Las versiones anteriores de las tecnologías de acceso a datos han
proporcionado por predeterminación acceso a datos continuamente
conectados. En dicho modelo, una aplicación crea una conexión a una base de
datos y la mantiene abierta durante la vida de la aplicación o al menos durante
el tiempo en que se requieren los datos. Conforme las aplicaciones son cada
vez más complejas y las bases de datos empiezan a dar servicio a más y más
clientes, una tecnología de acceso a datos conectados se vuelve poco práctica
por varias razones. Por ejemplo:
Las conexiones abiertas de la base de datos son costosas en términos de
recursos del sistema. Entre más conexiones abiertas, menos eficiente será el
rendimiento del sistema.
Las aplicaciones con un acceso a datos conectado son más difíciles de escalar.
Una aplicación que pueda mantener conexiones con dos clientes puede tener
un desempeño deficiente con 10, y puede ser totalmente inútil con 100.
ADO.NET aborda estos problemas, al implementar de manera predeterminada
un modelo de acceso a una base de datos desconectada. En este modelo, las
conexiones a los datos se establecen y se dejan abiertas solamente durante el
tiempo suficiente para realizar la acción solicitada. Por ejemplo, si una
aplicación solicita datos de una base de datos, la conexión se abrirá sólo por el
tiempo suficiente para cargar los datos en la aplicación y luego se cerrará. De
la misma forma, si se actualiza una base de datos, se abre la conexión para
ejecutar el comando UPDATE y luego se cierra de nuevo. Al mantener las
conexiones abiertas sólo por el tiempo mínimo requerido, ADO.NET conserva
los recursos del sistema y permite que el acceso a los datos se escale con un
impacto mínimo en el rendimiento.
Diapositiva 6
Arquitectura de ADO.NET
„ DataSet:
almacena datos en la máquina local
„
Tablas
„
Relaciones
„ Proveedor
de Datos: media la interacción entre el
programa y la base de datos
„
Connection
„
Command
„
DataReader
„
DataAdapter
6
El DataSet
El DataSet es una representación de los datos desconectados en la memoria.
Se puede considerar como una copia local de las partes más importantes de la
base de datos. Los datos se pueden cargar en un DataSet desde cualquier
fuente válida de datos, como una base de datos Microsoft SQL Server, una
base de datos Microsoft Access o un archivo XML. El DataSet prevalece en la
memoria y los datos en la misma se pueden manipular y actualizar sin importar
la base de datos. Cuando es apropiado, el DataSet puede entonces actuar
como una plantilla para actualizar la base de datos central.
El objeto DataSet contiene una colección de cero o más objetos DataTable,
cada uno de los cuales es una representación en la memoria de una tabla
única. La estructura de un DataTable particular se define por la colección de
DataColumns, la cual enumera las columnas en una tabla en particular, y por la
colección de restricciones, que enumera las restricciones de la tabla. En su
conjunto, estas dos colecciones conforman el esquema de la tabla. Un
DataTable también contiene una colección de DataRows, la cual contiene los
datos reales en el DataSet.
El DataSet contiene una colección de DataRelations. Un objeto DataRelation le
permite crear asociaciones entre las filas en una tabla y las filas en otra. La
colección DataRelations enumera un conjunto de objetos DataRelation que
define estas relaciones entre las tablas en el DataSet.
El Proveedor de datos
El Proveedor de datos crea y mantiene el vínculo con la base de datos. Un
Proveedor de datos no es en realidad un componente único, sino un conjunto
de componentes relacionados que funcionan de manera conjunta para
proporcionar los datos en una manera eficiente e de mayor rendimiento.
Actualmente, el Microsoft .NET Framework viene con dos proveedores de
datos: el Proveedor de datos SQL Server .NET, diseñado específicamente para
trabajar con Microsoft SQL Server 7.0 ó posterior, y el Proveedor de datos
OleDb .NET, que se conecta con otros tipos de bases de datos. Cada
Proveedor de datos consiste en versiones similares de las siguientes clases de
componentes genéricos:
El objeto Connection proporciona la conexión a la base de datos.
El objeto Command se utiliza para ejecutar un comando contra una fuente de
datos. Puede ejecutar comandos que no son de consulta como INSERT,
UPDATE o DELETE, o devolver un DataReader con los resultados de un
comando SELECT.
Un objeto DataReader proporciona un conjunto de registros de sólo lectura
hacia delante y conectados.
El objeto DataAdapter llena un DataSet o DataTable desconectado con los
datos y ejecuta las actualizaciones.
El acceso a los datos en ADO.NET se facilita de la siguiente forma: Un objeto
Connection establece una conexión entre la aplicación y la base de datos. Se
puede acceder directamente a esta conexión por medio de un objeto Command
o por un objeto DataAdapter. El objeto Command proporciona una ejecución
directa de un comando a la base de datos. Si el comando devuelve más de un
valor único, el objeto Command devuelve un DataReader para proporcionar los
datos. Estos datos pueden ser directamente procesados por la lógica de la
aplicación. De manera alterna, puede utilizar el DataAdapter para llenar un
objeto DataSet. Se pueden lograr actualizaciones a la base de datos ya sea a
través del objeto Command o a través del DataAdapter
Diapositiva 7
2. Accediendo a los datos
Preguntas de la sección
„ Preguntas
„
¿Cuáles son las clases disponibles?
„
¿Qué son los DataSets con información de
Tipos?
7
Diapositiva 8
Clases ADO.NET
„ Connection
„ Command
„ DataReader
„ DataAdapter
8
El objeto Connection
El objeto Connection representa la conexión real a la base de datos.
Microsoft Visual Studio .NET proporciona dos tipos de clases Connection:
el objeto SqlConnection, diseñado específicamente para conectarse a Microsoft
SQL Server 7.0 ó posterior y
el objeto OleDbConnection, que puede proporcionar conexiones a una amplia
gama de tipos de bases de datos.
El objeto Connection contiene toda la información requerida para abrir un canal
a la base de datos en la propiedad ConnectionString. El objeto Connection
también proporciona métodos que administrar las transacciones de los datos.
El Objeto Command
El objeto Command también está representado por dos clases
correspondientes: SqlCommand y OleDbCommand.
Puede utilizar los objetos Command para ejecutar los comandos a una base
de datos a través de una conexión. Se pueden utilizar los objetos Command
para ejecutar los procedimientos almacenados en la base de datos, ejecutar los
comandos SQL y devolver directamente tablas completas. Los objetos
Command proporcionan tres métodos que se utilizan para ejecutar comandos
en la base de datos:
ExecuteNonQuery. Ejecuta comandos que no devuelven valores, como
INSERT, UPDATE o DELETE.
ExecuteScalar. Devuelve un valor único desde una consulta de la base de
datos.
ExecuteReader. Devuelve un conjunto de resultados por medio de un objeto
DataReader.
El objeto DataReader
El objeto DataReader proporciona un conjunto de registros con un flujo de sólo
lectura, hacia delante y conectado a una base de datos. A diferencia de otros
componentes del Proveedor de datos, no se pueden crear instancias
directamente en los objetos DataReader. Más bien, el DataReader se devuelve
como un resultado del método ExecuteReader del objeto Command. El método
SqlCommand.ExecuteReader devuelve un objeto SqlDataReader, y el método
OleDbCommand.ExecuteReader devuelve un objeto OleDbDataReader. El
DataReader puede proporcionar filas de datos directamente a la lógica de la
aplicación cuando no necesita mantener los datos en la memoria caché.
Debido a que sólo una fila está en la memoria a la vez, el DataReader
proporciona el costo más bajo en términos de rendimiento del sistema, pero
requiere el uso exclusivo de un objeto abierto de conexión durante la vida del
DataReader.
El objeto DataAdapter
El DataAdapter es la clase en la parte central del acceso a datos
desconectados de ADO.NET.
Esencialmente es el intermediario, el que facilita toda la comunicación entre la
base de datos y un DataSet. El DataAdapter llena una DataTable o DataSet
con los datos de la base de datos cuando se invoca el método Fill. Después de
que se han manipulado los datos que residen en la memoria, el DataAdapter
puede trasmitir los cambios a la base de datos al invocar el método Update. El
DataAdapter proporciona cuatro propiedades que presentan los comandos de
la base de datos:
SelectCommand. Contiene el texto u objeto del comando que selecciona los
datos de la base de datos. Este comando se ejecuta cuando se invoca el
método Fill y llena una DataTable o un DataSet.
InsertCommand. Contiene el texto u objeto del comando que inserta una fila
en una tabla.
DeleteCommand. Contiene el texto u objeto del comando que elimina una fila
de una tabla.
UpdateCommand. Contiene el texto u objeto del comando que actualiza los
valores de una base de datos.
Cuando se invoca el método Update, los cambios en DataSet se copian a la
base de datos y se ejecuta InsertCommand, DeleteCommand o
UpdateCommand, según sea apropiado.
El siguiente ejemplo crea un SqlCommand y un SqlConnection. SqlConnection
se abre y se establece como la conexión para SqlCommand. El ejemplo invoca
entonces a ExecuteNonQuery, y cierra la conexión. Para lograr esto,
ExecuteNonQuery se pasa a una cadena de conexión y una cadena de
consulta que es una instrucción Transact-SQL INSERT.
VB
...
myConnectionString = "Initial Catalog=Northwind;Data
Source=localhost;Integrated Security=SSPI;"
Dim myConnection As New SqlConnection(myConnectionString)
Dim myInsertQuery As String = "INSERT INTO Customers (CustomerID,
CompanyName) Values('NWIND', 'Northwind Traders')"
Dim myCommand As New SqlCommand(myInsertQuery)
myCommand.Connection = myConnection
myConnection.Open()
myCommand.ExecuteNonQuery()
myCommand.Connection.Close()
...
C#
…
myConnectionString = "Initial Catalog=Northwind;Data
Source=localhost;Integrated Security=SSPI;";
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myInsertQuery = "INSERT INTO Customers (CustomerID,
CompanyName) Values('NWIND', 'Northwind Traders')";
SqlCommand myCommand = new SqlCommand(myInsertQuery);
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
…
El método Fill del DataAdapter se utiliza para llenar un DataSet con los
resultados del SelectCommand del DataAdapter. Fill toma como su argumento
un DataSet a llenar, y un objeto DataTable, o el nombre de la DataTable a
llenar con filas devueltas de SelectCommand.
El siguiente ejemplo de código crea una instancia de un DataAdapter que utiliza
una Conexión a la base de datos Microsoft SQL Server Northwind y llena una
DataTable en un DataSet con la lista de clientes. La instrucción SQL y los
argumentos de Connection pasados al constructor del DataAdapter se utilizan
para crear la propiedad SelectCommand del DataAdapter.
VB
…
Dim nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")
Dim selectCMD As SqlCommand = New SqlCommand("SELECCIONAR
CustomerID, CompanyName DE Clientes", nwindConn)
selectCMD.CommandTimeout = 30
Dim custDA As SqlDataAdapter = New SqlDataAdapter
custDA.SelectCommand = selectCMD
nwindConn.Open()
Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Clientes")
nwindConn.Close()
…
C#
…
SqlConnection nwindConn = new SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlCommand selectCMD = new SqlCommand("SELECCIONAR
CustomerID, CompanyName DE Clientes", nwindConn);
selectCMD.CommandTimeout = 30;
SqlDataAdapter custDA = new SqlDataAdapter();
custDA.SelectCommand = selectCMD;
nwindConn.Open();
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
nwindConn.Close();
…
Diapositiva 9
El DataSet
9
El DataSet representa un conjunto completo de datos incluyendo tablas
relacionadas, restricciones y las relaciones entre las tablas.
Los métodos y objetos en un DataSet son consistentes con los del modelo
relacional de la base de datos.
El DataSet también puede mantener y recargar sus contenidos como XML y su
esquema como un esquema del Lenguaje de definición de esquemas XML
(XSD).
DataTableCollection
Un DataSet de ADO.NET contiene una colección de cero o más tablas
representadas por objetos DataTable. DataTableCollection contiene todos los
objetos DataTable en un DataSet.
Un DataTable se define en el espacio de nombre System.Data y representa
una sola tabla de datos residente en la memoria. Contiene una colección de
columnas representada por un DataColumnCollection, y restricciones
representadas por un ConstraintCollection, que en conjunto definen el esquema
de la tabla. Un DataTable también contiene una colección de filas representada
por la DataRowCollection, que contiene los datos en la tabla. Junto con su
estado actual, un DataRow contiene las versiones tanto actual como original
para identificar los cambios a los valores almacenados en la fila.
DataRelationCollection
Un DataSet contiene relaciones en su objeto DataRelationCollection. Una
relación, representada por el objeto DataRelation, asocia filas en un DataTable
con filas en otro DataTable. Es análoga a una ruta conjunta que puede existir
entre columnas clave primarias y foráneas en una base de datos relacional.
Una DataRelation identifica las columnas coincidentes en dos tablas de un
DataSet.
Las relaciones permiten la navegación de una tabla a otra dentro de un
DataSet. Los elementos esenciales de una DataRelation son el nombre de la
relación, el nombre de las tablas relacionadas y las columnas relacionadas en
cada tabla. Se pueden desarrollar las relaciones con más de una columna por
tabla al especificar un arreglo de objetos DataColumn como las columnas
clave. Cuando se agrega una relación a la DataRelationCollection,
opcionalmente puede agregar una UniqueKeyConstraint y una
ForeignKeyConstraint para aplicar las restricciones de integridad cuando se
realizan los cambios a los valores relacionados de la columna.
ExtendedProperties
El DataSet (así como la DataTable y DataColumn) tiene una propiedad
ExtendedProperties. ExtendedProperties es una PropertyCollection en donde
puede colocar la información personalizada, como la instrucción SELECT que
se utilizó para generar el conjunto de resultados, o un sello de fecha/hora de
cuando se generaron los datos. La colección ExtendedProperties se mantiene
con la información del esquema para el DataSet (como la DataTable y
DataColumn).
El siguiente ejemplo crea dos objetos DataTable, uno DataRelation y agrega
los objetos nuevos al DataSet:
VB
…
' Coloque la siguiente línea en la sección de Declaraciones.
Private myDataSet As DataSet
Private Sub MakeDataTables()
' Ejecute todas las funciones.
MakeParentTable()
MakeChildTable()
MakeDataRelation()
End Sub
Private Sub MakeParentTable()
' Cree una DataTable nueva.
Dim myDataTable As DataTable = New DataTable("ParentTable")
' Declare las variables para los objetos DataColumn y DataRow.
Dim myDataColumn As DataColumn
Dim myDataRow As DataRow
' Cree una DataColumn nueva, establezca un DataType, ColumnName y
agreguéguelos a la DataTable.
myDataColumn = New DataColumn
myDataColumn.DataType = System.Type.GetType("System.Int32")
myDataColumn.ColumnName = "id"
myDataColumn.ReadOnly = True
myDataColumn.Unique = True
' Agregue la Columna a la DataColumnCollection.
myDataTable.Columns.Add(myDataColumn)
' Cree una segunda columna.
myDataColumn = New DataColumn
myDataColumn.DataType = System.Type.GetType("System.String")
myDataColumn.ColumnName = "ParentItem"
myDataColumn.AutoIncrement = False
myDataColumn.Caption = "ParentItem"
myDataColumn.ReadOnly = False
myDataColumn.Unique = False
' Agregue la columna a al tabla.
myDataTable.Columns.Add(myDataColumn)
' Haga que la columna de ID sea la columna clave primaria.
Dim PrimaryKeyColumns(0) As DataColumn
PrimaryKeyColumns(0) = myDataTable.Columns("id")
myDataTable.PrimaryKey = PrimaryKeyColumns
' Cree una instancia de la variable DataSet.
myDataSet = New DataSet
' Agregue la DataTable nueva al DataSet.
myDataSet.Tables.Add(myDataTable)
' Cree tres objetos DataRow nuevos y agréguelos a la DataTable
Dim i As Integer
For i = 0 To 2
myDataRow = myDataTable.NewRow()
myDataRow("id") = i
myDataRow("ParentItem") = "ParentItem " + i.ToString()
myDataTable.Rows.Add(myDataRow)
Next i
End Sub
Private Sub MakeChildTable()
' Cree una DataTable nueva.
Dim myDataTable As DataTable = New DataTable("childTable")
Dim myDataColumn As DataColumn
Dim myDataRow As DataRow
' Cree la primera columna y agréguela a la DataTable.
myDataColumn = New DataColumn
myDataColumn.DataType = System.Type.GetType("System.Int32")
myDataColumn.ColumnName = "ChildID"
myDataColumn.AutoIncrement = True
myDataColumn.Caption = "ID"
myDataColumn.ReadOnly = True
myDataColumn.Unique = True
' Agregue la columna a la DataColumnCollection.
myDataTable.Columns.Add(myDataColumn)
' Cree una segunda columna.
myDataColumn = New DataColumn
myDataColumn.DataType = System.Type.GetType("System.String")
myDataColumn.ColumnName = "ChildItem"
myDataColumn.AutoIncrement = False
myDataColumn.Caption = "ChildItem"
myDataColumn.ReadOnly = False
myDataColumn.Unique = False
myDataTable.Columns.Add(myDataColumn)
' Cree una tercer columna.
myDataColumn = New DataColumn
myDataColumn.DataType = System.Type.GetType("System.Int32")
myDataColumn.ColumnName = "ParentID"
myDataColumn.AutoIncrement = False
myDataColumn.Caption = "ParentID"
myDataColumn.ReadOnly = False
myDataColumn.Unique = False
myDataTable.Columns.Add(myDataColumn)
myDataSet.Tables.Add(myDataTable)
' Cree tres conjuntos de objetos DataRow, cinco filas de cada uno, y
agréguelos a la DataTable.
Dim i As Integer
For i = 0 To 4
myDataRow = myDataTable.NewRow()
myDataRow("childID") = i
myDataRow("ChildItem") = "Item " + i.ToString()
myDataRow("ParentID") = 0
myDataTable.Rows.Add(myDataRow)
Next i
For i = 0 To 4
myDataRow = myDataTable.NewRow()
myDataRow("childID") = i + 5
myDataRow("ChildItem") = "Item " + i.ToString()
myDataRow("ParentID") = 1
myDataTable.Rows.Add(myDataRow)
Next i
For i = 0 To 4
myDataRow = myDataTable.NewRow()
myDataRow("childID") = i + 10
myDataRow("ChildItem") = "Item " + i.ToString()
myDataRow("ParentID") = 2
myDataTable.Rows.Add(myDataRow)
Next i
End Sub
Private Sub MakeDataRelation()
' DataRelation require dos DataColumn (principal y secundario) y un
nombre.
Dim myDataRelation As DataRelation
Dim parentColumn As DataColumn
Dim childColumn As DataColumn
parentColumn = myDataSet.Tables("ParentTable").Columns("id")
childColumn = myDataSet.Tables("ChildTable").Columns("ParentID")
myDataRelation = New DataRelation("parent2Child", parentColumn,
childColumn)
myDataSet.Tables("ChildTable").ParentRelations.Add(myDataRelation)
End Sub
C#
// Coloque la siguiente línea en la sección de Declaraciones.
private System.Data.DataSet myDataSet;
private void MakeDataTables()
{
// Ejecute todas las funciones.
MakeParentTable();
MakeChildTable();
MakeDataRelation();
}
private void MakeParentTable()
{
// Cree una DataTable nueva.
System.Data.DataTable myDataTable = new DataTable("ParentTable");
// Declare variables para los objetos DataColumn y DataRow.
DataColumn myDataColumn;
DataRow myDataRow;
// Cree una DataColumn nueva, establezca el DataType, ColumnName y
agréguelos a la DataTable.
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.Int32");
myDataColumn.ColumnName = "id";
myDataColumn.ReadOnly = true;
myDataColumn.Unique = true;
// Agregue la Columna a la DataColumnCollection.
myDataTable.Columns.Add(myDataColumn);
// Cree una segunda columna.
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.String");
myDataColumn.ColumnName = "ParentItem";
myDataColumn.AutoIncrement = false;
myDataColumn.Caption = "ParentItem";
myDataColumn.ReadOnly = false;
myDataColumn.Unique = false;
// Agregue la la columna a la tabla.
myDataTable.Columns.Add(myDataColumn);
// Haga que la columna del ID sea la columna clave primaria.
DataColumn[] PrimaryKeyColumns = new DataColumn[1];
PrimaryKeyColumns[0] = myDataTable.Columns["id"];
myDataTable.PrimaryKey = PrimaryKeyColumns;
// Cree una instancia de la variable DataSet.
myDataSet = new DataSet();
// Agregue la DataTable nueva al DataSet.
myDataSet.Tables.Add(myDataTable);
// Cree tres objetos DataRow nuevos y agréguelos a la DataTable
for (int i = 0; i<= 2; i++)
{
myDataRow = myDataTable.NewRow();
myDataRow["id"] = i;
myDataRow["ParentItem"] = "ParentItem " + i;
myDataTable.Rows.Add(myDataRow);
}
}
private void MakeChildTable()
{
// Cree una DataTable nueva.
DataTable myDataTable = new DataTable("childTable");
DataColumn myDataColumn;
DataRow myDataRow;
// Cree la primera columna y agréguela a la DataTable.
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.Int32");
myDataColumn.ColumnName = "ChildID";
myDataColumn.AutoIncrement = true;
myDataColumn.Caption = "ID";
myDataColumn.ReadOnly = true;
myDataColumn.Unique = true;
// Agregue la columna a la DataColumnCollection.
myDataTable.Columns.Add(myDataColumn);
// Cree la segunda columna.
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.String");
myDataColumn.ColumnName = "ChildItem";
myDataColumn.AutoIncrement = false;
myDataColumn.Caption = "ChildItem";
myDataColumn.ReadOnly = false;
myDataColumn.Unique = false;
myDataTable.Columns.Add(myDataColumn);
// Cree la tercera columna.
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.Int32");
myDataColumn.ColumnName = "ParentID";
myDataColumn.AutoIncrement = false;
myDataColumn.Caption = "ParentID";
myDataColumn.ReadOnly = false;
myDataColumn.Unique = false;
myDataTable.Columns.Add(myDataColumn);
myDataSet.Tables.Add(myDataTable);
// Cree tres conjuntos de objetos DataRow, cinco filas de cada uno, y
agréguelos a la DataTable.
for (int i = 0; i<= 4; i++)
{
myDataRow = myDataTable.NewRow();
myDataRow["childID"] = i;
myDataRow["ChildItem"] = "Item " + i;
myDataRow["ParentID"] = 0 ;
myDataTable.Rows.Add(myDataRow);
}
for (int i = 0; i<= 4; i++)
{
myDataRow = myDataTable.NewRow();
myDataRow["childID"] = i + 5;
myDataRow["ChildItem"] = "Item " + i;
myDataRow["ParentID"] = 1 ;
myDataTable.Rows.Add(myDataRow);
}
for (int i = 0; i<= 4; i++)
{
myDataRow = myDataTable.NewRow();
myDataRow["childID"] = i +10;
myDataRow["ChildItem"] = "Item " + i;
myDataRow["ParentID"] = 2 ;
myDataTable.Rows.Add(myDataRow);
}
}
private void MakeDataRelation()
{
// DataRelation require dos DataColumn (principal y secundario) y un
nombre.
DataRelation myDataRelation;
DataColumn parentColumn;
DataColumn childColumn;
parentColumn = myDataSet.Tables["ParentTable"].Columns["id"];
childColumn = myDataSet.Tables["ChildTable"].Columns["ParentID"];
myDataRelation = new DataRelation("parent2Child", parentColumn,
childColumn);
myDataSet.Tables["ChildTable"].ParentRelations.Add(myDataRelation);
}
}…
Diapositiva 10
Los DataSets con información de
tipos
„ Derivados
de la clase base DataSet
„ Proveen
verificación de tipos en tiempo de
compilación
„ Proporcionan
un fácil y rápido acceso a las tablas y
columnas en el DataSet
„ Generados
desde un Esquema XML
10
Un DataSet con información de tipos es un DataSet que se deriva primero de la
clase base DataSet y luego utiliza información en un archivo de esquema XML
(un archivo .xsd) para generar una clase nueva. La información del esquema
(tablas, columnas, etcétera) se genera y compila en esta nueva clase del
conjunto de datos como un conjunto de objetos y propiedades de primera
clase.
Esto significa que puede acceder a las tablas y a las columnas por nombre en
lugar de utilizar métodos basados en colecciones. Por ejemplo, para acceder a
la tabla Titles desde un conjunto de datos llamado pubsDataSet1, utilice el
siguiente código:
PubsDataSet.Tables(“Libros");
Sin embargo, con un DataSet con información de tipos, puede acceder
directamente a la tabla Titles al utilizar el siguiente código:
PubsDataSet.Books;
Ventajas de los DataSet con información de tipos Los DataSet con
información de tipos no sólo son más fáciles de leer, sino que también cuentan
con un soporte completo de la tecnología Microsoft IntelliSense® en el Editor
de códigos en Visual Studio .NET. Además de ser más fácil para trabajar, la
sintaxis para el conjunto de datos escrito proporciona la verificación de tipo al
momento de compilar, esto reduce en gran medida la posibilidad de errores al
asignar valores a los miembros del conjunto de datos. El acceso a las tablas y
a las columnas en un conjunto de datos escrito también es un poco más rápido
durante el tiempo de ejecución debido a que el acceso se determina durante el
tiempo de compilación, no a través de colecciones durante el tiempo de
ejecución.
Puede generar un conjunto de datos escrito de manera sólida desde el
ambiente integrado de desarrollo (IDE) de Visual Studio .NET al seleccionar las
tablas de una base de datos existente o al crear una utilizando el Diseñador
XML.
Agregando los objetos ADO.NET en una aplicación Web Forms utilizando
el asistente de configuración
1. Arrastre un objeto OleDbDataAdapter o SqlDataAdapter desde la caja de
herramientas a un formulario
2. Especifique la conexión y la información del comando SQL
El asistente muestra varios cuadros de diálogo:
Si solicita crear una conexión, el asistente muestra la ficha Connection del
cuadro de diálogo Propiedades del vínculo de datos, que le permite especificar
un proveedor, nombre de servidor, nombre de la base de datos, nombre del
usuario y contraseña para la conexión.
Para ayudarle a crear las instrucciones SQL, el asistente proporciona el
Desarrollador de consulta, una utilidad que le permite crear y probar una
instrucción Select al utilizar las herramientas visuales. Para iniciarlo, haga clic
en el botón del Desarrollador de consulta cuando se le pida una instrucción
SQL.
3. En el Diseñador de componentes, seleccione el adaptador o los adaptadores
que transferirán los datos entre la fuente de datos y el conjunto de datos.
Por lo general, cada adaptador de datos accede a los datos en una tabla única.
Por lo tanto, para crear un conjunto de datos que contenga varias tablas de
datos, seleccione todos los adaptadores o las tablas con las que desea
trabajar.
4. En el menú Datos, elija Generar Dataset.
Aparecerá el cuadro de diálogo Generar DataSet.
5. Haga clic en Nuevo, y después especifique un nombre para el nuevo
DataSet. Si desea agregar el DataSet a su formulario o componente, haga clic
en Agregar una instancia de este DataSet al diseñador.
Esto genera un DataSet con información de tipos.
Comparando el acceso a datos entre DataSets con información de tipos y
DataSets sin información de tipos
Este ejemplo accede a la columna CustomerID en la primera fila de la tabla
Clientes.
Si está trabajando con un DataSet con información de tipos, puede hacer
referencia a una columna utilizando códigos como el que aparece a
continuación:
VB
...
Dim a As String
a = dsCustomersOrders1.Customers(0).CustomerID
...
C#
...
string s;
s = dsCustomersOrders1.Customers[0].CustomerID;
...
En contraste, si está trabajando con un DataSet sin información de tipos, el
código equivalente es:
VB
...
Dim a As String
a=
Convert.ToString(dsCustomersOrders1.Tables("Clientes").Rows(0).Item("Custo
merID"))
...
C#
...
string s = (string)
dsCustomersOrders1.Tables["Customers"].Rows[0]["CustomerID"];
...
Diapositiva 11
Actualizar los datos
„ Actualizar
los datos en el DataSet
„
Agregar filas
„
Editar filas
„
Eliminar filas
„ Actualizar
„
el DataSource
Método DataAdapter.Update()
11
Después de crear un conjunto de datos de DataTables, quizá desee agregar,
actualizar y eliminar datos. Cualesquiera cambios que realizan a los datos se
almacenan en la memoria y posteriormente se utilizan para aplicar los cambios
a la fuente de datos.
Para agregar nuevos registros utilizando DataSets con información de tipos :
VB
...
Dim myRow As DataRow = DatasetName.Customers.NewRow
myRow.FirstName = "Jay"
myRow.LastName = "Stevens"
Customers.Rows.Add(myRow)
...
C#
...
DataRow myRow = DatasetName.Customers.NewRow();
myRow.FirstName = "Jay";
myRow.LastName = "Stevens";
Customers.Rows.Add(myRow);
...
Para editar filas existentes en una tabla del conjunto de datos:
1. Invoque el método BeginEdit de la fila.
2. Cambie los datos en las columnas.
3. Invoque EndEdit o CancelEdit para aceptar o rechazar los cambios.
VB
...
DsCustomers.CustomersRow(myRow = dsCustomers.Customers.Rows(3))
myRow.BeginEdit()
myRow.ContactName = "John"
myRow.Region = "West"
myRow.EndEdit()
...
C#
...
DsCustomers.CustomersRow myRow =
dsCustomers.Customers.Rows[3];
myRow.BeginEdit();
myRow.ContactName ="John";
myRow.Region ="West";
myRow.EndEdit();
...
Para eliminar una fila
VB
...
dsCustomers.Customers.Rows(3).Delete()
...
C#
...
dsCustomers.Customers.Rows[3].Delete()
...
El valor del RowState depende de dos factores: (1) el tipo de operación que se
realizó en la fila, y (2) si se invocó o no AcceptChanges en el DataRow.
Added: Se ha agregado la fila a DataRowCollection, y AcceptChanges no se
ha invocado.
Deleted: Se eliminó la fila utilizando el método DELETE de DataRow.
Detached: Se creó la fila pero no es parte de ninguna DataRowCollection. Una
DataRow está en este estado inmediatamente después de que se crea y antes
de agregarse a una colección, o si se eliminó de una colección.
Modified: Se ha modificado la fila y no se ha invocado AcceptChanges.
Unchanged: La fila no ha cambiado desde que se invocó AcceptChanges por
última vez.
Al invocar el método AcceptChanges de una fila, se invoca implícitamente el
método EndEdit para terminar cualquier edición. Si el RowState de la fila es
Added o Modified, el RowState queda Unchanged. Si el RowState está en
Deleted, se elimina la fila.
Al invocar el método RejectChanges de una fila, se invoca implícitamente el
método CancelEdit para cancelar cualquier edición. Si el RowState está en
Deleted o Modified, la fila vuelve a sus valores anteriores y el RowState queda
Unchanged. Si el RowState está en Added, se elimina la fila.
Para actualizar la fuente de datos, utilice el método Update del objeto
DataAdapter, que es el vínculo entre el DataSet y la fuente de datos.
Usted utiliza las propiedades InsertCommand, UpdateCommand y
DeleteCommand del DataAdapter para identificar los cambios que se
produjeron en su DataSet. Usted especifica cada uno de ellos como un objeto
de comando existente para una instrucción INSERT, UPDATE o DELETE de
SQL. Para cualquier columna variable en las instrucciones, utiliza objetos
SqlParameter para identificar la columna, el tipo de datos, el tamaño y los datos
a insertarse.
El siguiente código muestra cómo utilizar la propiedad InsertCommand para
agregar una fila a la tabla Titles en la base de datos pubs:
VB
Dim insertTitlesCommand As New SqlCommand("Insert titles (title_id, title,
type) values (@title_id,@title,@type)")
insertTitlesCommand.Parameters.Add("@title_id", SqlDbType.VarChar, 6,
"title_id")
insertTitlesCommand.Parameters.Add("@title", SqlDbType.VarChar, 80,
"title")
insertTitlesCommand.Parameters.Add("@type", SqlDbType.Char, 12,
"type")
titlesSQLDataAdapter.InsertCommand = insertTitlesCommand
titlesSQLDataAdapter.Update(pubsDataSet, "títulos")
...
C#
SqlCommand insertTitlesCommand = new SqlCommand("Insert titles (title_id,
title, type) values (@title_id,@title,@type)");
insertTitlesCommand.Parameters.Add("@title_id", SqlDbType.VarChar, 6,
"title_id");
insertTitlesCommand.Parameters.Add("@title", SqlDbType.VarChar, 80,
"title");
insertTitlesCommand.Parameters.Add("@type", SqlDbType.Char, 12, "type");
titlesSQLDataAdapter.InsertCommand = insertTitlesCommand;
titlesSQLDataAdapter.Update(pubsDataSet, "títulos");
Diapositiva 12
Invocar los procedimientos
almacenados
„ Command
„ CommandType
„ Parámetros
„
Entrada
„
Salida
„
InputOutput
„
ReturnValue
12
Para invocar un procedimiento almacenado, configure CommandType del
objeto Command a StoredProcedure. Una vez que CommandType se configura
a StoredProcedure, puede utilizar la colección Parameters para definir los
parámetros.
Se puede crear un objeto Parameter utilizando el constructor de Parámetros, o
al invocar el método Agregar de la colección Parámetros de un Command.
Parameters.Add tomará como información cualquier instrucción del constructor
o un objeto Parameter existente. Para configurar el Valor de un Parámetro a
una referencia nula, utilice DBNull.Value.
Para parámetros que no sean parámetros de Entrada, debe configurar la
propiedad ParameterDirection para especificar si el tipo de parámetro es
InputOutput, Output o ReturnValue.
El ejemplo que aparece a continuación muestra lo que se requiere para invocar
procedimientos almacenados:
VB.NET
Dim sampleCMD As SqlCommand = New SqlCommand("SampleProc",
nwindConn)
sampleCMD.CommandType = CommandType.StoredProcedure
Dim sampParm As SqlParameter =
sampleCMD.Parameters.Add("RETURN_VALUE", SqlDbType.Int)
sampParm.Direction = ParameterDirection.ReturnValue
sampParm = sampleCMD.Parameters.Add("@InputParm",
SqlDbType.NVarChar, 12)
sampParm.Value = "Sample Value"
sampParm = sampleCMD.Parameters.Add("@OutputParm",
SqlDbType.NVarChar, 28)
sampParm.Direction = ParameterDirection.Output
nwindConn.Open()
Dim sampReader As SqlDataReader = sampleCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", sampReader.GetName(0),
sampReader.GetName(1))
Do While sampReader.Read()
Console.WriteLine("{0}, {1}", sampReader.GetInt32(0),
sampReader.GetString(1))
Loop
sampReader.Close()
nwindConn.Close()
Console.WriteLine(" @OutputParm: {0}",
sampleCMD.Parameters("@OutputParm").Value)
Console.WriteLine("RETURN_VALUE: {0}",
sampleCMD.Parameters("RETURN_VALUE").Value)
C#
SqlCommand sampleCMD = new SqlCommand("SampleProc", nwindConn);
sampleCMD.CommandType = CommandType.StoredProcedure;
SqlParameter sampParm = sampleCMD.Parameters.Add("RETURN_VALUE",
SqlDbType.Int);
sampParm.Direction = ParameterDirection.ReturnValue;
sampParm = sampleCMD.Parameters.Add("@InputParm",
SqlDbType.NVarChar, 12);
sampParm.Value = "Sample Value";
sampParm = sampleCMD.Parameters.Add("@OutputParm",
SqlDbType.NVarChar, 28);
sampParm.Direction = ParameterDirection.Output;
nwindConn.Open();
SqlDataReader sampReader = sampleCMD.ExecuteReader();
Console.WriteLine("{0}, {1}", sampReader.GetName(0),
sampReader.GetName(1));
while (sampReader.Read())
{
Console.WriteLine("{0}, {1}", sampReader.GetInt32(0),
sampReader.GetString(1));
}
sampReader.Close();
nwindConn.Close();
Console.WriteLine(" @OutputParm: {0}",
sampleCMD.Parameters["@OutputParm"].Value);
Console.WriteLine("RETURN_VALUE: {0}",
sampleCMD.Parameters["RETURN_VALUE"].Value);
Diapositiva 13
3. Leyendo y escribiendo datos XML
Preguntas de la sección
„ Preguntas
„
¿Qué es DOM?
„
¿Cuáles son las clases usadas para leer y
escribir datos XML?
13
Diapositiva 14
Documento XML
„ Document
„ DocumentFragment
„ EntityReference
„ Element
„ Attribute
„ Entity
14
La clase Modelo de objeto de documento (DOM) es una representación en
memoria de un documento XML. El DOM le permite leer, manipular y modificar,
de manera programática un documento XML. La clase XmlReader también lee
XML; sin embargo, proporciona acceso que no está en memoria caché, con
dirección únicamente hacia adelante y de sólo lectura. Esto significa que no
existen capacidades para editar los valores de un atributo o contenido de un
elemento, o la habilidad para insertar y eliminar nodos con XmlReader. Editar
es la función principal del DOM. Es la manera común y estructurada en la que
se representan datos XML en memoria, aunque los datos XML reales se
almacenan de manera lineal cuando están en un archivo o provienen de otro
objeto. Los siguientes son 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>
Dentro de una estructura de documento XML, cada etiqueta en esta ilustración
representa un nodo, conocido como un objeto XmlNode. El objeto XmlNode es
el objeto básico en el árbol DOM. La clase XmlDocument, la cual amplía
XmlNode, soporta métodos para realizar operaciones en el documento entero;
por ejemplo, cargarlo en memoria o guardar XML en un archivo.
Document (Clase XmlDocument) El contenedor de todos los nodos en el árbol.
También se conoce como la raíz del documento, lo cual no siempre es igual al
elemento raíz.
DocumentFragment (Clase XmlDocumentFragment) Una bolsa temporal que
contiene uno o más nodos sin una estructura de árbol.
EntityReference (Clase XmlEntityReference) Representa el texto de referencia
de entidad no ampliado.
Element (Clase XmlElement) Representa un nodo de elemento.
Attribute (Clase XmlAttribute) es un atributo de un elemento.
Entity (Clase XmlEntity) Representa las declaraciones <!ENTITY…> en un
documento XML, ya sea de un subconjunto de definición de tipo de documento
(DTD) interno o de DTDs y entidades de parámetro externas.
Diapositiva 15
XmlReader
„ Lee
el contenido XML cuando el contenido está
disponible totalmente
„ Encuentra
la profundidad de la pila de elementos
XML
„ Lee
„ Se
y navega los atributos
salta elementos y su contenido
„ XmlTextReader
15
La clase XmlReader es una clase base abstracta que proporciona acceso que
no está en memoria caché, con dirección únicamente hacia adelante y de sólo
lectura. La clase XmlReader verifica que XML esté bien formateado, y lanza
XmlExceptions si se encuentra un error. Puede leer un flujo o un documento, e
implementa los requerimientos del espacio de nombre descritos en la
recomendación proporcionada por el W3C ubicado en www.w3.org/TR/RECxml-names.
La clase XmlReader tiene métodos para:
Leer el contenido XML cuando el contenido está disponible en su totalidad; por
ejemplo, un archivo de texto XML.
Encontrar la profundidad de la pila de elementos XML.
Determinar si un elemento tiene contenido o está vacío.
Atributos de leer y navegar.
Saltarse elementos y su contenido.
La clase XmlReader tiene propiedades que devuelven información, como:
El nombre del nodo actual.
El contenido del nodo actual.
XmlTextReader. Clase que lee flujos de caracteres. Es un lector únicamente
hacia adelante con métodos que devuelven datos sobre contenido y tipos de
nodos. No existe soporte para la Definición de tipos de documentos (DTD) o
esquemas.
Ejemplo:
VB.NET
Imports System
Imports System.IO
Imports System.Xml
'Lee un documento XML
Public Class Sample
Private Const filename As String = "items.xml"
Public Shared Sub Main()
Dim reader As XmlTextReader = Nothing
Try
'Cargue el lector con el archivo de datos e ignore todos los nodos de
espacio blancos.
reader = New XmlTextReader(filename)
reader.WhitespaceHandling = WhitespaceHandling.None
'Analice el archivo y muestre cada uno de los nodos.
While reader.Read()
Select Case reader.NodeType
Case XmlNodeType.Element
Console.Write("<{0}>", reader.Name)
Case XmlNodeType.Text
Console.Write(reader.Value)
Case XmlNodeType.CDATA
Console.Write("<![CDATA[{0}]]>", reader.Value)
Case XmlNodeType.ProcessingInstruction
Console.Write("<?{0} {1}?>", reader.Name, reader.Value)
Case XmlNodeType.Comment
Console.Write("<!--{0}-->", reader.Value)
Case XmlNodeType.XmlDeclaration
Console.Write("<?xml version='1.0'?>")
Case XmlNodeType.Document
Case XmlNodeType.DocumentType
Console.Write("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value)
Case XmlNodeType.EntityReference
Console.Write(reader.Name)
Case XmlNodeType.EndElement
Console.Write("</{0}>", reader.Name)
End Select
End While
Finally
If Not (reader Is Nothing) Then
reader.Close()
End If
End Try
End Sub 'Main
End Class 'Sample End class
C#
using System;
using System;
using System.IO;
using System.Xml;
//Lee un documento XML
public class Sample
{
private const String filename = "items.xml";
public static void Main()
{
XmlTextReader reader = null;
try
{
//Cargue el lector con el archivo de datos e ignore todos los nodos de
espacio blancos.
reader = new XmlTextReader(filename);
reader.WhitespaceHandling = WhitespaceHandling.None;
//Analice el archivo y muestre cada uno de los nodos.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<{0}>", reader.Name);
break;
case XmlNodeType.Text:
Console.Write(reader.Value);
break;
case XmlNodeType.CDATA:
Console.Write("<![CDATA[{0}]]>", reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
Console.Write("<?{0} {1}?>", reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
Console.Write("<!--{0}-->", reader.Value);
break;
case XmlNodeType.XmlDeclaration:
Console.Write("<?xml version='1.0'?>");
break;
case XmlNodeType.Document:
break;
case XmlNodeType.DocumentType:
Console.Write("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value);
break;
case XmlNodeType.EntityReference:
Console.Write(reader.Name);
break;
case XmlNodeType.EndElement:
Console.Write("</{0}>", reader.Name);
break;
}
}
}
finally
{
if (reader!=null)
reader.Close();
}
}
} // End class
Diapositiva 16
XmlWriter
„ Escribe
XML bien formado
„ Escribe
múltiples documentos a un flujo de salida
„ Escribe
nombres válidos y nombres calificados
„ Codifica
bytes binarios como base64 y como
binhex y escribe las fichas de texto resultante
„ XmlTextWriter
16
XmlWriter es una clase base abstracta que define una interfaz para escribir
XML. El XmlWriter proporciona una manera únicamente hacia adelante, de sólo
lectura y que no esté en memoria caché de generar flujos XML, lo cual le ayuda
a construir documentos XML que cumplen con la recomendación del Lenguaje
de marcación extensible (XML) 1.0 (Second Edition) del W3C
(www.w3.org/TR/2000/REC-xml-20001006.html) y la recomendación de
Espacios de nombre en XML (www.w3.org/TR/REC-xml-names/).
La siguiente lista muestra que XmlWriter tiene métodos y propiedades definidas
para:
Especificar si se deben soportar los espacios de nombre.
Escribir XML bien formado.
Codifica bytes binarios como base64 y como binhex, y escribe el texto que
resulta.
Administrar la salida, incluyendo métodos para determinar el progreso de la
salida, con la propiedad WriteState.
Escribir múltiples documentos en un flujo de salida.
Vaciar o cerrar el resultado.
Reportar el prefijo del espacio de nombre actual, xml:lang, o el alcance
xml:space.
Escribir nombres válidos, nombres que califican y fichas de nombre.
La siguiente lista identifica lo que XmlWriter no verifica:
Caracteres de elementos y nombres de atributos inválidos.
Caracteres Unicode que no caben en la codificación especificada. Si los
caracteres Unicode no caben en la codificación especificada, el XmlWriter no
escapa los caracteres Unicode en entidades de caracteres.
Atributos duplicados.
Caracteres en el identificador público o identificador del sistema DOCTYPE.
El XmlTextWriter, derivado de XmlWriter, escribe XML a un archivo, consola,
flujo, y otros tipos de salida. Al escribir XML, los métodos realizan trabajo
adicional para producir XML bien formado.
El siguiente ejemplo crea salida XML utilizando el XmlTextWriter.
VB.NET
Shared Sub WriteQuote(ByVal writer As XmlWriter, ByVal symbol As String,
ByVal price As Double, ByVal change As Double, ByVal volume As Long)
writer.WriteStartElement("Acciones")
writer.WriteAttributeString("Símbolo", symbol)
writer.WriteElementString("Precio", XmlConvert.ToString(price))
writer.WriteElementString("Cambio", XmlConvert.ToString(change))
writer.WriteElementString("Volumen", XmlConvert.ToString(volume))
writer.WriteEndElement()
End Sub 'WriteQuote
Public Shared Sub Main()
Dim writer As New XmlTextWriter(Console.Out)
writer.Formatting = Formatting.Indented
WriteQuote(writer, "MSFT", 74.125, 5.89, 69020000)
writer.Close()
End Sub 'Main
C#
static void WriteQuote(XmlWriter writer, string symbol,
double price, double change, long volume)
{
writer.WriteStartElement("Acciones");
writer.WriteAttributeString("Símbolo", symbol);
writer.WriteElementString("Precio", XmlConvert.ToString(price));
writer.WriteElementString("Cambio", XmlConvert.ToString(change));
writer.WriteElementString("Volumen", XmlConvert.ToString(volume));
writer.WriteEndElement();
}
public static void Main()
{
XmlTextWriter writer = new XmlTextWriter(Console.Out);
writer.Formatting = Formatting.Indented;
WriteQuote(writer, "MSFT", 74.125, 5.89, 69020000);
writer.Close();
}
Resultado
<Acciones Simbolo="MSFT">
<Precio>74.125</Precio>
<Cambio>5.89</Cambio>
<Volumen>69020000</Volumen>
</Acciones>
Recursos
„ ADO.NET
http://msdn.microsoft.com/library/default.asp?url=/library/enus/cpguide/html/cpconaccessingdatawithadonet.asp?frame=true
„ El DataSet con información de tipos
http://msdn.microsoft.com/library/default.asp?url=/library/enus/cpguide/html/cpcongeneratingstronglytypeddataset.asp?frame=true
„ Espacio de nombre System.Xml
http://msdn.microsoft.com/library/enus/cpref/html/frlrfsystemxml.asp?frame=true