Compartir a través de


Utilizar anotaciones con un DataSet con información de tipos

Las anotaciones permiten modificar los nombres de los elementos del DataSet con información de tipos sin modificar el esquema subyacente. La modificación de los nombres de los elementos del esquema subyacente haría que el DataSet hiciera referencia a objetos que no existen en el origen de datos, además de perder una referencia a los objetos existentes en el origen de datos.

Con las anotaciones es posible personalizar los nombres de objetos del DataSet con información de tipos para utilizar nombres más significativos; esto hace que el código sea más legible y que los clientes puedan utilizar más fácilmente el DataSet, al tiempo que se deja intacto el esquema subyacente. Por ejemplo, el siguiente elemento de esquema, para la tabla Customers de la base de datos Northwind, da como resultado un nombre de objeto DataRow de CustomersRow y una DataRowCollection denominada Customers.

<xs:element name="Customers">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="CustomerID" type="xs:string" minOccurs="0" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

Un nombre Customers para una DataRowCollection es significativo en el código de cliente, pero una DataRow denominada CustomersRow puede llevar a confusión porque se trata de un único objeto. Además, en muchos escenarios, se haría referencia al objeto sin el identificador Row y en su lugar se haría referencia al mismo simplemente como un objeto Customer. La solución consiste en anotar el esquema e identificar nuevos nombres para los objetos DataRow y DataRowCollection. A continuación se muestra la versión anotada del esquema anterior.

<xs:element name="Customers" codegen:typedName="Customer" codegen:typedPlural="Customers">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="CustomerID" type="xs:string" minOccurs="0" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

Al especificar un valor Customer para typedName, el nombre de un objeto DataRow será Customer. Si se especifica el valor Customers para typedPlural se conservará el nombre Customers para DataRowCollection.

En la siguiente tabla se muestran las anotaciones disponibles.

Anotación Description
typedName Nombre del objeto.
typedPlural Nombre de una colección de objetos.
typedParent Nombre del objeto cuando se hace referencia al mismo en una relación primaria.
typedChildren Nombre del método para devolver objetos de una relación secundaria.
nullValue Valor si el valor subyacente es DBNull. Vea las anotaciones nullValue en la tabla siguiente. El valor predeterminado es _throw.

En la tabla siguiente se presentan los valores que se pueden especificar para la anotación nullValue.

nullValue Description
Valor de reemplazo Especifica un valor que se va a devolver. El valor devuelto debe coincidir con el tipo del elemento. Por ejemplo, utilice nullValue="0" para devolver 0 en el caso de campos null integer.
_throw Inicia una excepción. Éste es el valor predeterminado.
_null Devuelve una referencia nula o inicia una excepción si se encuentra un tipo primitivo.
_empty En el caso de cadenas, devuelve String.Empty; de lo contrario, devuelve un objeto creado desde un constructor vacío. Si se encuentra un tipo primitivo, inicia una excepción.

En la siguiente tabla se muestran los valores predeterminados de los objetos en un DataSet con información de tipos y las anotaciones disponibles.

Objeto/Método/Evento Valor predeterminado Anotación
DataTable TableNameDataTable typedPlural
Métodos de DataTable NewTableNameRow

AddTableNameRow

DeleteTableNameRow

typedName
DataRowCollection TableName typedPlural
DataRow TableNameRow typedName
DataColumn DataTable.ColumnNameColumn

DataRow.ColumnName

typedName
Propiedad PropertyName typedName
Descriptor de acceso secundario GetChildTableNameRows typedChildren
Descriptor de acceso primario TableNameRow typedParent
Eventos de DataSet TableNameRowChangeEvent

TableNameRowChangeEventHandler

typedName

Para utilizar anotaciones de DataSet con información de tipos debe incluir la siguiente referencia xmlns en el esquema del lenguaje de definición de esquemas XML (XSD).

xmlns:codegen="urn:schemas-microsoft-com:xml-msprop"

A continuación se muestra un ejemplo de esquema anotado que expone la tabla Customers de la base de datos Northwind, incluyendo una relación con la tabla Orders.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="CustomerDataSet" 
      xmlns:codegen="urn:schemas-microsoft-com:xml-msprop"
       
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="CustomerDataSet" msdata:IsDataSet="true">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="Customers" codegen:typedName="Customer" codegen:typedPlural="Customers">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="CustomerID" codegen:typedName="CustomerID" type="xs:string" minOccurs="0" />
              <xs:element name="CompanyName" codegen:typedName="CompanyName" type="xs:string" minOccurs="0" />
              <xs:element name="Phone" codegen:typedName="Phone" codegen:nullValue="" type="xs:string" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="Orders" codegen:typedName="Order" codegen:typedPlural="Orders">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="OrderID" codegen:typedName="OrderID" type="xs:int" minOccurs="0" />
              <xs:element name="CustomerID" codegen:typedName="CustomerID" codegen:nullValue="" type="xs:string" minOccurs="0" />
              <xs:element name="EmployeeID" codegen:typedName="EmployeeID" codegen:nullValue="0" type="xs:int" minOccurs="0" />
              <xs:element name="OrderDate" codegen:typedName="OrderDate" codegen:nullValue="1980-01-01T00:00:00" type="xs:dateTime" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
    <xs:unique name="Constraint1">
      <xs:selector xpath=".//Customers" />
      <xs:field xpath="CustomerID" />
    </xs:unique>
    <xs:keyref name="CustOrders" refer="Constraint1" codegen:typedParent="Customer" codegen:typedChildren="GetOrders">
      <xs:selector xpath=".//Orders" />
      <xs:field xpath="CustomerID" />
    </xs:keyref>
  </xs:element>
</xs:schema>

En el siguiente ejemplo de código se utiliza un DataSet con establecimiento inflexible de tipos creado a partir del esquema de ejemplo. Utiliza un DataAdapter para llenar la tabla Customers y otro DataAdapter para llenar la tabla Orders. El DataSet con establecimiento inflexible de tipos define las DataRelations.

Dim nwindConn As SqlConnection = New SqlConnection("Data Source=localhost;Integrated Security=SSPI;" & _
                                                   "Initial Catalog=northwind")
Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT CustomerID, CompanyName, Phone FROM Customers", &
                                                  nwindConn)
Dim orderDA As SqlDataAdapter = New SqlDataAdapter("SELECT OrderID, CustomerID, EmployeeID, OrderDate FROM Orders", &
                                                   nwindConn)

' Populate a strongly typed DataSet.
nwindConn.Open()
Dim custDS As CustomerDataSet = New CustomerDataSet()
custDA.Fill(custDS, "Customers")
orderDA.Fill(custDS, "Orders")
nwindConn.Close()

' Add a strongly typed event.
AddHandler custDS.Customers.CustomerChanged, &
           New CustomerDataSet.CustomerChangeEventHandler(AddressOf OnCustomerChanged)

' Add a strongly typed DataRow.
Dim newCust As CustomerDataSet.Customer = custDS.Customers.NewCustomer()
newCust.CustomerID = "NEW01"
newCust.CompanyName = "My New Company"
custDS.Customers.AddCustomer(newCust)

' Navigate the child relation.
Dim customer As CustomerDataSet.Customer
Dim order As CustomerDataSet.Order

For Each customer In custDS.Customers
  Console.WriteLine(customer.CustomerID)
  For Each order In customer.GetOrders()
    Console.WriteLine(vbTab & order.OrderID)
  Next
Next

Private Shared Sub OnCustomerChanged(sender As Object, e As CustomerDataSet.CustomerChangeEvent)

End Sub
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlDataAdapter custDA = new SqlDataAdapter("SELECT CustomerID, CompanyName, Phone FROM Customers", nwindConn);
SqlDataAdapter orderDA = new SqlDataAdapter("SELECT OrderID, CustomerID, EmployeeID, OrderDate FROM Orders", nwindConn);

// Populate a strongly typed DataSet.
nwindConn.Open();
CustomerDataSet custDS = new CustomerDataSet();
custDA.Fill(custDS, "Customers");
orderDA.Fill(custDS, "Orders");
nwindConn.Close();

// Add a strongly typed event.
custDS.Customers.CustomerChanged += new 
  CustomerDataSet.CustomerChangeEventHandler(OnCustomerChanged);

// Add a strongly typed DataRow.
CustomerDataSet.Customer newCust = custDS.Customers.NewCustomer();
newCust.CustomerID = "NEW01";
newCust.CompanyName = "My New Company";
custDS.Customers.AddCustomer(newCust);

// Navigate the child relation.
foreach(CustomerDataSet.Customer customer in custDS.Customers)
{
  Console.WriteLine(customer.CustomerID);
  foreach(CustomerDataSet.Order order in customer.GetOrders())
    Console.WriteLine("\t" + order.OrderID);
}

protected static void OnCustomerChanged(object sender, CustomerDataSet.CustomerChangeEvent e)
{

}

Vea también

Trabajar con DataSet con información de tipos | Crear y utilizar DataSets | DataColumnCollection (Clase) | DataSet (Clase)