Está en la página 1de 9

Capitulo 1: Clases desconectadas de ADO.

NET (Parte 3)
Lección 2: Serialización, tipos especializados y enlace de datos

■ Utilice las clases desconectadas para crear una aplicación que puede recoger datos de un


usuario y almacenarlo en un archivo binario o XML.
■ Guarde los objetos especializados en un valor de la columna y recuperar estos objetos.
■ Conexión de las clases de ADO.NET a la interfaz gráfica de usuario mediante el uso
de técnicas de enlace de datos.

Serializar y deserializar el DataTable con datos XML


El contenido de un DataTable se puede escribir un archivo XML o una secuencia, mediante el
método WriteXml:
---------------------------------VB---------------------------------
'metodo para crear nombres de archivos en el escritorio
Private Function desktopFileName(ByVal fileName As String)As String
 
Return Path.Combine(Environment.GetFolderPath (Environment.SpecialFold
er.Desktop),fileName)
End Function
'escribo un xml
cars.WriteXml(desktopFileName("Cars.xml”))
---------------------------------CS---------------------------------
//metodo para crear nombres de archivos en el escritorio
private string desktopFileName(string fileName)
{
  returnPath.Combine(
  Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
  fileName);
}
//escribo el xml
cars.WriteXml(desktopFileName("Cars.xml"));
--------------------------------------------------------------------
Si este código se ejecuta con DataSet definido en la lección anterior, el archivo cars.xml se
verá así:
xml version="1.0" standalone="yes"?>
<DocumentElement>
  <Cars>
    <Vin>123456789ABCD<Vin>
    <Make>Ford<Make>
    <Year>2002<Year>
    <Year_x0020_and_x0020_Make>2002 Ford<Year_x0020_and_x0020_Make>
    <Cars>
  <Cars>
    <Vin>987654321XYZ<Vin>
    <Make>Jeep<Make>
    <Year>2002<Year>
    <Year_x0020_and_x0020_Make>2002 Jeep<Year_x0020_and_x0020_Make>
    <Cars>
<DocumentElement>

En este ejemplo se utiliza DocumentElement como el elemento raíz y Cars para cada fila de
datos. Un nombre de elemento XML no puede contener caracteres de espacio, por lo que “Year
and Make” se convierten automáticamente a Year_x0020_and_x0020_Make.

Puede ajustar la salida XML, proporcionando un esquema XML o establecer las propiedades de
la tabla de datos y sus columnas. Para cambiar los atributos Vin, Marca y año se puede
establecer la propiedad ColumnMapping cada DataColumn de MappingType.Attribute.
La columna ”Year and Make”  es una columna calculada, por lo que sus datos no necesitan ser
almacenados, para esto se debe establecer su propiedad ColumnMapping a
MappingType.Hidden.

Nombre Descripción
Element La columna se asigna a un elemento XML.
Attribute La columna se asigna a un atributo XML.
SimpleContent La columna se asigna a un nodo XmlText.
Hidden La columna se asigna a una estructura interna.

Es importante entender que la propiedad ColumnMapping sólo afecta  al formato de los datos al
escribir en XML.
---------------------------------VB---------------------------------
'seteo el nombre de la tabla y la forma de mapear columnas
cars.TableName = "Auto"
cars.Columns("Vin").ColumnMapping= MappingType.Attribute
cars.Columns("Make").ColumnMapping = MappingType.Attribute
cars.Columns("Year").ColumnMapping = MappingType.Attribute
cars.Columns("Year and Make").ColumnMapping= MappingType.Hidden
---------------------------------CS---------------------------------
//seteo el nombre de la tabla y la forma de mapear columnas
car.TableName = "Auto";
car.Columns["Vin"].ColumnMapping= MappingType.Attribute;
car.Columns["Make"].ColumnMapping = MappingType.Attribute;
car.Columns["Year"].ColumnMapping = MappingType.Attribute;
car.Columns["Year and Make"].ColumnMapping= MappingType.Hidden;
--------------------------------------------------------------------
El XML quedaría de esta forma:
<xml version="1.0" standalone="yes"?>
<DocumentElement>
  <Auto Vin="123456789ABCD" Make="Ford" Year="2002" />
  <Auto Vin="987654321XYZ" Make="Jeep" Year="2002" />
<DocumentElement>

El XML es bastante compacto, pero los tipos de datos no se guardan y todos se consideran
string.Para almacenar el esquema XML con los datos y sus tipos, se agrega la enumeración
XmlWriteMode.WriteSchema al guardar:
---------------------------------VB---------------------------------
cars.WriteXml(desktopFileName("CarWithSchema.xml"), XmlWriteMode.Write
Schema)
---------------------------------CS---------------------------------
car.WriteXml(desktopFileName("CarWithSchema.xml"), XmlWriteMode.WriteS
chema);
--------------------------------------------------------------------
Guardándolo de esta forma el xml quedaria:
<xml version="1.0" standalone="yes"?>
<NewDataSet>
  <xs:schema id="NewDataSet" xmlns=""
  xmlns:xs=http://www.w3.org/2001/XMLSchema
  xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet"msdata:IsDataSet="true"
    msdata:MainDataTable="Auto" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Auto">
            <xs:complexType>
             
<xs:attribute name="Vin" msdata:Caption="VIN" use="required">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="23" />
                  <xs:restriction>
                <xs:simpleType>
              <xs:attribute>
              <xs:attribute name="Make" use="required">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="35" />
                  <xs:restriction>
                <xs:simpleType>
              <xs:attribute>
             
<xs:attribute name="Year" type="xs:int" use="required" />
              <xs:attribute name="Year_x0020_and_x0020_Make"
              msdata:ReadOnly="true"
              msdata:Expression="Year + ' ' + Make"use="prohibited">
                <xs:simpleType>
                  <xs:restriction base="xs:string">
                    <xs:maxLength value="70" />
                  <xs:restriction>
                <xs:simpleType>
              <xs:attribute>
            <xs:complexType>
          <xs:element>
        <xs:choice>
      <xs:complexType>
      <xs:unique name="Constraint1" msdata:PrimaryKey="true">
        <xs:selector xpath=".//Auto" />
        <xs:field xpath="@Vin" />
      <xs:unique>
    <xs:element>
  <xs:schema>
  <Auto Vin="123456789ABCD" Make="Ford" Year="2002" />
  <Auto Vin="987654321XYZ" Make="Jeep" Year="2002" />
<NewDataSet>

Con el esquema XML incluido, todos los tipos de datos están definidos y un
DataTable se podría cargar sin  problemas desde este archivo:
---------------------------------VB---------------------------------
Dim xmlTableAs New DataTable()
xmlTable.ReadXml(desktopFileName("CarWithSchema.xml"))
---------------------------------CS---------------------------------
DataTable xmlTable = newDataTable();
xmlTable.ReadXml(desktopFileName("CarWithSchema.xml"));
--------------------------------------------------------------------

Serialización y deserialización de DataSet


Un DataSet puede ser guardado o serializado, como XML o como datos binarios en un  stream
o archivo, sino que también se puede cargar o deserializar, con datos XML o binarios de un
stream  o archivo. Pueden ser transferidos a través de una red de varios protocolos, incluyendo
HTTP.

Serialización de un DataSet como XML


Se puede serializar un DataSet en un archivo XML mediante la ejecución de su método
WriteXml como vimos anteriormente.
Una relación entre tablas se implementa mediante una DataRelation y cuando se guarda en un
XML, las relaciones primaria-secundaria se representan mediante elementos primarios que
contienen elementos secundarios anidados. Para facilitar el anidamiento de objetos
secundarios se establece la propiedad Nested como true, las filas secundarias de la relación
se anidan dentro de la columna primaria cuando se escriben comodatos XML. La
propiedad Nested de la DataRelation es false de manera predeterminada.
---------------------------------VB---------------------------------
vendorData.Relations("vendor_part").Nested= True
For Each dt As DataTable InvendorData.Tables
   ForEach dc AsDataColumn In dt.Columns
       IfNot (dc.DataType.Equals(GetType(Guid))) Then
          dc.ColumnMapping= MappingType.Attribute
       EndIf
   Next
Next
vendorData.WriteXml(desktopFileName("Vendors1.xml"),_
XmlWriteMode.IgnoreSchema)

---------------------------------CS---------------------------------
//anido los datos y los atributos xml
vendorData.Relations["vendor_part"].Nested= true;
foreach (DataTable dt in vendorData.Tables)
{
   foreach(DataColumn dc in dt.Columns)
   {
       if(dc.DataType != typeof(Guid))
         dc.ColumnMapping = MappingType.Attribute;
   }
}
vendorData.WriteXml(desktopFileName("Vendors1.xml"),
XmlWriteMode.IgnoreSchema);
--------------------------------------------------------------------
De esta forma quedaría el XML con las relaciones anidadas:
<xml version="1.0" standalone="yes"?>
<VendorData>
  <Vendor Name="Tailspin Toys">
    <Id>d012b54d-c855-4c1f-969e-74554d2cb0c7<Id>
    <Part PartCode="WGT1" PartDescription="Widget 1Description"
    Cost="10" RetailPrice="12.32">
      <Id>167583e9-f4eb-4004-9efa-5477e0f55208<Id>
      <VendorId>d012b54d-c855-4c1f-969e-74554d2cb0c7<VendorId>
    <Part>
    <Part PartCode="WGT2" PartDescription="Widget 2Description"
    Cost="9" RetailPrice="11.32">
      <Id>d3b42db7-b23f-4c33-9961-f7a325342167<Id>
      <VendorId>d012b54d-c855-4c1f-969e-74554d2cb0c7<VendorId>
    <Part>
  <Vendor>
<VendorData>
Para poder pasar los tipos de datos se la para como parámetro XmlWriteMode.WriteSchema ,
el archivo XML resultante es mucho mas grande.
Se puede utilizar el método WriteXmlSchema del DataSet para extraer la definición de
esquema XML en un archivo separado.
---------------------------------VB---------------------------------
vendorData.WriteXmlSchema(desktopFileName("VendorSchema.xsd"))
---------------------------------CS---------------------------------
vendorData.WriteXmlSchema(desktopFileName("VendorSchema.xsd"));
--------------------------------------------------------------------
Serialización de un DataSet como un DiffGram
Un DiffGram es un documento XML que contiene todos los datos del dataset, incluida la
información DataRow original (DataRowVersion).Un DataSet se puede serializar como un
DiffGram simplemente pasando XmlWriteMode.DiffGram al método WriteXml.
---------------------------------VB---------------------------------
vendorData.WriteXml(desktopFileName("VendorSchema.xsd"),
XmlWriteMode.DiffGram)
---------------------------------CS---------------------------------
vendorData.WriteXml(desktopFileName("VendorSchema.xsd")
XmlWriteMode.DiffGram);
--------------------------------------------------------------------
Ejemplo de como se vería un XML DiffGram:
<xml version="1.0" standalone="yes"?>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
  <VendorData>
    <Vendor diffgr:id="Vendor1" msdata:rowOrder="0" Name="Tailspin
Toys">
      <Id>9e3fe885-8ffd-4c58-9cbf-a486dcbc930e<Id>
     
<Part diffgr:id="Part1" msdata:rowOrder="0" diffgr:hasChanges="modifie
d"
      PartCode="WGT1" PartDescription="Widget 1Description"
      Cost="12" RetailPrice="12.32">
        <Id>4e91d3ca-a4a0-416e-ad4d-cebf047afcf4<Id>
        <VendorId>9e3fe885-8ffd-4c58-9cbf-a486dcbc930e<VendorId>
      <Part>
    <Vendor>
  <VendorData>
  <diffgr:before>
    <Part diffgr:id="Part1" msdata:rowOrder="0" PartCode="WGT1"
    PartDescription="Widget 1
Description"Cost="10" RetailPrice="12.32">
      <Id>4e91d3ca-a4a0-416e-ad4d-cebf047afcf4<Id>
      <VendorId>9e3fe885-8ffd-4c58-9cbf-a486dcbc930e<VendorId>
    <Part>
   
<Part diffgr:id="Part2" diffgr:parentId="Vendor1" msdata:rowOrder="1"
          PartCode="WGT2" PartDescription="Widget 2
Description" Cost="9"
          RetailPrice="11.32">
      <Id>75a54b24-f8bd-4bbd-8427-20a277a44908<Id>
      <VendorId>9e3fe885-8ffd-4c58-9cbf-a486dcbc930e<VendorId>
    <Part>
  <diffgr:before>
<diffgr:diffgram>
Deserializar DataSet a partir de XML
Un dataset se puede crear fácilmente mediante la deserialización de un archivo XML o un
stream:
---------------------------------VB---------------------------------
'lee un xml y carga el dataset
Dim vendorData As New DataSet()
vendorData.ReadXmlSchema(desktopFileName("VendorSchema.xsd"))
vendorData.ReadXml(desktopFileName("Vendors3.xml"),_
XmlReadMode.IgnoreSchema)
---------------------------------CS---------------------------------
//lee un xml y carga el dataset
DataSet vendorData = new DataSet();
vendorData.ReadXmlSchema(desktopFileName("VendorSchema.xsd"));
vendorData.ReadXml(desktopFileName("Vendors3.xml"),
XmlReadMode.IgnoreSchema);
--------------------------------------------------------------------
Nombre Descripción
Auto Predeterminado. El XML es examinado por el método ReadXml y se
selecciona el modo apropiado.
ReadSchema Lee cualquier esquema en línea y carga los datos. Si el DataSet ya contiene un
esquema, se pueden agregar al mismo las nuevas tablas, aunque se producirá
una excepción si cualquier tabla del esquema en línea ya existe en el DataSet.
IgnoreSchema Omite cualquier esquema y lee los datos del esquema del DataSetexistente. Si
los datos no coinciden con el esquema existente, se descartan
InferSchema Omite cualquier esquema, deduce el esquema a partir de los datos y los carga.
DiffGram Lee un DiffGram, aplicando los cambios del DiffGram a DataSet. La semántica
es idéntica a la de una operación Merge. Al igual que ocurre con la
operación Merge, se conservan los valores RowState.
Fragment Lee fragmentos XML, como los que se generan al ejecutar consultas  en una
instancia de SQL Server. Al establecer XmlReadMode en Fragment, se lee el
espacio de nombres predeterminado como el esquema en línea.
InferTypedSchema Omite cualquier esquema, deduce el esquema con establecimiento inflexible
de tipos a partir de los datos y los carga. Si el tipo no se puede deducir de los
datos, se interpreta como datos de cadena. Si elDataSet ya contiene un
esquema, se extiende el esquema actual mediante la adición de nuevas tablas
o columnas a las tablas existentes.

Serializar el DataSet como datos binarios


Aunque el conjunto de datos se puede serializar en XML, en muchos casos, el tamaño del
archivo XML causa problemas con los recursos como la memoria y espacio en el disco o ancho
de banda cuando se mueve estos datos a través de la red. Si el XML no es necesario,el
conjunto de datos se puede serializar como un archivo binario:
---------------------------------VB---------------------------------
'agrego los Imports
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Dim fsas new FileStream(_
desktopFileName("VendorData.bin",FileMode.Create)
Dim fmtAs New BinaryFormatter()
‘si no colocamos serializationFormat.Binary, el archivo binario
‘tiene un formato BinaryXML (un archivo que guarda xml adentro),
‘pero de esta forma queda con TrueBinary
vendorData.RemotingFormat = SerializationFormat.Binary
fmt.Serialize(fs, vendorData)
fs.Close()
---------------------------------CS---------------------------------
//agrego los using
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
 
FileStream fs = new FileStream(
desktopFileName("VendorData.bin"),FileMode.Create);
BinaryFormatter fmt = new BinaryFormatter();
//si no colocamos serializationFormat.Binary, el archivo binario
//tiene un formato BinaryXML (un archivo que guarda xml adentro),
//pero de esta forma queda con TrueBinary
vendorData.RemotingFormat = SerializationFormat.Binary;
fmt.Serialize(fs, vendorData);
 
fs.Close( );
--------------------------------------------------------------------
Deserializar un DataSet a partir de datos binarios
El archivo de datos binarios que ha guardado en el ejemplo anterior puede ser serializado
dentro de un dataset. El BinaryFormatter almacena el esquema de forma automática, así que
no hay necesidad de cargar un primer esquema. El BinaryFormatter automáticamente identifica
el archivo como si hubiera sido guardado como BinaryXml o TrueBinary:
---------------------------------VB---------------------------------
'deserializar un archivo binario
Dim vendorData As DataSet
Dim fsAs New FileStream(_
desktopFileName("VendorData.bin"),FileMode.Open)
Dim fmtAs New BinaryFormatter()
vendorData = CType(fmt.Deserialize(fs),DataSet)
fs.Close()
---------------------------------CS---------------------------------
 DataSet vendorData;
 FileStream fs = new FileStream(
desktopFileName("VendorData.bin"), FileMode.Open);
 BinaryFormatterfmt = newBinaryFormatter();
vendorData = (DataSet)fmt.Deserialize(fs);
 fs.Close();
--------------------------------------------------------------------
Recorriendo datos con la clase DataTableReader
La clase DataTableReader permite recorrer DataRows en una o más DataTable. Contiene un
método llamado Read que se ejecuta para cargar  de a una fila de datos y luego la posición se
puede ir avanzando.Si se llega al final, el método Read devuelve un valor nulo.
La clase DataSet contiene un método llamado CreateDataReader que devuelve una instancia
de la clase DataTableReader. Si el conjunto de datos contiene más de una tabla, el
DataTableReader lee las filas del primer DataTable, y se puede utilizar el método NextResult
para continua recorriendo todas las DataTable del dataset.
---------------------------------VB---------------------------------
 'leo los datos delDataTable
 Dim rd As DataTableReader=masterData.CreateDataReader()
 While (rd.Read())
    TextBox1.AppendText(rd("Name").ToString()+ vbCrLf)
End While
 rd.NextResult()
 While (rd.Read())
    TextBox1.AppendText(rd("PartName").ToString()+ vbCrLf)
 End While
---------------------------------CS---------------------------------
 //leo los datos en elDataTable
 DataTableReader rd= masterData.CreateDataReader();
 while (rd.Read())
{
    textBox1.AppendText(rd["Name"].ToString()+ "\r\n");
}
rd.NextResult();
 while (rd.Read())
{
    textBox1.AppendText(rd["PartName"].ToString()+ "\r\n");
 }
-------------------------------------------------------------------
Manejo de tipos especializados
La clase DataTable permite tener columnas cuyo tipo sea especializado y requiere un
tratamiento especial en algunos casos, porque si el tipo de datos de una columna se utiliza
como una clave principal o como un RowFilter para una vista de datos, cualquier cambio en el
valor de la columna debe incluir la asignación de un nuevo objeto a la columna en lugar de sólo
cambiar las propiedades existentes en esta. Esta asignación es necesaria para activar la
actualización de los índices internos utilizados por ordenar, filtrar, y las operaciones de primary
key.

---------------------------------VB--------------------------

<Serializable()> 
Public Class Car 
    Public Property Make() As String 
    Public Property Model() As String 
    Public Property Year() As Integer 
End Class
---------------------------------CS--------------------------

[Serializable] 
    public class Car 
    { 
        public int Year { get; set; } 
        public string Make { get; set; } 
        public string Model { get; set; } 
    }
-------------------------------------------------------------
Data Bindings

La mayoría de los controles que se utilizan en formularios Windows Forms, ASP.NET o


Windows Presentation Foundation (WPF) son enlazables a datos.

Enlace de datos en aplicaciones de Windows Forms y Web Forms (ASPX) 

Para enlazar controles en una aplicación de Windows Forms, se debe establecer la propiedad
DataSource del control a un objeto que implemente la interfaz IList. Además, puede que se
tengan que establecer otras propiedades, dependiendo del tipo de control y la fuente de los
datos:

         DataSource: propiedad a la que se le asignan los datos (cualquier elemento que


implemente la interface IListSource, IBindingList, IBindingListView  e IEnumerable en
ASPX).

         DataMember: cuando de asigna la propiedad DataSource, si el objeto contiene mas de


una columna se debe especificar cual se va a usar (se coloca el nombre de la columna a
usar).

         DisplayMember: se usa en controles como los ComboBox y ListBox (DropDownList y 


ListBox en ASPX), para indicar que columna va a ser mostrada.

         ValueMember: En ComboBoxs y ListBoxs (DropDownList y ListBox en ASPX), indica


la columna que será devuelta cuando un valor es seleccionado.

Enlace de datos en Windows Presentation Foundation (WPF)

Las aplicaciones WPF requieren un objetivo y una fuente en el DataBinding. El destino de


enlace puede ser de cualquier propiedad accesible (publica) derivada de DependencyProperty,
puede unirse a los dataSet y dataTables, y puede unirse a Common Language Runtime (CLR),
los XAML. Para enlazar los controles se puede utilizar la propiedad ItemsSource.

Resumen de la lección

En esta lección se proporciona información acerca de la serialización y deserialización de las


clases ADO.NET desconectadas, así como sobre el manejo de los tipos de datos
especializados en un DataSet y DataTable.

         Los DataSets y DataTables se pueden serializar y deserializar desde y hacia un archivo


binario o XML o una secuencia.

         El valor de la columna puede contener objetos personalizados.

         Puede utilizar DataTableReader para recorrer una dataTable.y rellenar ventanas y


controles Web.
         La mayoría de los controles de interfaz gráfica de usuario tiene una propiedad
DataSource y la propiedad DataMember, que son utilizadas para el enlace de datos.

También podría gustarte