エンティティフレームワーク-遅延読み込み

遅延読み込みは、エンティティまたはエンティティのコレクションが、エンティティを参照するプロパティに初めてアクセスされたときにデータベースから自動的に読み込まれるプロセスです。遅延読み込みとは、特に要求するまで、関連データの読み込みを遅らせることを意味します。

  • POCOエンティティタイプを使用する場合、遅延読み込みは、派生プロキシタイプのインスタンスを作成し、仮想プロパティをオーバーライドして読み込みフックを追加することで実現されます。

  • 遅延読み込みはほとんどデフォルトです。

  • デフォルトの構成のままにして、クエリでEntity Frameworkに遅延読み込み以外のものが必要であることを明示的に指示しない場合、遅延読み込みが得られます。

  • たとえば、Studentエンティティクラスを使用する場合、関連するEnrollmentsは、Enrollmentsナビゲーションプロパティに最初にアクセスしたときに読み込まれます。

  • ナビゲーションプロパティは、パブリック、仮想として定義する必要があります。コンテキストはNOT プロパティが仮想として定義されていない場合は、遅延読み込みを実行します。

以下は、Enrollmentsのナビゲーションプロパティを含むStudentクラスです。

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

最初に学生リストがデータベースからロードされ、次に必要なときに特定の学生の登録がロードされる簡単な例を見てみましょう。

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

上記のコードをコンパイルして実行すると、次の出力が返されます。

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

遅延読み込みをオフにする

遅延読み込みとシリアル化はうまく混ざりません。注意しないと、遅延読み込みが有効になっているという理由だけでデータベース全体をクエリすることになります。エンティティをシリアル化する前に、遅延読み込みをオフにすることをお勧めします。

特定のナビゲーションプロパティをオフにする

次の例に示すように、Enrollmentsプロパティを非仮想化することで、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 ICollection<Enrollment> Enrollments { get; set; } 
}

すべてのエンティティに対してオフにします

次の例に示すように、Configurationプロパティのフラグをfalseに設定することで、コンテキスト内のすべてのエンティティの遅延読み込みをオフにできます。

public partial class UniContextEntities : DbContext { 

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

遅延読み込みをオフにした後、上記の例を再度実行すると、登録が読み込まれず、学生データのみが取得されることがわかります。

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

理解を深めるために、上記の例を段階的に実行することをお勧めします。