Entity Framework - Caricamento lento

Il caricamento lento è il processo mediante il quale un'entità o una raccolta di entità viene caricata automaticamente dal database la prima volta che si accede a una proprietà che fa riferimento all'entità / entità. Il caricamento lento significa ritardare il caricamento dei dati correlati, fino a quando non lo richiedi specificamente.

  • Quando si utilizzano i tipi di entità POCO, il caricamento lento si ottiene creando istanze di tipi di proxy derivati ​​e quindi sovrascrivendo le proprietà virtuali per aggiungere l'hook di caricamento.

  • Il caricamento lento è praticamente l'impostazione predefinita.

  • Se lasci la configurazione predefinita e non dici esplicitamente a Entity Framework nella tua query che vuoi qualcosa di diverso dal caricamento lento, il caricamento lento è ciò che otterrai.

  • Ad esempio, quando si utilizza la classe dell'entità Studente, le registrazioni correlate verranno caricate la prima volta che si accede alla proprietà di navigazione Iscrizioni.

  • La proprietà di navigazione deve essere definita come pubblica, virtuale. Il contesto lo faràNOT eseguire il caricamento lento se la proprietà non è definita come virtuale.

Di seguito è riportata una classe Student che contiene la proprietà di navigazione di 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; }
}

Diamo un'occhiata a un semplice esempio in cui l'elenco degli studenti viene caricato prima dal database e poi caricherà le iscrizioni di un particolare studente ogni volta che ne avrai bisogno.

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();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, riceverai il seguente output.

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

Disattiva il caricamento lento

Il caricamento lento e la serializzazione non si combinano bene e, se non stai attento, puoi finire per interrogare l'intero database solo perché il caricamento lento è abilitato. È buona norma disattivare il caricamento lento prima di serializzare un'entità.

Disattivazione per proprietà di navigazione specifiche

Il caricamento lento della raccolta Enrollments può essere disattivato rendendo la proprietà Enrollments non virtuale come illustrato nell'esempio seguente.

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; } 
}

Disattiva per tutte le entità

Il caricamento lento può essere disattivato per tutte le entità nel contesto impostando un flag sulla proprietà Configuration su false, come mostrato nell'esempio seguente.

public partial class UniContextEntities : DbContext { 

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

Dopo aver disattivato il caricamento lento, ora, quando esegui di nuovo l'esempio precedente, vedrai che le iscrizioni non vengono caricate e vengono recuperati solo i dati degli studenti.

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

Ti consigliamo di eseguire l'esempio precedente in modo graduale per una migliore comprensione.