jueves, 21 de enero de 2010

C# - [ADO.NET] – Parte 6 - Campos Auto numéricos (Identity)

 

Introducción


Se basara la explicación de este articulo de uno anterior en donde se aprendió de una forma simple y por medio de un ejemplo completo a trabajar los datos con ado.net

[ADO.NET] – Parte 5 - Ejemplos Simples – Operaciones CRUD

Por lo cual tomando ese ejemplo de base se pasara a explicar como trabajar con campos del tipo Autonuméricos o Identity.

Como es sabido en estos tipos de campos es la base de datos la que genera el Id del registro que se inserta, por lo tanto las modificaciones solo afectaran a las operaciones INSERT de la aplicación de ejemplo.

En la base de datos se ha realizado el siguiente cambio en la tabla:

 

 

1- Obtener Identity en la misma consulta


En este ejemplo se hará uso de una consulta combinada en donde en la misma ejecución se insertara el registro y a la vez se recuperara el identificador autonumérico generado.

[C#]

private void btnGuardar_Click(object sender, EventArgs e)
{
    //
    // Validaciones
    //
    int Id = 0;
    if (!string.IsNullOrEmpty(txtId.Text))
    {
        if (!int.TryParse(txtId.Text, out Id))
        {
            MessageBox.Show("El Id debe ser un valor numerico");
            return;
        }
    }

    if (Exists(Id))
    {
        bool result = Update(Id, txtNombre.Text, txtDireccion.Text, dtpFechaNanimiento.Value);

        if (result)
            MessageBox.Show("El registro se ha actualizado correctamente.");
    }
    else
    {
        int id = Insert(txtNombre.Text, txtDireccion.Text, dtpFechaNanimiento.Value);

        if (id > 0)
        {
            MessageBox.Show(string.Format("El registro se ha insertado correctamente. Id : {0}", id));
            txtId.Text = Convert.ToString(id);
        }
    }
}

private int Insert(string nombre, string direccion, DateTime fechaNacimiento)
{
    if (!ValidateForm())
        return 0;

    string sql = @"INSERT INTO Contactos (NombreCompleto
                          ,Direccion
                          ,FechaNacimiento)
                      VALUES (@Nombre, 
                            @Direccion, 
                            @FechaNacimiento)
                    SELECT SCOPE_IDENTITY()";


    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {

        SqlCommand command = new SqlCommand(sql, conn);
        command.Parameters.AddWithValue("Nombre", nombre);
        command.Parameters.AddWithValue("Direccion", direccion);
        command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento);

        conn.Open();

        return Convert.ToInt32(command.ExecuteScalar());

    }
}

[VB.NET]

Private Sub btnGuardar_Click(sender As Object, e As EventArgs)
	'
	' Validaciones
	'
       Dim _Id As Integer = 0
	If Not String.IsNullOrEmpty(txtId.Text) Then
           If Not Integer.TryParse(txtId.Text, _Id) Then
               MessageBox.Show("El Id debe ser un valor numerico")
               Return
           End If
	End If

       If Exists(_Id) Then
           Dim result As Boolean = Update(_Id, txtNombre.Text, txtDireccion.Text, dtpFechaNanimiento.Value)

           If result Then
               MessageBox.Show("El registro se ha actualizado correctamente.")
           End If
       Else
           Dim idObtenido As Integer = Insert(txtNombre.Text, txtDireccion.Text, dtpFechaNanimiento.Value)

           If idObtenido > 0 Then
               MessageBox.Show(String.Format("El registro se ha insertado correctamente. Id : {0}", idObtenido))
               txtId.Text = Convert.ToString(idObtenido)
           End If
       End If
End Sub

Private Function Insert(nombre As String, direccion As String, fechaNacimiento As DateTime) As Integer
	If Not ValidateForm() Then
		Return 0
	End If

       Dim sql As String = "INSERT INTO Contactos (NombreCompleto" & _
                               ",Direccion" & _
                               ",FechaNacimiento)" & _
                               "VALUES (@Nombre, " & _
                               "@Direccion, " & _
                               "@FechaNacimiento)" & _
                           "SELECT SCOPE_IDENTITY()"


	Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString())

		Dim command As New SqlCommand(sql, conn)
		command.Parameters.AddWithValue("Nombre", nombre)
		command.Parameters.AddWithValue("Direccion", direccion)
		command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento)

		conn.Open()


		Return Convert.ToInt32(command.ExecuteScalar())
	End Using
End Function	

Como se observa en el código el principal cambio se lo lleva al consulta SQL, en donde se combinan dos consultas en una.

Por medio de método ExecuteScalar() del SqlCommand se realizaran las dos operaciones, ejecutar la consulta de INSERT y al mismo tiempo devolver el valor único del SELECT.

Por ultimo se lo pasa el id obtenido al evento en al presentación para que muestre el id generado en pantalla.

 

2 – Obtener Id en consultas separadas


Un problema con la técnica anterior es que si por alguna razón el INSERT no realiza la operación de forma correcta, puede haber problemas con el id que se obtiene.

Esto puede ser extraño pero hay formas de asegurar que solo se obtenga con el id si es que la operación anterior se ha realizado de forma correcta.

Mas que nada esta técnica es útil cuando se quiere asegurar o validar que el INSERT afecto a los registros de forma adecuada.

[C#]

private int InsertComandosSeparadas(string nombre, string direccion, DateTime fechaNacimiento)
{
    if (!ValidateForm())
        return 0;

    string sql = @"INSERT INTO Contactos (NombreCompleto
                          ,Direccion
                          ,FechaNacimiento)
                      VALUES (@Nombre, 
                            @Direccion, 
                            @FechaNacimiento)";

    
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {

        SqlCommand command = new SqlCommand(sql, conn);
        command.Parameters.AddWithValue("Nombre", nombre);
        command.Parameters.AddWithValue("Direccion", direccion);
        command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento);

        conn.Open();


        int rowsAffected = command.ExecuteNonQuery();

        if (rowsAffected > 0)
        {
            string sqlIdentity = "SELECT @@IDENTITY";
            SqlCommand cmdIdentity = new SqlCommand(sqlIdentity, conn);

            return Convert.ToInt32(cmdIdentity.ExecuteScalar());
        }
        else
            return -1;


    }
}

[VB.NET]

Private Function InsertComandosSeparadas(nombre As String, direccion As String, fechaNacimiento As DateTime) As Integer
	If Not ValidateForm() Then
		Return 0
	End If

       Dim sql As String = "INSERT INTO Contactos (NombreCompleto" & _
                                   ",Direccion" & _
                                   ",FechaNacimiento)" & _
                               "VALUES (@Nombre, " & _
                                   "@Direccion, " & _
                                   "@FechaNacimiento)"


	Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString())

		Dim command As New SqlCommand(sql, conn)
		command.Parameters.AddWithValue("Nombre", nombre)
		command.Parameters.AddWithValue("Direccion", direccion)
		command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento)

		conn.Open()


		Dim rowsAffected As Integer = command.ExecuteNonQuery()

		If rowsAffected > 0 Then
			Dim sqlIdentity As String = "SELECT @@IDENTITY"
			Dim cmdIdentity As New SqlCommand(sqlIdentity, conn)

			Return Convert.ToInt32(cmdIdentity.ExecuteScalar())
		Else
			Return -1


		End If
	End Using
End Function

 

En le código puede observarse que la primer parte se conserva idéntica a la origina, en donde solo una instrucción de INSERT es declarada, y ejecutada por medio del ExecuteNonQuery(), este retornara los registros afectados y según el valor de retorno se procederá a recuperar el id autonumérico generado.

Hay un cambio que hay que hacer notar y es que en el SELECT se ha cambiado la técnica usada para recuperar el id, en este caso se hace uso del @@IDENTITY

Seguramente la pregunta que se harán es porque de este cambio, bien resulta que la diferencia entre estas instrucciones esta en el ámbito en que se ejecutan, SCOPE_IDENTITY trabaja en el ámbito actual, o sea el ámbito de la instrucción, si en este ejemplo usáramos esta instrucción obtendríamos como resultado un NULL, pues este debe ser ejecutado en la misma operación.

En cambio @@IDENTY no es afectado por aun ámbito especifico, puede ser consultado luego de haber realizado la operación de INSERT en una operación distinta. Algo que haya que marcar es que @@IDENTITY puede tener problemas ya que al no trabajar en un ámbito determinado puede ser afectada por otras operaciones, si es que se realizan acciones con varias tablas.

@@IDENTITY

SCOPE_IDENTITY

 

3 – Obtener Id desde Stored Procedure


En este caso se analizara como obtener el id generado por la tabla, en donde la operacion de actualización esta dentro de un Stored Procedure, para esto se requerirán algunos cambios.

 

[C#]

private int InsertStoredprocedure(string nombre, string direccion, DateTime fechaNacimiento)
{
    if (!ValidateForm())
        return 0;

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
        conn.Open();

        SqlCommand command = new SqlCommand("sp_ContactoInsert", conn);
        command.CommandType = CommandType.StoredProcedure;

        SqlParameter paramId = new SqlParameter("Id", SqlDbType.Int);
        paramId.Direction = ParameterDirection.Output;
        command.Parameters.Add(paramId);

        command.Parameters.AddWithValue("Nombre", nombre);
        command.Parameters.AddWithValue("Direccion", direccion);
        command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento);

        int rowsAffected = command.ExecuteNonQuery();

        if (rowsAffected > 0)
        {
            return Convert.ToInt32(command.Parameters["Id"].Value);
        }
        else
            return -1;


    }
}

[VB.NET]

Private Function InsertStoredProcedure(nombre As String, direccion As String, fechaNacimiento As DateTime) As Integer
	If Not ValidateForm() Then
		Return 0
	End If

	Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString())
		conn.Open()

		Dim command As New SqlCommand("sp_ContactoInsert", conn)
		command.CommandType = CommandType.StoredProcedure

		Dim paramId As New SqlParameter("Id", SqlDbType.Int)
		paramId.Direction = ParameterDirection.Output
		command.Parameters.Add(paramId)

		command.Parameters.AddWithValue("Nombre", nombre)
		command.Parameters.AddWithValue("Direccion", direccion)
		command.Parameters.AddWithValue("FechaNacimiento", fechaNacimiento)

		Dim rowsAffected As Integer = command.ExecuteNonQuery()

		If rowsAffected > 0 Then
			Return Convert.ToInt32(command.Parameters("Id").Value)
		Else
			Return -1
           End If

       End Using

End Function

[Stored Procedure]

ALTER PROCEDURE dbo.sp_ContactoInsert
	
	@Id int OUTPUT,
	@Nombre varchar(50),
	@Direccion varchar(50),
	@FechaNacimiento DateTime
	
AS
	INSERT INTO Contactos (NombreCompleto
                                  ,Direccion
                                  ,FechaNacimiento)
                              VALUES (@Nombre, 
                                    @Direccion, 
                                    @FechaNacimiento);

                                                                        
    SELECT @Id = SCOPE_IDENTITY()     
                             
	RETURN

 

En el código se han quitados todas las consulta reemplazándolo por el nombre del stored procedure.

En este caso se hace uso de un parámetro que actuara como output para el valor generado dentro del Stored procedure, el cual será recuperado luego de la ejecución de la instrucción.

[C#]
[VB.NET]

28 comentarios:

  1. MUCHAS GRACIAS, ENCONTRE LA SOLUCION A UNO DE MIS PROBLEMAS JEJEJE...

    UN ABRAZO FUERTE

    ResponderEliminar
  2. y como seria para cSharp y oracle para insertar un registro con txtbox botton y un gridview....

    ResponderEliminar
  3. hola

    bueno en Oracle un identity es diferente porque basicamente no existe el mismo concepto

    lo que usas en Oracle es un Sequences


    saludos

    ResponderEliminar
  4. Buenas Don Leandro tengo uan pregunta viendo este código tengo un problema en mi Uni estoy haciendo un programa referente a un banco y tengo 2 tablas una
    una Usuarios y una Cliente cuando se ingresa a el sistema se usa un usuario y una contraseña y a la hora de insertar en clientes se necesita guardar el id_usuario que ingreso a el sistema en clientes el id_usuarios es una Foreing Key como podria guardar ese dato para llevarlo a una insercion si que me de una exepción

    ResponderEliminar
  5. hola R.Boniche

    no se como es la estructura de la tabla cliente, pero me parece raro que si alguien se auntentica con usuario y pasword tengas que insertar en la tabla, porque se supone que el cliente ya existe

    no sera que tienes que actualizar algun dato del clinete?

    o sea no user un INSERT sino un UPDATE

    ademas la tabla cliente solo tiene el id_cliente, no tiene ningun otro campo?

    saludos

    ResponderEliminar
  6. Hola leandro veo que tienes un bloque de codigo Validaciones pero solo lo llamas en los procedimientos de insert, InsertComandosSeparadas, InsertStoredProcedure.

    no seria mas facil colocarlos en btnEliminar_Click, btnGuardar_Click, de hecho lo tienes comentariado.

    Lo tomo como tema porque necesito algo de codigo para validar mis formularios y me parecio interesante usar tu codigo de este ejemplo

    ResponderEliminar
  7. hola epsilon coder

    recuerda que los 3 metodos que mencionaste son lo mismo solo que con diferentes implementaciones

    o sea no es que en tu codigo vas a tener insert, InsertComandosSeparadas, InsertStoredProcedure.
    porque esto no es correcto, solo tendrias un unico insert con una de estas tres implementaciones de ejemplo

    las validaciones seguramente apliquen de forma distinta a cada funcionalidad, en un delete no validas lo mismo que en un insert o update, porque las operaciones difieren

    ademas recuerda que hay validaciones de interfaz de usuario y validaciones de negocio, por ejemplo de UI podria ser validar que una fecha tenga el formato correcto, que un campo de dni este completo y sea numerico

    pero despues estan las valicaciones de negocio, en estas aplicas logica y debes quizas debas consultar a la db para poder verificarlas

    saludos

    ResponderEliminar
  8. Leandro:
    ¿Y que sucede si la variable OutPut no es INTEGER y es VARCHAR?
    ¿Es imposible capturarlo en VB?
    Si de todas maneras el Id (la variable OUTPUT) debiera ser alfanumerico ¿que se puede hacer?

    ResponderEliminar
  9. hola Carlos

    me temo que no puede hacer un autonumerico de un varchar, tiene que ser especificamente numerico el tipo de datos para poder hacerlo incremental

    si debe ser alfanumerico quizas dividiria el campo en dos, uan para la parte en letras y oro para la numerica
    aunqie lo ideal seria que crees un campo id secuencial nuemrico y dejes este como un codigo alternativo que tu crees pero que no sea la key de la tabla (si podrias definir este campo como UNIQUE para que no se pueda duplicar)

    saludos

    ResponderEliminar
  10. Buenos días Leandro.



    Soy nuevo en esto y quería hacerte una pregunta ¿Por qué no veo el código xaml debajo cuando abro Contactos.cs? Me aparece un icono sobre fondo gris que pone “errProvider” Solo me pasa en esta aplicación, en cualquier otra me aparece el código perfectamente. Te agradezco mucho la generosidad que demuestras con este blog. Muchas Gracias. Saludos.

    ResponderEliminar
  11. hola Adolfo

    por lo que comentas estas desarrollando con WPF, no ?

    lo que no creo es que debajo de un .cs exista un xaml, si tendrias un Window1.xaml este si tienes un .cs asociado que seria el code behind donde pones los eventos

    pero de un .cs que se desplegue un xaml, me parece raro


    saludos

    ResponderEliminar
  12. Hola Leandro.
    Es la aplicación que tu colgaste en este articulo "C# - [ADO.NET] – Parte 6 - Ejemplos simples – Campos Auto numéricos (Identity)" que se llama “[csharp] WinAdoNET”.

    Tienes razon, es un .cs pero tiene un formulario ventana. Por lo que veo en este caso debajo del Contactos.cs esta el Contactos.Designer.cs donde esta definida la ventana y sus botones en lugar de cómo esta normalmente que seria Contactos.xaml.cs. El problema es mío que no había visto nunca ninguna ventana en WPF que no tuviera su código xaml definiendo los campos y las dimensiones. ¿Hay alguna razon por la que este asi hecha?
    Gracias.

    ResponderEliminar
  13. hola Adolfo

    en wpf puede haber archivo xaml sin ningun .cs asociado, por lo general se usan para definir Resources, en estos puede definir estilos, template, etc

    como no son en realidad ninguna ventana o sea no hereda el contenido de Window o Page entonces no tienen ningun cs asociado donde definir evento o el constructor

    de casualida ese xaml comienza con el tag ResourceDictionary, proque estos xaml no tiene ningun cs asociado

    saludos

    ResponderEliminar
  14. Hola Leandro, un saludo muy afectuoso, tu blog de mucha utilidad y de los pocos que tienen claridad y contenido interesante a nivel de programación. Te molesto con una duda, estoy trabajando con C# y un archivo mdf, el problema es que al hacer un insert y querer recuperar el último campo identity me devuelve null con las diferentes opciones (SELECT @@IDENTITY y SELECT SCOPE_IDENTITY()), con la consulta SELECT IDENT_CURRENT(‘tablename’) me devuelva un número erróneo (p.e. el último valor del campo es 5 y la consulta me devuelve un 8), quisiera saber si estoy haciendo algo mal o recibir una orientación de tu parte, te dejo el inicio del método que uso para la consulta, mcuhas gracias:

    string consulta = "INSERT INTO Facturas (folio, fecha, fk_LoteFolio, fk_Cliente) VALUES " +
    "(@folio, @fecha, @fk_LoteFolio, @fk_Cliente)";

    int idFac = 0;
    SqlCommand cmd = new SqlCommand();

    cmd.CommandType = CommandType.Text;
    cmd.Connection = Con;
    cmd.CommandText = consulta;
    cmd.Parameters.Add("@folio", SqlDbType.Int);
    cmd.Parameters.Add("@fecha", SqlDbType.SmallDateTime);
    cmd.Parameters.Add("@fk_LoteFolio", SqlDbType.Int);
    cmd.Parameters.Add("fk_Cliente", SqlDbType.Int);
    cmd.Parameters[0].Value = fac.Folio;
    cmd.Parameters[1].Value = fac.Fecha;
    cmd.Parameters[2].Value = fac.FK_LoteFolio;
    cmd.Parameters[3].Value = fkCli;

    try
    {
    Abrir();
    cmd.ExecuteNonQuery();
    consulta = "SELECT @@IDENTITY";
    //Aquí me regresa null o un num. erróneo y ya no puedo continuar
    idFac = Convert.ToInt32(cmd.ExecuteScalar());

    consulta = "INSERT INTO Detalle (nombre, cantidad, unidad, precio, fk_Facturas) VALUES " +
    "(@nombre, @cantidad, @unidad, @precio, @fk_Facturas)";
    cmd.CommandText = consulta;

    for (int i = 0; i < fac.Productos.Length; i++)
    {
    cmd.Parameters.Clear();
    cmd.Parameters.Add("@nombre", SqlDbType.VarChar, 100).Value = fac.Productos[i].NombreProd;
    cmd.Parameters.Add("@cantidad", SqlDbType.Int).Value = fac.Productos[i].Cantidad;
    cmd.Parameters.Add("@unidad", SqlDbType.VarChar, 20).Value = fac.Productos[i].Unidad;
    cmd.Parameters.Add("@precio", SqlDbType.Decimal).Value = fac.Productos[i].Precio;
    cmd.Parameters.Add("@fk_Facturas", SqlDbType.Int).Value = idFac;
    cmd.ExecuteNonQuery();
    }

    ResponderEliminar
  15. hola Emexto

    lo que veo es que defines la variable consulta con el @@IDENTITY pero nucna asignas al SqlCommand, por lo que el cmd.ExecuteScalar() vuelve a ejecutar el insert

    creo que deberias usar el SCOPE_IDENTITY, como explico aqui

    [ADO.NET] – Parte 6 - Ejemplos simples – Campos Auto numéricos (Identity)

    saludos

    ResponderEliminar
  16. Tienes toda la razón Leandro, tan simple como eso, muchas gracias, nuevamente felicidades por tu labor.

    ResponderEliminar
  17. buenos dias leandro disculpa podrias volver a subir proyectos de C# asi como de vb.net porque al descargar me sale no estan disponibles o han sido eliminados. tanto de este tema como los anteriores de este mes.

    ResponderEliminar
  18. hola r3nzo1986

    no habia visto que esto, gracias por avisar

    hoy mismo cuando llego a casa actualizo los link del codigo

    saludos

    ResponderEliminar
  19. hola Leandro...

    Es posible tener como identificador un codigo tipo alfa-numerico ?: Area - (numero de mes)-(numero de incidente de area incremental por mes)
    Ejemplo:
    PC-05-01

    ResponderEliminar
  20. hola emilio

    si quieres que sea autonumerico me temo que no

    solo puede ser numerico

    ademas por las 3 formas normales de normalizacion de base de datos este tipo de campo nunca deberias crearlo de esa forma, no es correcto

    saludos

    ResponderEliminar
  21. Querido amigo, muy útil la información que nos compartes, soy nuevo en c#, en el desarrollo de un proyecto que llevo en marcha quiero llenar en una lista una imagen que esta en sql server, cualquier información al respecto quedo agradecido.

    Saludos;

    ResponderEliminar
  22. hola Alejandro

    deberias analizar el articulo

    [WinForms] Edición Empleados

    alli trabajo con imagenes que esta en una tabla de sql server

    saludos

    ResponderEliminar
  23. Hola Leandro,

    Primero Felicidades por tu labor, mi consulta es si se puede recuperar de la misma forma que se recupera un autonumerico, un identificador generado por un trigger. Este identificador es un numero incremental que se genera en funcion de otro campo por ejemplo la id de una sucursal, en este caso cada sucursal tendria su propio correlativo como en este pequeño ejemplo:
    id_sucursal | id_fac
    1 | 1
    1 | 2
    2 | 1
    2 | 2
    1 | 3
    2 | 3

    esta numeración se genera con un trigger (no conozco otra manera) y quisiera recuperar esta numeración en la misma consulta de inserción, es esto posible??, utilizo sql server 2005 y visual basic 2008.

    Gracias.

    ResponderEliminar
    Respuestas
    1. ¿como haces para tener el contador secuencial dependiendo del id principal?

      Eliminar
  24. hola yeso

    la verdad no se porque generas un secuencial usando un trigger, no le veno ningun sentido

    el trigger asociado a la tabla se ejecuta de forma independiente a la operacion que realices, solo podrias recuperarlo si despues de toda a operacion realizas un SELECT a la tabla y puedes determinar cual es el valor generado por el trigger

    pero la verdad me parece algo raro como esta resuelto el problema

    saludos

    ResponderEliminar
  25. buenas noches, si tengo dos tablas relacionadas y necesito ingresar en una sola transaccion los datos a las dos tablas como puedo hacerlo, tabla1 {idcliente,nombre} tabla2{idcliente,fecha}, es decir el la tabla1 el idcliente es identyty pero en la tabla2 no. espero me entienda, gracias

    ResponderEliminar
    Respuestas
    1. hola
      En una sola operacion no vas a poder realizarlo, necesitas dos command para realizar un insert en cada tabla
      podrias en la primer insertar y recuperar el id generado, para luego usarlo en el insert de la segunda tabla
      Podrias usar el TransactionScope para mantener la transaccion en las dos operaciones
      saludos

      Eliminar
  26. Hola Leandro, aquí mis dudas, espero puedas ayudarme.

    Estoy desarrollando un formulario para pagos de cuotas de clientes, estos pagos estan basados en un convenio previo con el cliente.
    es decir, el cliente se compromente a pagar los servicios o productos en cuotas.

    Tengo tres tablas:

    1. Convenio

    IdConvenio Cliente FechaConvenio IdCliente (el IdConvenio es campo Identity)
    1 Juan 25/09/2016 1

    2. ConvenioDetalle

    IdConvenioDetalle Concepto IdConvenio TotalAcuerdo Cuotas ValorCuota (el IdConvenioDetalle es campo Identity)
    1 Materiales 1 100 2 50
    2 Seguridad 1 300 3 100

    3. ConvenioPagos

    IdConvenioPago IdConvenioDetalle NroCuota ValorCuota (IdConvenioPago es campo Identity)
    1 1 1 50
    2 1 2 50
    3 2 1 100
    4 2 2 100
    5 2 3 100

    El IdConvenio que es identity de la tabla Convenio lo guardo bien en la tabla ConvenioDetalle en su campo IdConvenio.
    Lo que deseo es que al pulsar el boton Guardar, se guarden los valores identity del campo IdConvenioDetalle de la tabla ConvenioDetalle
    en el campo IdConvenioDetalle de la tabla ConvenioPagos pero teniendo en cuenta que los valores identity dependen de las cuotas que el
    cliente se comprometa a pagar.


    probe con SELECT @@IDENTITY pero me guarda siempre el ultimo Identity y asi no quiero.
    Yo quiero que los IdConvenioDetalle de la tabla ConvenioDetalle se guarde en la tabla ConvenioPagos a la vez, tal como lo muestro en el punto nro. 3:

    IdConvenioPago IdConvenioDetalle NroCuota ValorCuota (IdConvenioPago es campo Identity)
    1 2 1 50
    2 2 2 50
    3 2 1 100
    4 2 2 100
    5 2 3 100

    Gracias.

    ResponderEliminar