Ya se comento como actualizar una entidad con los métodos de Attach() y Refresh() en el post "Actualizar entidades con Attach() y Refresh() en LINQ"

Ahora les mostrare la forma de actualizar campos que desean que sean nulos o con valor false.
Ahora les mostrare la forma de actualizar campos que desean que sean nulos o con valor false.Como ya sabrán, en el momento de querer actualizar una entidad, el Refresh() se encarga de realizar el query que actualiza el registro, manteniendo los campos que no han sido modificados, esos campos son los nulos y los de valor false.

Por ejemplo:

Digamos que tienen la tabla Producto con los siguientes campos:

IDProducto    int     not null
Codigo    nvarchar(50)      not null
Nombre    nvarchar(50)      not null
Descripcion    nvarchar(50)      null
IsExistente    bit     not null

En este ejemplo se presenta el siguiente caso:

A la hora de actualizar se asignan los campos IDProducto y Codigo de la siguiente manera:
protected void btnActualizar_Click(object sender, EventArgs e)
{  
    Producto p = new Producto();  
    try  
    {      
        p.IDProducto = 3;      
        p.Codigo = "234";      
        if (Catalogo.ActualizaProducto(p))          
            Response.Write("Actualización exitosa");  
    }  
    catch (Exception ex)  
    {      
        Response.Write(ex.Message);  
    }
}

El método ActualizaProducto se encarga de actualizar la entidad.
public static bool ActualizaProducto(Producto ProductoModificado)
{
    try
    {
        using (AdvertisingDataContext DB = new AdvertisingDataContext())
        {
            Producto ProductoNuevo = new Producto();
            ProductoNuevo.IDProducto = ProductoModificado.IDProducto;
            DB.Productos.Attach(ProductoModificado, ProductoNuevo);
            DB.Refresh(System.Data.Linq.RefreshMode.KeepChanges, ProductoModificado);
            DB.SubmitChanges(); return true;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Al final el query que actualizó el registro es este:
DECLARE @p0 Int SET @p0 = 3
DECLARE @p1 NVarChar(1000) SET @p1 = '234'
UPDATE [Productos]
SET [Codigo] = @p1
WHERE [IDProducto] = @p0

Como verán, la tabla Producto tiene 5 campos y el query de Update solo contempla 2 (uno para identificar el registro y el otro para asignar el valor), que pasa con los demás campos?

Cuando declaramos una instancia de la entidad Producto. Ejemplo:
Producto producto = new Producto();

Todas sus propiedades automáticamente heredan el valor por default que este indicado en la clase Producto, en este caso "null" y aquellos que son de tipo booleano son "false".

Cuando hacemos uso del Refresh() en modo "KeepChanges", automaticamente este método revisa los campos donde su valor sea nulos o false y los omite en el query del Update.

Esto normalmente no tiene ningún inconveniente, pero puede existir el caso que sea necesario asignar campos nulos o valores false en la base de datos, para poder hacer esto les mostrare la forma de hacerlo.

Tomando el mismo ejemplo de arriba, ahora asignaré los campos Descripcion en nulo e IsExistente en false. Ejemplo:
protected void btnActualizar_Click(object sender, EventArgs e)
{
    Producto p = new Producto();
    try
    {
        p.IDProducto = 3;
        p.Codigo = "234";
        p.Descripcion = null;
        p.IsExistente = false;
        if (Catalogo.ActualizaProducto(p))
            Response.Write("Actualización exitosa");
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }
}

Dejando el método ActualizaProducto tal y como esta, el query del Update se crea exactamente como lo mostré unas líneas arriba.

Para poder actualizar esos campos, es necesario crear nuevas variables que guarden el valor del campo que queremos actualizar, para utilizarlos justo despues del Refresh(). Ejemplo:
public bool ActualizaProducto(Productos ProductoModificado)
{
    try
    {
        string Descripcion = ProductoModificado.Descripcion;
        bool IsExistente = ProductoModificado.IsExistente;
        using (TypedDataContext DB = new TypedDataContext())
        {
            Productos ProductoNuevo = new Productos();
            ProductoNuevo.IDProducto = ProductoModificado.IDProducto;
            DB.Productos.Attach(ProductoModificado, ProductoNuevo);
            DB.Refresh(System.Data.Linq.RefreshMode.KeepChanges, ProductoModificado);
            ProductoModificado.Descripcion = Descripcion;
            ProductoModificado.IsExistente = IsExistente;
            DB.SubmitChanges();
            return true;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Se tiene que hacer asi, ya que los valores de las propiedades de la entidad Producto se actualizan una vez que se ejecuta la linea del Refresh(), pero al momento de asignar los valores a nuevas variables, estas si mantienen el valor original, y al reasignarlas despues del Refresh() forzamos al query del Update que las considere.

Esto es recomendable solo cuando se tiene considerado guardar campos como nulos, pero es necesario para campos booleanos que necesiten ser false.

En el query final, podemos ver como ahora si son considerados los valores nulos y false.
DECLARE @p0 Int SET @p0 = 3
DECLARE @p1 NVarChar(1000) SET @p1 = '234'
DECLARE @p2 NVarChar(1000) SET @p2 = NULL
DECLARE @p3 Bit SET @p3 = 0
UPDATE [Productos]
SET [Codigo] = @p1, [Descripcion] = @p2, [IsExistente] = @p3
WHERE [IDProducto] = @p0

Your comment will be posted after it is approved.


Leave a Reply.