Encuentra por qué tu ModelState.IsValid está marcando falso

Tenía un código similar a éste en un controlador:

if (ModelState.IsValid)
{
   //…algo
}
else
{
   //…otra cosa
   return View(cefuVM);
}

Cada vez que se ejecutaba ese código, mi “ModelState.IsValid” era falso y se iba a la parte del “else”, sin marcar ningún error aparentemente.

Para ver qué está pasando, añade esta línea de código en la parte del “else”.

if (ModelState.IsValid)
{
   //…algo
}
else
{
   var errors = ModelState.Select(x => x.Value.Errors)
   .Where(y => y.Count > 0)
   .ToList();
   //…otra cosa
   return View(cefuVM);
}

Coloca un “break” en Visual Studio y corre en modo “debug”. Analiza la variable “errors” en la ventanita “Locals” y verás algo similar a lo siguiente:

locals

Como puedes ver, ahí aparece el error que yo mismo programé en la validación de mi “ViewModel”.

Referencia.

Otro artículo relacionado.

Cómo eliminar los registros hijos relacionados de una tabla en Entity Framework

Supongamos que tienes una tabla llamada “Alumno” y otra llamada “Tarea”. La relación entre ellas es de uno a muchos, es decir, un alumno puede tener muchas tareas, y una tarea pertenece a un sólo alumno.

Ahora, supongamos que quieres eliminar todas las tareas del alumno con Id = 93 cuyo “ciclo” sea igual a 2015.

Podrías encontrar los registros relacionados e iterar en ellos realizando la eliminación de cada uno de ellos individualmente, pero hay una forma más rápida de hacerlo:

//Encontramos todos los registros que queremos eliminar
var alumno = context.Alumno.SingleOrDefault(a => a.AlumnoId == 93);
var tareasAEliminar = alumno.Tareas.Where(t => t.Ciclo == 2015);
//Eliminarlos de un sólo golpe
context.Tareas.RemoveRange(tareasAEliminar);

Listo, después de eso solamente guardas los cambios de tu contexto y en ese momento se eliminarán los registros.

Entity Framework intenta añadir un “1” después del nombre de una columna

En una “Web API” en la que estoy trabajando, estoy generando el modelo de una base de datos existente con “ADO.NET Entity Data Model” (los archivos que terminan en .edmx).

Al crear el modelo, seleccioné la opción “Include foreign key columns in the model”, y al querer guardar un registro, obtenía este error:

ExceptionMessage : Invalid column name 'MiEntidad_MiEntidadId1'

Como puedes ver, “Entity Framework” estaba intentando colocar un “1” al final del nombre de la llave foránea. Buscando en Internet encontré algo que me hizo intentar desmarcar la opción “Include foreign key columns in the model” y de esta forma se solucionó el problema.

Así que cuando crees tu modelo, hazlo así:

edmw

Con eso arreglas el problema.

An entity object cannot be referenced by multiple instances of IEntityChangeTracker

Este error me apareció en una aplicación en la que tenía el siguiente esquema:

//En uno de mis repositorios
 public class ProductoRepository: IProductoRepository, IDisposable 
 {
    private MiContext context;
    //Constructor
    public ProductoRepository(MiContext context) 
    {
       this.context = context;
    }
    //… otros métodos aquí
 }
 //En otro de mis repositorios
 public class MarcaRepository: IMarcaRepository, IDisposable 
 {
    private MiContext context;
    //Constructor
    public MarcaRepository(MiContext context) 
    {
       this.context = context;
    }
    //… otros métodos aquí
 }
 //Y en mi controller:
 public IProductoRepository repositorioProducto;
 public IMarcaRepository repositorioMarca;
 //Constructor
 public MiController() 
 {
    this.repositorioProducto = new ProductoRepository(new MiContext());
    this.repositorioMarca = new MarcaRepository(new MiContext());
 }

En los repositorios todo está bien, porque en el constructor recibimos el “context” y lo asignamos a la variable local “context”, no hay problema ahí.

Sin embargo, checa el código del “controller”. Primero creo dos variables locales, cada una para cada repositorio, y después en el constructor las asigno a una nueva instancia de la clase de cada repositorio, y paso como parámetro una nueva instancia de “MiContext” a cada una.

Precisamente esto es lo que genera el error:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker

Lo que tienes que hacer es crear una sola instancia de “MiContext” en el “controller” y luego pasar esa misma a los dos constructores de los repositorios, de esta forma:

//En el controller
 private MiContext context = new MiContext();
 public IProductoRepository repositorioProducto;
 public IMarcaRepository repositorioMarca;
 //Constructor
 public MiController()
 {
    this.repositorioProducto = new ProductoRepository(context);
    this.repositorioMarca = new MarcaRepository(context);
 }

De esta forma estarás trabajando con un sólo contexto y desaparecerá el error mencionado.

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.