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)
{
}