Anotando DataSets tipados

As anotações permitem que você modifique os nomes dos elementos em seu DataSet tipado sem modificar o esquema subjacente. Modificar os nomes dos elementos no esquema subjacente faz o DataSet tipado referir-se a objetos que não existem na fonte de dados, além de perder uma referência a objetos existentes na fonte de dados.

Usando as anotações, é possível personalizar os nomes dos objetos no DataSet tipado com nomes mais significativos, tornando o código mais legível e o DataSet tipado mais fácil para uso dos clientes, deixando o esquema subjacente intacto. Por exemplo, o seguinte elemento de esquema da tabela Customers do banco dedados Northwind resultaria em um nome de objeto DataRow de CustomersRow e um DataRowCollection nomeado Customers.

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

Um nome DataRowCollection de Clientes é significativo no código do cliente, mas um nome DataRow de CustomersRow é enganoso porque é um único objeto. Além disso, em cenários comuns, o objeto seria referido sem o identificador Row e, em vez disso, seria simplesmente referido como um objeto Customer. A solução é anotar o esquema e identificar os novos nomes para os objetos DataRow e DataRowCollection. Veja a seguir a versão anotada do 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>  

Especificar um valor typedName de Customer resultará em nome de objeto DataRow de Customer. Especificar um valor typedPlural de Customers preservará o nome DataRowCollection de Customers.

A tabela a seguir mostra as anotações disponíveis para uso.

Annotation Descrição
typedName Nome do objeto.
typedPlural Nome de uma coleção de objetos.
typedParent Nome do objeto quando chamado em uma relação de pai.
typedChildren Nome do método para retornar objetos de uma relação filho.
nullValue Valor se o valor subjacente for DBNull. Consulte a tabela a seguir para anotaçõesnullValue. O padrão é _throw.

A tabela a seguir mostra os valores que podem ser especificados para a anotação nullValue.

Valor nullValue Descrição
Valor de Substituição Especifique um valor a ser retornado. O valor retornado deve corresponder ao tipo de elemento. Por exemplo, use nullValue="0" para retornar 0 para campos de inteiro nulos.
_throw Gera uma exceção. Esse é o padrão.
_null Retorna uma referência nula ou gera uma exceção se um tipo primitivo for localizado.
_empty Para cadeias de caracteres, retorne String.Empty, caso contrário, retorne um objeto criado de um construtor vazio. Se um tipo primitivo for encontrado, gera uma exceção.

A tabela a seguir mostra os valores padrão para objetos em um DataSet tipado e as anotações disponíveis.

Objeto/método/evento Padrão Annotation
DataTable TableNameDataTable typedPlural
Métodos DataTable NewTableNameRow

AddTableNameRow

DeleteTableNameRow
typedName
DataRowCollection TableName typedPlural
DataRow TableNameRow typedName
DataColumn DataTable.ColumnNameColumn

DataRow.ColumnName
typedName
Propriedade PropertyName typedName
Acessador Child GetChildTableNameRows typedChildren
Acessador Parent TableNameRow typedParent
Eventos DataSet TableNameRowChangeEvent

TableNameRowChangeEventHandler
typedName

Para usar as anotações DataSet, será necessário incluir a seguinte referência xmlns no esquema (XSD) de linguagem de definição de esquema XML. Para criar um xsd de tabelas de banco de dados, consulte WriteXmlSchema ou Trabalhar com conjuntos de dados no Visual Studio.

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

O seguinte é um esquema anotado de exemplo que expõe a tabela Customers do banco de dados Northwind com uma relação com a tabela Orders incluída.

<?xml version="1.0" encoding="utf-8"?>  
<xs:schema id="CustomerDataSet"
      xmlns:codegen="urn:schemas-microsoft-com:xml-msprop"  
      xmlns=""
      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="OrderAdapter"  
codegen:typedName="OrderAdapter" 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>  

O exemplo de código usa um DataSet fortemente tipado criado do esquema de exemplo. Usa um SqlDataAdapter para preencher a tabela Customers e outro SqlDataAdapter para preencher a tabela Orders. O DataSet fortemente tipado define o DataRelations.

' Assumes a valid SqlConnection object named connection.  
Dim customerAdapter As SqlDataAdapter = New SqlDataAdapter( _  
    "SELECT CustomerID, CompanyName, Phone FROM Customers", &  
    connection)  
Dim orderAdapter As SqlDataAdapter = New SqlDataAdapter( _  
    "SELECT OrderID, CustomerID, EmployeeID, OrderAdapter FROM Orders", &  
    connection)  
  
' Populate a strongly typed DataSet.  
connection.Open()  
Dim customers As CustomerDataSet = New CustomerDataSet()  
customerAdapter.Fill(customers, "Customers")  
orderAdapter.Fill(customers, "Orders")  
connection.Close()  
  
' Add a strongly typed event.  
AddHandler customers.Customers.CustomerChanged, &  
    New CustomerDataSet.CustomerChangeEventHandler( _  
    AddressOf OnCustomerChanged)  
  
' Add a strongly typed DataRow.  
Dim newCustomer As CustomerDataSet.Customer = _  
    customers.Customers.NewCustomer()  
newCustomer.CustomerID = "NEW01"  
newCustomer.CompanyName = "My New Company"  
customers.Customers.AddCustomer(newCustomer)  
  
' Navigate the child relation.  
Dim customer As CustomerDataSet.Customer  
Dim order As CustomerDataSet.Order  
  
For Each customer In customers.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  
// Assumes a valid SqlConnection object named connection.  
SqlDataAdapter customerAdapter = new SqlDataAdapter(  
    "SELECT CustomerID, CompanyName, Phone FROM Customers",  
    connection);  
SqlDataAdapter orderAdapter = new SqlDataAdapter(  
    "SELECT OrderID, CustomerID, EmployeeID, OrderAdapter FROM Orders",
    connection);  
  
// Populate a strongly typed DataSet.  
connection.Open();  
CustomerDataSet customers = new CustomerDataSet();  
customerAdapter.Fill(customers, "Customers");  
orderAdapter.Fill(customers, "Orders");  
connection.Close();  
  
// Add a strongly typed event.  
customers.Customers.CustomerChanged += new
  CustomerDataSet.CustomerChangeEventHandler(OnCustomerChanged);  
  
// Add a strongly typed DataRow.  
CustomerDataSet.Customer newCustomer =
    customers.Customers.NewCustomer();  
newCustomer.CustomerID = "NEW01";  
newCustomer.CompanyName = "My New Company";  
customers.Customers.AddCustomer(newCustomer);  
  
// Navigate the child relation.  
foreach(CustomerDataSet.Customer customer in customers.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)  
    {  
  
    }  

Confira também