Freigeben über


Abrufen von Identitäts- oder AutoWert-Werten

Sie können eine Spalte in einer DataTable als Primärschlüssel festlegen, der automatisch erhöht wird, so dass für jede Zeile der Tabelle ein eindeutiger Wert verwendet wird. Wahrscheinlich haben Sie jedoch mehrere Clients für Ihre Anwendung, und jeder dieser Clients arbeitet möglicherweise mit einer separaten Instanz von DataTable. In diesem Fall könnte es zwischen den separaten Instanzen von DataTable doppelte Werte geben. Da alle Clients mit einer einzigen Datenquelle arbeiten, können Sie diesen Konflikt dadurch lösen, dass die Datenquelle den automatisch erhöhten Wert selbst definiert. Verwenden Sie dazu Sie Identität-Felder in Microsoft SQL Server oder die AutoWert-Felder in Microsoft Access.

Wenn Sie die Datenquelle zum Füllen eines Identität- oder AutoWert-Feldes für eine neue Zeile verwenden, die zu einem DataSet hinzugefügt wurde, entsteht eine außergewöhnliche Situation, weil das DataSet keine direkte Verbindung zur Datenquelle besitzt. Folglich weiß das DataSet nichts von Werten, die automatisch von der Datenquelle generiert wurden. Mit einer Datenquelle, die gespeicherte Prozeduren mit Ausgabeparametern erstellen kann, wie z. B. Microsoft SQL Server, können Sie die automatisch generierten Werte (z. B. einen neuen Identitätswert) allerdings als Ausgabeparameter angeben und den Wert mit dem DataAdapter wieder der Spalte im DataSet zuordnen.

Ihre Datenquelle unterstützt möglicherweise keine gespeicherten Prozeduren mit Ausgabeparametern. In diesem Fall können Sie wahrscheinlich einen automatisch generierten Wert mit dem RowUpdated-Ereignis abrufen und in die eingefügte oder aktualisierte Zeile des DataSets stellen. Das Beispiel in diesem Abschnitt zeigt, wie Sie mit Microsoft Access 2000 oder höher und dem Jet 4.0 OLE DB Provider Code zum RowUpdated-Ereignis hinzufügen und damit feststellen können, ob eine Einfügung vorgenommen wurde. Außerdem können Sie den automatisch erhöhten Wert abrufen und in der gerade aktualisierten Zeile speichern.

Die folgende gespeicherte Prozedur und das Codebeispiel zeigen, wie der automatisch erhöhte Identitätswert aus einer Microsoft SQL Server-Tabelle der entsprechenden Spalte in einer Zeile, die zu einer Tabelle in einem DataSet hinzugefügt wurde, zugeordnet wird. Die gespeicherte Prozedur wird verwendet, um eine neue Zeile in die Categories-Tabelle der Northwind-Datenbank einzufügen und den Identitätswert zurückzugeben, der von SCOPE_IDENTITY() als Ausgabeparameter zurückgegeben wurde.

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

Die gespeicherte Prozedur InsertCategory kann anschließend als Quelle von DataAdapter.InsertCommand angegeben werden. Ein Parameter wird erstellt, der den Ausgabeparameter für die Identität empfangen soll. Dieser Parameter besitzt ParameterDirection.Output als Direction und verfügt über eine SourceColumn, die als CategoryID-Spalte der lokalen Categories-Tabelle im DataSet angegeben ist. Bei der Verarbeitung von InsertCommand für eine hinzugefügte Zeile wird der automatisch erhöhte Identitätswert als Ausgabeparameter zurückgegeben und in der CategoryID-Spalte der aktuellen Zeile platziert.

Das folgenden Codebeispiel zeigt, wie der automatisch erhöhte Wert als Ausgabeparameter zurückgegeben und als Quellwert für die CategoryID-Spalte im DataSet angegeben wird.

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 unterstützt keine gespeicherten Prozeduren oder Stapelbefehlsverarbeitung, so dass es nicht möglich ist, der Quellspalte in der Tabelle des vorhergehenden Beispiels einen Ausgabeparameter zuzuordnen. Allerdings unterstützt Microsoft Access 2000 oder höher die @@IDENTITY-Eigenschaft, um den Wert eines AutoWert-Feldes nach einem INSERT abzurufen. Mit dem RowUpdated-Ereignis können Sie feststellen, ob eine INSERT-Operation durchgeführt wurde. Außerdem können Sie den neuesten @@IDENTITY-Wert abrufen und ihn in die Identitätsspalte der lokalen Tabelle im DataSet stellen.

Das folgende Codebeispiel zeigt, wie ein neuer Wert in die Categories-Tabelle der Northwind-Datenbank von Microsoft Access 2000 eingefügt wird. Das Beispiel verwendet das RowUpdated-Ereignis, um die Werte für AutoWert einzutragen, die vom Jet-Modul und der Access-Datenbank generiert werden, wenn ein Datensatz in die Categories-Tabelle eingefügt wird. Beachten Sie, dass dies nur mit Jet 4.0 OLE DB Provider und Microsoft Access 2000 oder höher möglich ist.

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

Siehe auch

Beispielszenarien zu ADO.NET | Zugreifen auf Daten mit ADO.NET | Datenzugriff mit .NET Framework-Datenprovidern