Entity Framework: carga diferida

La carga diferida es el proceso mediante el cual una entidad o colección de entidades se carga automáticamente desde la base de datos la primera vez que se accede a una propiedad que hace referencia a la entidad / entidades. La carga diferida significa retrasar la carga de datos relacionados hasta que lo solicite específicamente.

  • Cuando se utilizan tipos de entidad POCO, la carga diferida se logra creando instancias de tipos de proxy derivados y luego anulando las propiedades virtuales para agregar el gancho de carga.

  • La carga diferida es prácticamente la predeterminada.

  • Si deja la configuración predeterminada y no le dice explícitamente a Entity Framework en su consulta que desea algo más que la carga diferida, la carga diferida es lo que obtendrá.

  • Por ejemplo, cuando se usa la clase de entidad Estudiante, las inscripciones relacionadas se cargarán la primera vez que se acceda a la propiedad de navegación Inscripciones.

  • La propiedad de navegación debe definirse como pública, virtual. El contextoNOT Realice una carga diferida si la propiedad no está definida como virtual.

A continuación se muestra una clase para estudiantes que contiene la propiedad de navegación de Enrollments.

public partial class Student {

   public Student() {
      this.Enrollments = new HashSet<Enrollment>();
   }
	
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public System.DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

Echemos un vistazo a un ejemplo simple en el que la lista de estudiantes se carga primero desde la base de datos y luego cargará las inscripciones de un estudiante en particular cuando lo necesite.

class Program {

   static void Main(string[] args) {

      using (var context = new UniContextEntities()) {

         //Loading students only
         IList<Student> students = context.Students.ToList<Student>();

         foreach (var student in students) {

            string name = student.FirstMidName + " " + student.LastName;
            Console.WriteLine("ID: {0}, Name: {1}", student.ID, name);
	
            foreach (var enrollment in student.Enrollments) {
               Console.WriteLine("Enrollment ID: {0}, Course ID: {1}", 
                  enrollment.EnrollmentID, enrollment.CourseID);
            }
         }

         Console.ReadKey();
      }
   }
}

Cuando se compile y ejecute el código anterior, recibirá el siguiente resultado.

ID: 1, Name: Ali Alexander
       Enrollment ID: 1, Course ID: 1050
       Enrollment ID: 2, Course ID: 4022
       Enrollment ID: 3, Course ID: 4041
ID: 2, Name: Meredith Alonso
       Enrollment ID: 4, Course ID: 1045
       Enrollment ID: 5, Course ID: 3141
       Enrollment ID: 6, Course ID: 2021
ID: 3, Name: Arturo Anand
       Enrollment ID: 7, Course ID: 1050
ID: 4, Name: Gytis Barzdukas
       Enrollment ID: 8, Course ID: 1050
       Enrollment ID: 9, Course ID: 4022
ID: 5, Name: Yan Li
       Enrollment ID: 10, Course ID: 4041
ID: 6, Name: Peggy Justice
       Enrollment ID: 11, Course ID: 1045
ID: 7, Name: Laura Norman
       Enrollment ID: 12, Course ID: 3141

Desactivar la carga diferida

La carga diferida y la serialización no se mezclan bien, y si no tiene cuidado, puede terminar consultando toda su base de datos solo porque la carga diferida está habilitada. Es una buena práctica desactivar la carga diferida antes de serializar una entidad.

Desactivar para propiedades de navegación específicas

La carga diferida de la colección Enrollments se puede desactivar haciendo que la propiedad Enrollments no sea virtual, como se muestra en el siguiente ejemplo.

public partial class Student { 

   public Student() { 
      this.Enrollments = new HashSet<Enrollment>(); 
   }
	
   public int ID { get; set; } 
   public string LastName { get; set; } 
   public string FirstMidName { get; set; } 
   public System.DateTime EnrollmentDate { get; set; }
	
   public ICollection<Enrollment> Enrollments { get; set; } 
}

Desactivar para todas las entidades

La carga diferida se puede desactivar para todas las entidades en el contexto estableciendo una marca en la propiedad Configuración en falso como se muestra en el siguiente ejemplo.

public partial class UniContextEntities : DbContext { 

   public UniContextEntities(): base("name = UniContextEntities") {
      this.Configuration.LazyLoadingEnabled = false;
   }
	
   protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
      throw new UnintentionalCodeFirstException(); 
   } 
}

Después de desactivar la carga diferida, ahora, cuando vuelva a ejecutar el ejemplo anterior, verá que las inscripciones no se cargan y solo se recuperan los datos de los estudiantes.

ID: 1, Name: Ali Alexander
ID: 2, Name: Meredith Alons
ID: 3, Name: Arturo Anand
ID: 4, Name: Gytis Barzduka
ID: 5, Name: Yan Li
ID: 6, Name: Peggy Justice
ID: 7, Name: Laura Norman
ID: 8, Name: Nino Olivetto

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