none
Error al querer actualizar un registro mediante EF. RRS feed

  • Pregunta

  • Saludos amigos de la MSDN.

    Actualmente estoy utilizando el EF 6.x, cuando quiere buscar un registro en la base de datos uso el siguiente codigo:

      public List<tbCategoriaProducto> GetListEntities(int estado)
            {
    
                try
                {
                    dbSisSodInaEntities2 context = new dbSisSodInaEntities2();
                    
                        if (estado == (int)Enumeradores.Estado.Activo)
                        {
                            //Recuperamos los datos de la tabla con el estado en activo.
                            return (from p in context.tbCategoriaProducto
                                    where p.estado == true
                                    select p).ToList();
                        }
                        else if (estado == (int)Enumeradores.Estado.Inactivo)
                        {
                            //Recuperamos los valores con el estado en inactivo
                            return (from p in context.tbCategoriaProducto
                                    where p.estado == false
                                    select p).ToList();
    
                        }
                        else
                        {
                            //Recuperamos todos los valores de la tabla.
                            return (from p in context.tbCategoriaProducto
                                    select p).ToList();
    
                        }
    
                    
                }
                catch (Exception ex)
                {
    
                    throw new Exception("Ha ocurrido el siguiente error: " + ex.ToString());
                }
    
            
            
            }

    Dado que son tablas relacionales, nuestro profesor nos dijo que la mejor forma para que los datos no se pierdan al realizar el dispose del  DbContext es no utilizando el Using.

    Entonces al querer actualizar la informacion de los datos recuperados y puestos en el formulario. me esta generando el siguiente error:

    Tengo entendido que al realizar la actualizacion mediante el siguiente codigo: 

     public tbCategoriaProducto Actualizar(tbCategoriaProducto categoriaNueva)
            {
                try
                {
                    using (dbSisSodInaEntities2 context = new dbSisSodInaEntities2())
                    {
    
                        context.Entry(categoriaNueva).State = System.Data.Entity.EntityState.Modified;
                        context.SaveChanges();
    
                        return categoriaNueva;
    
                    }
    
                }
                catch (UpdateRecordException ex)
                {
    
                    throw new Exception(ex.Message);
                }
    
                catch (Exception ex)
                {
                    throw new Exception("Ha ocurrido el siguiente error: " + ex.ToString());
                }
    
            }

    Al crear una nueva instancia del DbContext, el EF no sabe cual de las dos instancias en memoria utlizar, mi consulta viene a ser la siguiente.

    ¿Como puedo eliminar de la memoria esa instancia que he creado del DbContext ? y ¿ Hay alguna otra manera de poder retornar los valores de una tabla relacional sin que se pierdan en memoria utlizando el using ?

    Saludos y muchas gracias de antemano.

    lunes, 12 de octubre de 2015 21:36

Todas las respuestas

  • Hola Jose Cartin,

    Lo correcto es que la instancia del DBContext este enmarcado por el ámbito de la instrucción using. No deberías tener una instancia del contexto con ámbito de la clase. 

    lunes, 12 de octubre de 2015 22:02
  • Muchas gracias por tu respuesta. Actualmente la solucion correcta es utilizar el using, pero el detalle esta en que cuando realizo la consulta de busqueda para obtener valores de una tabla con sus relaciones que necesito recuperar, me genera error, dado que no me recupera los valores de las tablas de relacion.

    Saludos, y gracias de antemano.

    lunes, 12 de octubre de 2015 22:39
  • Hola Jose Cartin,

    Quizá si pones en mayor evidencia el problema que tienes sería mejor para apoyarte. ¿Cuál es la consulta que realizas de múltiples relaciones? ¿Qué error te retorna? ¿En qué parte del código te marca la excepción?

    Si reduces el ámbito del using a sólo una operación no deberías tener problemas, OJO, no deberías tener una instancia del contexto dentro de otra, cada instancia de contexto es independiente.

    lunes, 12 de octubre de 2015 23:34
  • Aqui te paso el codigo de como realmente deberia ser realizada la consulta:

     public List<tbCategoriaProducto> GetListEntities(int estado)
            {
    
                try
                {
                    using (dbSisSodInaEntities2 context = new dbSisSodInaEntities2())
                    {
    
                        if (estado == (int)Enumeradores.Estado.Activo)
                        {
                            //Recuperamos los datos de la tabla con el estado en activo.
                            return (from p in context.tbCategoriaProducto
                                    where p.estado == true
                                    select p).ToList();
                        }
                        else if (estado == (int)Enumeradores.Estado.Inactivo)
                        {
                            //Recuperamos los valores con el estado en inactivo
                            return (from p in context.tbCategoriaProducto
                                    where p.estado == false
                                    select p).ToList();
    
                        }
                        else
                        {
                            //Recuperamos todos los valores de la tabla.
                            return (from p in context.tbCategoriaProducto
                                    select p).ToList();
    
                        }
    
                    }
                }
                catch (Exception ex)
                {
    
                    throw new Exception("Ha ocurrido el siguiente error: " + ex.ToString());
                }
    
            
            
            }
    

    Ahi todo correcto, porque es una tabla sin relaciones que ella ocupe de otra tabla.

    El problema se provoca cuando quiero recuperar datos de una tabla que contiene relaciones con otras. Segu nuestro profesor, para poder recuperar los datos de la tabla junto a los datos de sus relaciones, debemos usar el DbContext sin el using, y ahi es donde esta generando el problema.

    Mi consulta entonces es, ¿ Que otra forma hay de que pueda retornar los valores de una tabla y sus relaciones sin dejar la instancia del DbContext abierta en memoria?

     
      public List<tbIngredientes> getIngredientes(int idIngrediente)
            {
    
                try
                {
    
                    dbSisSodInaEntities2 context = new dbSisSodInaEntities2();
                    
                        //Recuperamos los ingredientes segun su tipo.
                        return  (from p in context.tbIngredientes
                                             where p.idTipoIngrediente == idIngrediente
                                             select p).ToList();
    
    
                }
                catch (Exception ex)
                {
                    throw ex;
                }
    
            }

    En el siguiente codigo veriamos como el profesor nos sugerio realizar la consulta para recuperar los datos de la tabla y sus relaciones, adjunto foto del modelado de datos.

    Y el error provacado es el que ya habia puesto en el inicio del tema.

    Saludos y gracias de antemano.

    martes, 13 de octubre de 2015 4:29
  • Hola Jose Cartin,

    Vamos por partes:

    El método GetListEntities (que por cierto debería tener un nombre no tan genérico, algo más especifico) debería poder reducirse - bajo mi criterio - a lo siguiente:

    public List<tbCategoriaProducto> GetListEntities(bool? estado)
    {
    	try
    	{
    		using (dbSisSodInaEntities2 context = new dbSisSodInaEntities2())
    		{
    			var categoriasProducto = context.tbCategoriaProducto.Where(x => x.estado == estado || estado == null);
    			
    			return categoriasProducto.ToList();
    		}
    	}
    	catch (Exception ex)
    	{
    		throw new Exception("Ha ocurrido el siguiente error: " + ex.ToString());
    	}
    }

    El parámetro estado del método GetListEntities puede recibir los siguientes valores: true, false o null cuando se quiera mostrar todos los registros sin filtrar por el estado.

    Por otro lado, el tema de que una tabla esté relacionada con otras no impide que se pueda usar la instrucción using, es más, reitero que lo mejor que puedes hacer es enmarcar el ámbito del contexto con using. Fíjate que la segunda consulta tampoco relaciona dos tablas, es sólo una tabla.

    public List<tbIngredientes> getIngredientes(int idIngrediente)
    {
    	try
    	{
    		using (dbSisSodInaEntities2 context = new dbSisSodInaEntities2())
    		{
    			var ingredientes = context.tbIngredientes.Where(x => x.idTipoIngrediente == idIngrediente);
    			
    			return ingredientes.ToList();
    		}
    	}
    	catch (Exception ex)
    	{
    		throw ex;
    	}
    
    }


    No deberías tener problemas si el objeto context lo usas dentro del ámbito del using, revisa que no tengas declarado el objeto context a nivel de clase.

    martes, 13 de octubre de 2015 5:23
  • Primero deverias de fijarte que tengas LazyLoadingEnabled = true en tu modelo para que por default te jale las relaciones de tus llaves foraneas, te paso un ejemplo de una consulta que te jala tus relaciones

    public AlmacenProductos obtenProdAlma(int idAlmacen, string idProducto)
            {
                AlmacenProductos Result = new AlmacenProductos();
                contexto = new VeloZhoesBDEntities();
                contexto.Configuration.LazyLoadingEnabled = true;
                try
                {
                    Result = contexto.AlmacenProductos.FirstOrDefault(q => q.IdAlmacen == idAlmacen &&      q.IdProducto == idProducto);
                    return Result;
                }
                catch(Exception ex)
                {
                    throw (ex);
                }
                finally
                {
                    Result = null;
                    contexto = null;
                }
            }

    El error que tienes o el por qué no te jala las relaciones es porque cierras el contexto antes de enviar el resultado, con el código que puse arribita no deberías tener inconvenientes solo adaptalo a tu consulta.

    Saludos !!!

    miércoles, 25 de noviembre de 2015 17:45