Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Es posible establecer una columna de un DataTable para que sea una clave principal de incremento automático con el fin de garantizar que haya un valor único para cada fila de la tabla. Sin embargo, es posible tener varios clientes de la aplicación y cada uno de esos clientes puede trabajar con una instancia diferente de la tabla DataTable. En este caso, podría haber valores duplicados en las distintas instancias de la DataTable. Como todos los clientes trabajan con un único origen de datos, es posible resolver este conflicto si se permite que el origen de datos defina el valor de incremento automático. Para ello se utilizan campos Identidad en Microsoft SQL Server o Autonumérico en Microsoft Access.
El uso del origen de datos con el fin de llenar una columna Identidad o Autonumérica para una nueva fila agregada a un DataSet crea una situación diferente, ya que el DataSet no tiene conexión directa con el origen de datos. Por tanto, el DataSet no conoce los valores generados automáticamente por el origen de datos. Sin embargo, con un origen de datos que pueda crear procedimientos almacenados con parámetros de salida, como Microsoft SQL Server, se pueden especificar los valores generados automáticamente, como un nuevo valor de identidad, como parámetro de salida, y utilizar DataAdapter para volver a asignar el valor a la columna del DataSet.
Puede que el origen de datos pertinente no admita procedimientos almacenados con parámetros de salida. En este caso es posible utilizar el evento RowUpdated para recuperar un valor generado automáticamente y ponerlo en la fila insertada o actualizada del DataSet. Esta sección incluye un ejemplo que muestra cómo se puede utilizar Microsoft Access 2000 o posterior y el proveedor de datos OLE DB de Jet 4.0 con el fin de agregar código al evento RowUpdated para determinar si se ha producido una inserción, y recuperar el valor de incremento automático y almacenarlo en la fila actualizada en estos momentos.
El procedimiento almacenado y el ejemplo de código siguientes muestran cómo asignar el valor de identidad de incremento automático desde una tabla de Microsoft SQL Server a su columna correspondiente en una fila agregada a una tabla de un DataSet. El procedimiento almacenado se utiliza para insertar una nueva fila en la tabla Categories de la base de datos Northwind y para devolver el valor de identidad devuelto por SCOPE_IDENTITY() como un parámetro de salida.
CREATE PROCEDURE InsertCategory
@CategoryName nchar(15),
@Identity int OUT
AS
INSERT INTO Categories (CategoryName) VALUES(@CategoryName)
SET @Identity = SCOPE_IDENTITY()
El procedimiento almacenado InsertCategory puede especificarse entonces como origen de DataAdapter.InsertCommand. Se crea un parámetro para recibir el parámetro de salida de identidad. Ese parámetro tiene un valor ParameterDirection.Output para Direction y en SourceColumn se especifica la columna CategoryID de la tabla local Categories del DataSet. Cuando se procesa InsertCommand para una fila agregada, se devuelve el valor de identidad de incremento automático como este parámetro de salida y se coloca en la columna CategoryID de la fila actual.
En el siguiente ejemplo de código se muestra cómo devolver el valor de incremento automático como el parámetro de salida y cómo especificarlo como el valor de origen para la columna CategoryID del 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 no admite procedimientos almacenados ni el procesamiento de comandos por lotes, por lo que no es posible asignar un parámetro de salida a la columna de origen de la tabla en el ejemplo anterior. Sin embargo, Microsoft Access 2000 o posterior admite la propiedad @@IDENTITY para recuperar el valor de un campo Autonumérico después de una inserción (con INSERT). Mediante el evento RowUpdated es posible determinar si se ha producido una inserción, recuperar el último valor de @@IDENTITY y ponerlo en la columna de identidad de la tabla local del DataSet.
En el siguiente ejemplo de código se muestra cómo insertar un nuevo valor en la tabla Categories de la base de datos Northwind de Microsoft Access 2000. En el ejemplo se utiliza el evento RowUpdated para rellenar los valores Autonuméricos generados por el motor Jet y la base de datos de Access al insertar un registro en la tabla Categories. Hay que tener en cuenta que esto sólo funcionará con el proveedor OLE DB de Jet 4.0 y Microsoft Access 2000 o posterior.
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;
}
}
}
Vea también
Ejemplo de escenarios de ADO.NET | Acceso a datos con ADO.NET | Utilizar proveedores de datos de .NET Framework para obtener acceso a datos