Extraction des valeurs de champs Identité ou NuméroAuto

Vous pouvez définir une colonne d'un DataTable en tant que clé primaire auto-incrémentée afin que chaque ligne de la table ait une valeur unique. Toutefois, vous pouvez disposer de plusieurs clients pour votre application, et chacun d'eux peut travailler avec une instance distincte du DataTable. Dans ce cas, vous pouvez vous retrouver avec des valeurs dupliquées entre les différentes instances du DataTable. Étant donné que tous vos clients travaillent avec une seule source de données, vous pouvez résoudre ce conflit en laissant la source de données définir la valeur auto-incrémentée. Pour ce faire, vous pouvez utiliser les champs Identité dans Microsoft SQL Server, ou NuméroAuto dans Microsoft Access.

L'utilisation de la source de données pour remplir une colonne Identité ou NuméroAuto pour une nouvelle ligne ajoutée à un DataSet crée une situation unique, car le DataSet n'a pas de connexion directe à la source de données. Par conséquent, le DataSet ignore l'existence des valeurs générées automatiquement par la source de données. Toutefois, avec une source de données capable de créer des procédures stockées avec paramètres de sortie, comme Microsoft SQL Server, vous pouvez spécifier une valeur générée automatiquement, telle qu'une nouvelle valeur d'identité, en tant que paramètre de sortie et utiliser le DataAdapter pour répercuter cette valeur dans la colonne du DataSet.

Il est possible que votre source de données ne prenne pas en charge les procédures stockées avec paramètres de sortie. Dans ce cas, vous pouvez utiliser l'événement RowUpdated pour extraire une valeur générée automatiquement et la placer dans la ligne insérée ou mise à jour du DataSet. Cette section comprend un exemple qui montre comment, avec Microsoft Access 2000 ou version ultérieure et à l'aide du fournisseur OLE DB Jet 4.0, vous pouvez ajouter du code à l'événement RowUpdated pour déterminer si une insertion a eu lieu et extraire la valeur auto-incrémentée afin de la stocker dans la ligne actuellement mise à jour.

La procédure stockée et l'exemple de code suivants montrent comment répercuter la valeur d'identité auto-incrémentée d'une table Microsoft SQL Server dans la colonne appropriée d'une ligne ajoutée à une table d'un DataSet. La procédure stockée sert à insérer une nouvelle ligne dans la table Categories de la base de données Northwind et à retourner la valeur d'identité retournée à partir de SCOPE_IDENTITY() en tant que paramètre de sortie.

CREATE PROCEDURE InsertCategory
  @CategoryName nchar(15),
  @Identity int OUT
AS
INSERT INTO Categories (CategoryName) VALUES(@CategoryName)
SET @Identity = SCOPE_IDENTITY()

La procédure stockée InsertCategory peut ensuite être spécifiée comme source du DataAdapter.InsertCommand. Un paramètre est créé pour recevoir le paramètre de sortie d'identité. Ce paramètre a un argument Direction défini à ParameterDirection.Output et un SourceColumn spécifié en tant que colonne CategoryID de la table locale Categories du DataSet. Lorsque InsertCommand est traité pour une ligne ajoutée, la valeur d'identité auto-incrémentée est retournée comme ce paramètre de sortie et placée dans la colonne CategoryID de la ligne en cours.

L'exemple de code suivant montre comment retourner la valeur auto-incrémentée en tant que paramètre de sortie et la spécifier en tant que valeur source de la colonne CategoryID dans le DataSet.

Dim nwindConn As SqlConnection = New SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

Dim catDA As SqlDataAdapter = New SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", nwindConn)

catDA.InsertCommand = New SqlCommand("InsertCategory", nwindConn)
catDA.InsertCommand.CommandType = CommandType.StoredProcedure

catDA.InsertCommand.Parameters.Add("@CategoryName", SqlDbType.NChar, 15, "CategoryName")

Dim myParm As SqlParameter = catDA.InsertCommand.Parameters.Add("@Identity", SqlDbType.Int, 0, "CategoryID")
myParm.Direction = ParameterDirection.Output

nwindConn.Open()

Dim catDS As DataSet = New DataSet
catDA.Fill(catDS, "Categories")

Dim newRow As DataRow = catDS.Tables("Categories").NewRow()
newRow("CategoryName") = "New Category"
catDS.Tables("Categories").Rows.Add(newRow)

catDA.Update(catDS, "Categories")

nwindConn.Close()
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");

SqlDataAdapter catDA = new SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", nwindConn);

catDA.InsertCommand = new SqlCommand("InsertCategory", nwindConn);
catDA.InsertCommand.CommandType = CommandType.StoredProcedure;

catDA.InsertCommand.Parameters.Add("@CategoryName", SqlDbType.NChar, 15, "CategoryName");

SqlParameter myParm = catDA.InsertCommand.Parameters.Add("@Identity", SqlDbType.Int, 0, "CategoryID");
myParm.Direction = ParameterDirection.Output;

nwindConn.Open();

DataSet catDS = new DataSet();
catDA.Fill(catDS, "Categories");

DataRow newRow = catDS.Tables["Categories"].NewRow();
newRow["CategoryName"] = "New Category";
catDS.Tables["Categories"].Rows.Add(newRow);

catDA.Update(catDS, "Categories");

nwindConn.Close();

Microsoft Access ne prend pas en charge les procédures stockées ou le traitement des commandes batch, et il n'est donc pas possible de mapper un paramètre de sortie à la colonne source de la table de l'exemple précédent. Toutefois, Microsoft Access 2000 ou version ultérieure prend en charge la propriété @@IDENTITY pour extraire la valeur d'un champ NuméroAuto après une INSERTION. En utilisant l'événement RowUpdated, vous pouvez déterminer si une INSERTION a eu lieu, extraire la dernière valeur de @@IDENTITY, et la placer dans la colonne d'identité de la table locale du DataSet.

L'exemple de code suivant montre comment insérer une nouvelle valeur dans la table Categories de la base de données Microsoft Access 2000 Northwind. Cet exemple utilise l'événement RowUpdated pour remplir les valeurs NuméroAuto générées par le moteur Jet et la base de données Access lorsqu'un enregistrement est inséré dans la table Categories. Notez que ce code ne fonctionnera qu'avec le fournisseur OLE DB Jet 4.0 et Microsoft Access 2000 ou versions ultérieures.

Imports System
Imports System.Data
Imports System.Data.OleDb
Imports Microsoft.VisualBasic

Public class Sample

  Shared nwindConn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                              "Data Source=c:\Program Files\Microsoft Office\Office\Samples\northwind.mdb;")

  Public Shared Sub Main() 

    ' Use the DataAdapter to fill and update the DataSet.
    Dim catDA As OleDbDataAdapter = New OleDbDataAdapter("SELECT CategoryID, CategoryName FROM Categories ORDER BY CategoryID", nwindConn)

    catDA.InsertCommand = New OleDbCommand("INSERT INTO Categories (CategoryName) Values(?)", nwindConn)
    catDA.InsertCommand.CommandType = CommandType.Text

    catDA.InsertCommand.Parameters.Add("@CategoryName", OleDbType.Char, 15, "CategoryName")

    nwindConn.Open()
 
    ' Fill the DataSet.
    Dim catDS As DataSet = New DataSet
    catDA.Fill(catDS, "Categories")

    ' Add a new row.
    Dim newRow As DataRow = catDS.Tables("Categories").NewRow()
    newRow("CategoryName") = "New Category"
    catDS.Tables("Categories").Rows.Add(newRow)

    ' Include an event to fill in the Autonumber value.
    AddHandler catDA.RowUpdated, New OleDbRowUpdatedEventHandler(AddressOf OnRowUpdated)

    ' Update the DataSet.
    catDA.Update(catDS, "Categories")

    nwindConn.Close()
  End Sub

  Private Shared Sub OnRowUpdated(sender As Object, args As OleDbRowUpdatedEventArgs)
    ' Include a variable and a command to retrieve the identity value from the Access database.
    Dim newID As Integer = 0
    Dim idCMD As OleDbCommand = New OleDbCommand("SELECT @@IDENTITY", nwindConn)

    If args.StatementType = StatementType.Insert
      ' Retrieve the identity value and store it in the CategoryID column.
      newID = CInt(idCMD.ExecuteScalar())
      args.Row("CategoryID") = newID
    End If
  End Sub
End Class
[C#]
using System;
using System.Data;
using System.Data.OleDb;

public class Sample
{
  static OleDbConnection nwindConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" +
                                                  @"Data Source=c:\Program Files\Microsoft Office\Office\Samples\northwind.mdb;");

  public static void Main() 
  {
    // Use the DataAdapter to fill and update the DataSet.
    OleDbDataAdapter catDA = new OleDbDataAdapter("SELECT CategoryID, CategoryName FROM Categories ORDER BY CategoryID", nwindConn);

    catDA.InsertCommand = new OleDbCommand("INSERT INTO Categories (CategoryName) Values(?)", nwindConn);
    catDA.InsertCommand.CommandType = CommandType.Text;

    catDA.InsertCommand.Parameters.Add("@CategoryName", OleDbType.Char, 15, "CategoryName");

    nwindConn.Open();
 
    // Fill the DataSet.
    DataSet catDS = new DataSet();
    catDA.Fill(catDS, "Categories");

    // Add a new row.
    DataRow newRow = catDS.Tables["Categories"].NewRow();
    newRow["CategoryName"] = "New Category";
    catDS.Tables["Categories"].Rows.Add(newRow);

    // Include an event to fill in the Autonumber value.
    catDA.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated);

    // Update the DataSet.
    catDA.Update(catDS, "Categories");

    nwindConn.Close();
  }

  protected static void OnRowUpdated(object sender, OleDbRowUpdatedEventArgs args)
  {
    // Include a variable and a command to retrieve the identity value from the Access database.
    int newID = 0;
    OleDbCommand idCMD = new OleDbCommand("SELECT @@IDENTITY", nwindConn);

    if (args.StatementType == StatementType.Insert)
    {
      // Retrieve the identity value and store it in the CategoryID column.
      newID = (int)idCMD.ExecuteScalar();
      args.Row["CategoryID"] = newID;
    }
  }
}

Voir aussi

Exemples de scénarios ADO.NET | Accès aux données avec ADO.NET | Utilisation des fournisseurs de données .NET Framework pour l'accès aux données