none
Error en llave foranea RRS feed

  • Pregunta

  • Amigos como estan tengo un problema con una llave foranea que cree,  tengo las siguientes tablas

    Cabecera

    create table off_movcabing(
    	numero int identity(1,1) not null,
    	documento nvarchar(2) not null default 0,
    	fecha datetime,
    	contratoid int not null default 0,
    	descripcion nvarchar(100),
    	estado int default 0,
    	CONSTRAINT movcabing_pk PRIMARY KEY (numero)
    )

    Detalle

    create table off_movdeting(
    	codigo int identity(1,1) not null,
    	numero int not null,
    	documento nvarchar(2) not null,	
    	articuloid nvarchar(20) not null,
    	cantidad int,
    	CONSTRAINT movdeting_pk PRIMARY KEY (codigo),
    	constraint fk_movdeting_movcab foreign key(numero) references off_movcabing(numero),
    	constraint fk_movdeting_suministro foreign key(articuloid) references off_articulos(articuloid),
    	)

    Quiero que para poder grabar un registro en la tabla de detalle deba existir el numero de la cabecera

    constraint fk_movdeting_movcab foreign key(numero) references off_movcabing(numero),

    Para el grabado de daros uso algo como esto

    public void Save(IngresoEntity entidad,string accion)
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    int ingresoNumero = entidad.IngresoId;
                    //
                    //Grabamos la cabecera del egreso
                    //
                    if (accion == "Nuevo")
                        ingresoNumero=InsertarIngreso(entidad);
                    else
                    {
                        EliminarIngresoDetalle(entidad.IngresoId);
                        EditarIngresoCabecera(entidad);
                    }
    
                    //insertamos el detalle del egreso
                    foreach (IngresoDetalleEntity linea in entidad.Detalle)
                    {
                        if (!string.IsNullOrEmpty(linea.ArticuloId) && (linea.Cantidad>0))
                        {
                            InsertarIngresoDetalle(ingresoNumero, linea);
                        }
                    }
    
                    scope.Complete();
                }
            }

    En el campo  ingresoNumero tengo el numero de retorna la funcion InsertarIngreso que mas o menos es algo como esto

    public int InsertarIngreso(IngresoEntity entidad)
            {
                using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlServer"].ToString()))
                {
                    string query = @"INSERT INTO off_movcabing
                                           (documento
                                           ,fecha
                                           ,descripcion)
                                     VALUES
                                           (@pdocumento
                                           ,@pfecha
                                           ,@pdescripcion);
    
                                    SELECT SCOPE_IDENTITY()";
    
                    SqlCommand comando = new SqlCommand(query, conn);
                    comando.Parameters.Add(new SqlParameter("@pdocumento", SqlDbType.NVarChar)).Value = "IN";
                    comando.Parameters.Add(new SqlParameter("@pfecha", SqlDbType.DateTime)).Value = entidad.Fecha;
                    comando.Parameters.Add(new SqlParameter("@pdescripcion", SqlDbType.NVarChar)).Value = entidad.Descripcion;
                    
                    conn.Open();
    
                    int contratoNumero = Convert.ToInt32(comando.ExecuteScalar());
                    return contratoNumero;
                }
            }
    Como el campo numero de la tabla off_movcabing es de tipo identity, se supone que me da el numero incremental automatico que seria el numero de documento al que hace referencia en el detalle, pero cuando se ejecuta el metodo

     InsertarIngresoDetalle(ingresoNumero, linea);

    Despues de ingresar 2 transacciones e intentar la tercera tengo este mensaje.

    The insert statement conflicted with the FOREIGN KEY constraint "fk_movdeting_movcab". The conflic occurred in database "Base", table "dbo.off_movcabing", column 'numero'.

    The stament has been  terminated.

    No es siempre, es decir si hago un ingreso nuevo, se me graban 2 por ejemplo y ya en el tercero me da ese mensaje de error??

    Segun yo no deberia tener problema en la llave foranea ya que se ingreso correctamente la cabecera no me da error ahi, entonces no se si alguien me pude dar una idea de que puede estar pasando??

    He revisado en la tabla y los datos estan bien. No se realmente que puede ser y porque si me funciono en los primeros registros, si quito la llave foranea me graba normalmente y graba los datos bien. O es que no es necesario poner la llave ahi??

    Saludos

    miércoles, 29 de febrero de 2012 22:18

Respuestas

  • ¿Cuál instrucción falla entonces:  La adición de un detalle nuevo, supongo?  Es que el dato curioso es lo que dice el error:  table dbo.off_movcabing (no dbo.off_movdeting), column numero.  Claro, "numero" es el nombre de la columna en ambas tablas.  ¿Podría usted renombrar una de las columnas "numero" para ver si el mensaje de error cambia y ya tener 100% claro cuál es la fuente del error?  Al menos un renombre temporal, sólo para averiguar qué está pasando.

    Jose R. MCP

    • Marcado como respuesta Fsigu viernes, 2 de marzo de 2012 22:28
    viernes, 2 de marzo de 2012 17:59

Todas las respuestas

  • El lío es tu llave foránea:

    	constraint fk_movdeting_movcab foreign key(numero) references off_movcabing(numero),
    	constraint fk_movdeting_suministro foreign key(articuloid) references off_articulos(articuloid),

    Me imagino que quieres crear una llave foránea compuesta por 2 columnas. Si ese es el caso, debes reemplazar tu código por algo parecido a lo siguiente siguiente:

    constraint fk_movdeting_movcab foreign key(numero, articuloid) references off_movcabing(numero,articuloid)


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com

    viernes, 2 de marzo de 2012 17:23
  • Gracias amigo por responder, pero no solo quiero una llave foranea del campo numero, es decir quiero que no se pueda insertar en la tabla detalle si no hay el numero en la cabecera.

    En la tabla cabecera el campo numero es la llave primaria, entonces quiero que no se puede insertar nada en el detalle sin que tengo su cabecera.

    Luego podria hacer otra llave para que no inserte un codigo de articulo que no exista.

    Saludos

    viernes, 2 de marzo de 2012 17:27
  • Cuando depura el código, ¿qué valor está almacenado en la variable ingresoNumbero del método Save()?  Además usted no nos menciona cuál instrucción Sql es la que falla:  La del ingreso del registro maestro, o los ingresos de los detalles.

    Jose R. MCP

    viernes, 2 de marzo de 2012 17:41
  • Gracias Jose, si perdon falla al insertar en el detalle, y el valor de ingresoNumero si tiene un valor nuevo, es decir no esta repetido.


    Saludos

    viernes, 2 de marzo de 2012 17:44
  • ¿Cuál instrucción falla entonces:  La adición de un detalle nuevo, supongo?  Es que el dato curioso es lo que dice el error:  table dbo.off_movcabing (no dbo.off_movdeting), column numero.  Claro, "numero" es el nombre de la columna en ambas tablas.  ¿Podría usted renombrar una de las columnas "numero" para ver si el mensaje de error cambia y ya tener 100% claro cuál es la fuente del error?  Al menos un renombre temporal, sólo para averiguar qué está pasando.

    Jose R. MCP

    • Marcado como respuesta Fsigu viernes, 2 de marzo de 2012 22:28
    viernes, 2 de marzo de 2012 17:59
  • Gracias jose realmente lo corregi eliminando todas las llaves de las tablas y volviendolas a crear, gracias igual a todos por la ayuda.

    viernes, 2 de marzo de 2012 20:13
  • Fsigu, si ya esta respondido, tienes que marcar como respuesta. Y todos los comentarios útiles los puedes calificar haciendo click en votar como útil.

    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com

    viernes, 2 de marzo de 2012 20:16