Entity Framework: seguimiento de cambios

Entity Framework proporciona la capacidad de realizar un seguimiento de los cambios realizados en las entidades y sus relaciones, por lo que se realizan las actualizaciones correctas en la base de datos cuando se llama al método de contexto SaveChanges. Esta es una característica clave de Entity Framework.

  • El seguimiento de cambios realiza un seguimiento de los cambios mientras se agregan nuevos registros a la colección de entidades, modificando o eliminando entidades existentes.

  • Luego, todos los cambios se mantienen en el nivel DbContext.

  • Estos cambios de seguimiento se pierden si no se guardan antes de que se destruya el objeto DbContext.

  • La clase DbChangeTracker le brinda toda la información sobre las entidades actuales que están siendo rastreadas por el contexto.

  • Para rastrear cualquier entidad por contexto, debe tener la propiedad de clave primaria.

En Entity Framework, el seguimiento de cambios está habilitado de forma predeterminada. También puede deshabilitar el seguimiento de cambios estableciendo la propiedad AutoDetectChangesEnabled de DbContext en false. Si esta propiedad se establece en true, Entity Framework mantiene el estado de las entidades.

using (var context = new UniContextEntities()) {
   context.Configuration.AutoDetectChangesEnabled = true;
}

Echemos un vistazo al siguiente ejemplo en el que los estudiantes y sus inscripciones se recuperan de la base de datos.

class Program {

   static void Main(string[] args) {

      using (var context = new UniContextEntities()) {

         context.Configuration.AutoDetectChangesEnabled = true;
         Console.WriteLine("Retrieve Student");

         var student = (from s in context.Students where s.FirstMidName == 
            "Ali" select s).FirstOrDefault<Student>();

         string name = student.FirstMidName + " " + student.LastName;
         Console.WriteLine("ID: {0}, Name: {1}", student.ID, name);
         Console.WriteLine();
         Console.WriteLine("Retrieve all related enrollments");

         foreach (var enrollment in student.Enrollments) {
            Console.WriteLine("Enrollment ID: {0}, Course ID: {1}", 
               enrollment.EnrollmentID, enrollment.CourseID);
         }

         Console.WriteLine();

         Console.WriteLine("Context tracking changes of {0} entity.", 
            context.ChangeTracker.Entries().Count());

         var entries = context.ChangeTracker.Entries();

         foreach (var entry in entries) {
            Console.WriteLine("Entity Name: {0}", entry.Entity.GetType().Name);
            Console.WriteLine("Status: {0}", entry.State);
         }

         Console.ReadKey();
      }
   }
}

Cuando se compile y ejecute el ejemplo anterior, recibirá el siguiente resultado.

Retrieve Student 
ID: 1, Name: Ali Alexander
Retrieve all related enrollments
       Enrollment ID: 1, Course ID: 1050
       Enrollment ID: 2, Course ID: 4022
       Enrollment ID: 3, Course ID: 4041
Context tracking changes of 4 entity.
Entity Name: Student
Status: Unchanged
Entity Name: Enrollment
Status: Unchanged
Entity Name: Enrollment
Status: Unchanged
Entity Name: Enrollment
Status: Unchanged

Puede ver que todos los datos solo se recuperan de la base de datos, por eso el estado no cambia para todas las entidades.

Echemos ahora un vistazo a otro ejemplo sencillo en el que agregaremos una inscripción más y eliminaremos un estudiante de la base de datos. A continuación se muestra el código en el que se agrega una nueva inscripción y se elimina un estudiante.

class Program {

   static void Main(string[] args) {

      using (var context = new UniContextEntities()) {

         context.Configuration.AutoDetectChangesEnabled = true;

         Enrollment enr = new Enrollment() { 
            StudentID = 1, CourseID = 3141 
         };

         Console.WriteLine("Adding New Enrollment");
         context.Enrollments.Add(enr);
         Console.WriteLine("Delete Student");

         var student = (from s in context.Students where s.ID == 
            23 select s).SingleOrDefault<Student>();

         context.Students.Remove(student);
         Console.WriteLine("");

         Console.WriteLine("Context tracking changes of {0} entity.", 
            context.ChangeTracker.Entries().Count());
         var entries = context.ChangeTracker.Entries();

         foreach (var entry in entries) {
            Console.WriteLine("Entity Name: {0}", entry.Entity.GetType().Name);
            Console.WriteLine("Status: {0}", entry.State);
         }

         Console.ReadKey();
      }
   }
}

Cuando se compile y ejecute el ejemplo anterior, recibirá el siguiente resultado.

Adding New Enrollment
Delete Student
Context tracking changes of 2 entity.
Entity Name: Enrollment
Status: Added
Entity Name: Student
Status: Deleted

Ahora puede ver que el estado de la entidad de inscripción se establece en agregado y el estado de la entidad de estudiante se elimina, porque se agregó una nueva inscripción y se quitó un estudiante de la base de datos.

Le recomendamos que ejecute el ejemplo anterior paso a paso para una mejor comprensión.