Cómo duplicar un objeto incluyendo objetos relacionados con Entity Framework

Partiendo del supuesto que tenemos un objeto que tiene objetos relacionados (hijos), lo podemos clonar incluyendo sus objetos relacionados.

Para hacerlo tenemos que usar “AsNoTracking” en “Entity Framework”, de esta manera:

var clon = context.Alumno
           .AsNoTracking()
           .Include(a => a.Asignaciones)
           .Include(a => a.Domicilios)
           .Single(a => a.AlumnoId == "5");

Como puedes ver, estamos encontrando el alumno que tenga un Id igual a 5, y estamos especificando que se incluyan sus objetos relacionados (hijos) de asignaciones y domicilios. Esto va a encontrar al alumno y guardarlo en la variable “clon”, la cual contendrá todos sus descendientes de asignaciones y domicilios.

Si no utilizas “AsNoTracking” entonces todo cambio que hagas en el objeto nuevo va a operar, obviamente, sobre el objeto original.

Al usar “AsNoTracking”, puedes hacer las modificaciones que gustes a “clon” y al final guardarlo. Cuando hagas esto se creará una copia nueva del objeto original, es decir, lo habrás duplicado.

Cómo visualizar el valor de EntityValidationErrors en Visual Studio

Quizás en algún desarrollo te has enfrentado a este error:

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

El error nos indica que tenemos que visualizar la colección “EntityValidationErrors” para encontrar los errores que está marcando nuestra aplicación.

La forma más sencilla de hacerlo es correr la aplicación en “Debug mode” en Visual Studio, y en la ventanita “Watch” añadir lo siguiente:

((System.Data.Entity.Validation.DbEntityValidationException) $exception).EntityValidationErrors

Y verás los errores de esta forma:

errorvalidation

Espero que te sirva.

Otro artículo relacionado.

Cómo escribir y leer valores en localStorage utilizando javaScript

“localStorage” es una mejora de las “Cookies”, te permite almacenar y leer información en el navegador, sin tener que enviarse necesariamente al servidor. Es muy útil si necesitas guardar datos que vas a estar utilizando continuamente, por ejemplo, con plugins de jQuery: “data grids”, selectores de opciones, guardar el estado de un menú, etc. El tamaño máximo que puedes guardar utilizando “localStorage” son 10MB.

Es muy fácil de utilizar, para crear una variable hazlo así:

localStorage.setItem("Numero", 11);
localStorage.setItem("Nombre", "Checo Pérez");

Si quieres saber si una variable ya está establecida, utiliza:

if (localStorage.getItem("Numero")) {
   //Haz algo aquí
}

Para obtener el valor de una variable:

var elNombre = localStorage.getItem("Nombre");
var elNumero = parseInt(localStorage.getItem("Numero"));

Para eliminar una variable:

localStorage.removeItem("Nombre");

Ahora bien, si estás usando objetos, entonces necesitas primero guardarlos como Json. Hazlo así:

var miObjeto = { Nombre: "Checo Pérez", Numero: 11, Pais: "México", Activo: true };
//Para colocar el objeto en localStorage
localStorage.setItem("Piloto", JSON.stringify(miObjeto));
//Para leer el objeto Json
var piloto = JSON.parse(localStorage.getItem("Piloto"));
//Para leer las propiedades:
var nombre = piloto.Nombre;
var numero = piloto.Numero;
var pais = piloto.Pais;
var activo = piloto.Activo;

Espero que te sirva.

Cómo enviar un valor temporal de una página a otra utilizando TempData

Tratando de utilizar “ViewBag” dentro de un “Controller”, tenía lo siguiente:

ViewBag.HayErrores = "verdadero";
return RedirectToAction("OtraAccion");

En la página “OtraAccion” el valor de “ViewBag.HayErrores” ya no existe.
Esto se debe a que los “ViewBag” no son persistentes al realizar la redirección.

Para utilizar un valor temporal que sobreviva a la redirección, debes utilizar “TempData”, para nuestro ejemplo quedaría así:

TempData["HayErrores"] = "verdadero";
return RedirectToAction("OtraAccion");

Y después en tu “View” puedes checar el valor utilizando “Razor”. Solamente tienes que checar primero que el valor no sea nulo, de esta forma:

var HayErrores = "";
if (TempData["HayErrores"] != null) 
{
   HayErrores = TempData["HayErrores"].ToString();
}
if (HayErrores == "verdadero") 
{
   <h3> Error </h3>
   Hay un error, por favor vuelve a intentarlo.
}

New transaction is not allowed because there are other threads running in the session

Estaba guardando varios registros en un ciclo utilizando “Entity Framework”, y dentro de este ciclo estaba llamando “SaveChanges”.

Algo similar a esto:

foreach (var cliente in clientes)
{
   var ElCliente = new Cliente();
   ElCliente.Nombre = cliente.Nombre;
   ElCliente.Apellido = cliente.Apellido;
   repositorioClientes.Insertar(ElCliente);
   repositorioClientes.SaveChanges();
}

Al hacer lo anterior, me aparecía este mensaje:

New transaction is not allowed because there are other threads running in the session.

Investigando en Internet me di cuenta de que para evitar este error lo mejor es hacer solamente las inserciones dentro del ciclo, pero dejar el “SaveChanges” fuera del mismo, de esta forma:

foreach (var cliente in clientes)
{
   var ElCliente = new Cliente();
   ElCliente.Nombre = cliente.Nombre;
   ElCliente.Apellido = cliente.Apellido;
   repositorioClientes.Insertar(ElCliente);
}
repositorioClientes.SaveChanges();

Y listo, con eso se fue el error y los registros se guardaron correctamente.