现在的位置: 首页 > 综合 > 正文

如何在ado.net程序中检索“标识”或“自动编号”值.

2013年02月26日 ⁄ 综合 ⁄ 共 6488字 ⁄ 字号 评论关闭

为了确保表中的每一行都有唯一的值,可以将 DataTable 中的列设置为自动递增的主键。但是,您的应用程序可能会有多个客户端,而每个客户端都可能会使用一个单独的 DataTable 实例。在这种情况下,单独的 DataTable 实例之间最终可能会出现重复的值。由于所有客户端都使用单个数据源,因此可以让数据源定义自动递增值,从而解决这一冲突。若要完成此任务,请使用 Microsoft SQL Server 中的“标识”字段或 Microsoft Access 中的“自动编号”字段。
如果使用数据源为添加到 DataSet 中的新行填充“标识”或“自动编号”列,则会出现唯一的情况,因为 DataSet 与数据源之间没有直接连接。因此,DataSet 不识别任何由数据源自动生成的值。但是,对于可以创建带有输出参数的存储过程的数据源(如 Microsoft SQL Server),可以将自动生成的值(如新的标识值)指定为输出参数并使用 DataAdapter 将该值映射回 DataSet 中的相应列。
数据源可能不支持带有输出参数的存储过程。在这种情况下,将可以使用 RowUpdated 事件来检索自动生成的值,并将其放入 DataSet 中的插入行或更新行。本节包含一个示例,它显示当在 Microsoft Access 2000 或更高版本上使用 Jet 4.0 OLE DB 提供程序时,如何将代码添加到 RowUpdated 事件中以确定插入是否已发生,然后检索自动生成的值并将其存储在当前更新的行中。
以下存储过程和代码示例显示如何将自动递增的标识值从 Microsoft SQL Server 表映射回它在向 DataSet 的表添加的行中的相应列。该存储过程用于将一个新行插入 Northwind 数据库的 Categories 表并以输出参数的形式返回从 SCOPE_IDENTITY() 中返回的标识值。
CREATE PROCEDURE InsertCategory
  @CategoryName nchar(15),
  @Identity int OUT
AS
INSERT INTO Categories (CategoryName) VALUES(@CategoryName)
SET @Identity = SCOPE_IDENTITY()
然后,可以将 InsertCategory 存储过程指定为 DataAdapter.InsertCommand 的源。为了接收标识输出参数,将创建一个参数。该参数具有 ParameterDirection.Output 的 Direction,并将 SourceColumn 指定为 DataSet 中本地 Categories 表的 CategoryID 列。为添加的行处理 InsertCommand 后,将自动增加的标识值作为此输出参数返回,然后放在当前行的 CategoryID 列中。
以下代码示例显示如何以输出参数的形式返回自动递增的值并将其指定为 DataSet 中 CategoryID 列的源值。
[Visual Basic]
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 不支持存储过程或批命令处理,因此无法将输出参数映射到上例所示表中的源列。但是,Microsoft Access 2000 或更高版本支持 @@IDENTITY 属性在“插入”(INSERT) 后检索“自动编号”字段的值。使用 RowUpdated 事件,您可以确定“插入”(INSERT) 是否已发生,检索最新的 @@IDENTITY 值,然后将该值放入 DataSet 中本地表的标识列。
以下代码示例显示如何将一个新值插入 Microsoft Access 2000 Northwind 数据库的 Categories 表中。该示例使用 RowUpdated 事件来填充在向 Categories 表中插入记录时 Jet 引擎和 Access 数据库所生成的“自动编号”值。请注意,这仅适用于 Jet 4.0 OLE DB 提供程序和 Microsoft Access 2000 或更高版本。
[Visual Basic]
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;
    }
  }
}

抱歉!评论已关闭.