Partager via


Utilisation d'annotations avec un DataSet typé

Les annotations vous permettent de modifier le nom des éléments de votre DataSet typé sans pour autant modifier le schéma sous-jacent. Si vous modifiiez le nom des éléments de votre schéma sous-jacent, le DataSet typé ferait référence à des objets qui n'existent pas dans la source de données et perdrait des références vers des objets qui existent bien dans la source de données.

En utilisant des annotations, vous pouvez personnaliser le nom des objets de votre DataSet typé au profit de noms plus conviviaux qui rendront le code plus aisé à lire et votre DataSet typé plus facile à utiliser par les clients, tout en laissant intact le schéma sous-jacent. Par exemple, l'élément de schéma suivant pour la table Customers de la base de données Northwind donnerait un objet DataRow nommé CustomersRow et un DataRowCollection nommé Customers.

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

Le nom Customers pour un DataRowCollection est évocateur dans un code client, mais le nom CustomersRow pour un DataRow est équivoque, car il s'agit d'un objet unique. C'est pourquoi, dans un scénario classique, il serait fait référence à l'objet sans l'identificateur Row, pour donner simplement Customer. La solution consiste à annoter le schéma et à identifier de nouveaux noms pour les objets DataRow et DataRowCollection. Voici une version annotée du précédent schéma.

<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>

En assignant à typedName la valeur Customer, vous obtenez un DataRow nommé Customer. En assignant à typedPlural la valeur Customers, vous conservez le nom Customers pour le DataRowCollection.

Le tableau suivant présente les différentes annotations disponibles.

Annotation Description
typedName Nom de l'objet.
typedPlural Nom d'une collection d'objets.
typedParent Nom de l'objet lorsqu'il y est fait référence dans une relation parente.
typedChildren Nom de la méthode permettant de retourner des objets d'une relation enfant.
nullValue Valeur à utiliser si la valeur sous-jacente est DBNull. Consultez le tableau suivant pour les annotations nullValue. La valeur par défaut est _throw.

Le tableau suivant présente les valeurs qui peuvent être spécifiées pour l'annotation nullValue.

nullValue Description
Valeur de remplacement Spécifie une valeur à retourner. La valeur retournée doit correspondre au type de l'élément. Par exemple, utilisez nullValue="0" pour retourner 0 pour les champs de type null integer (entier nul).
_throw Levée d'une exception. Il s'agit de la valeur par défaut.
_null Retourner une référence null ou lever une exception si un type primitif est rencontré.
_empty Pour des chaînes, retourner String.Empty, dans les autres cas, retourner un objet créé à partir d'un constructeur vide. Si un type primitif est rencontré, lever une exception.

Le tableau suivant présente les valeurs par défaut pour les objets d'un DataSet typé et les annotations disponibles.

Objet/méthode/événement Par défaut Annotation
DataTable TableNameDataTable typedPlural
Méthodes de DataTable NewTableNameRow

AddTableNameRow

DeleteTableNameRow

typedName
DataRowCollection TableName typedPlural
DataRow TableNameRow typedName
DataColumn DataTable.ColumnNameColumn

DataRow.ColumnName

typedName
Propriété PropertyName typedName
Accesseur enfant GetChildTableNameRows typedChildren
Accesseur parent TableNameRow typedParent
Événements de DataSet TableNameRowChangeEvent

TableNameRowChangeEventHandler

typedName

Pour utiliser des annotations de DataSet typé, vous devez inclure la référence xmlns suivante dans votre schéma XSD (XML Schema Definition language).

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

L'exemple suivant est un schéma annoté qui expose la table Customers de la base de données Northwind et inclut une relation avec la table 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>

L'exemple de code suivant utilise un DataSet fortement typé créé à partir du schéma précédent. Il utilise un DataAdapter pour remplir la table Customers et un autre pour remplir la table Orders. Le DataSet fortement typé définit le 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)
{

}

Voir aussi

Utilisation d'un DataSet typé | Création et utilisation de DataSets | DataColumnCollection, classe | DataSet, classe