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