Apa pengaruh kata kunci virtual dalam Entity Framework 4.1 POCO Code First?

229

Apakah virtualkata kunci memiliki efek ketika digunakan pada properti di EF Code First ?. Dapatkah seseorang menggambarkan semua konsekuensinya dalam situasi yang berbeda?

Misalnya, saya tahu ini dapat mengontrol pemuatan malas - jika Anda menggunakan kata kunci virtual pada properti hubungan ICollection / one-to-many, itu akan dimuat secara malas, sedangkan jika Anda membiarkan kata kunci virtual keluar, itu akan bersemangat.

Apa efek lain yang dapat virtualdimiliki kata kunci dalam EF dengan entitas POCO ?. Haruskah saya menjadikannya default untuk digunakan virtualdi semua properti saya, atau default untuk tidak menggunakannya?

Scott Stafford
sumber

Jawaban:

194

Sejauh ini, saya tahu efek ini.

  • Lazy Loading : Setiap virtualICollections akan malas dimuat kecuali Anda secara khusus menandai mereka sebaliknya.
  • Pelacakan perubahan yang lebih efisien . Jika Anda memenuhi semua persyaratan berikut ini maka pelacakan perubahan Anda dapat menggunakan metode yang lebih efisien dengan mengaitkan properti virtual Anda. Dari tautan:

    Untuk mendapatkan proksi pelacakan perubahan, aturan dasarnya adalah kelas Anda harus publik, non-abstrak atau tidak disegel. Kelas Anda juga harus menerapkan pengambil / setter virtual publik untuk semua properti yang bertahan. Terakhir, Anda harus mendeklarasikan properti navigasi hubungan berbasis koleksi sebagai ICollection<T>satu - satunya. Mereka tidak dapat berupa implementasi konkret atau antarmuka lain yang berasal dari ICollection<T>(perbedaan dari proksi Pemuatan yang Ditangguhkan)

Tautan lain yang bermanfaat yang menjelaskan hal ini adalah Persyaratan MSDN untuk Membuat Proxy POCO .

Scott Stafford
sumber
52
Tidak ada alasan lain untuk membuat properti virtual. Properti navigasi ditandai sebagai virtual untuk pemuatan yang malas dan properti skalar ditandai sebagai virtual untuk pelacakan perubahan.
Ladislav Mrnka
10
apa itu properti navigasi dan apa itu properti skalar?
Abid Ali
9
@AbidAli: Saya percaya properti navigasi adalah kunci asing (tipe kelas entitas) atau hubungan satu ke banyak (tipe ICollection <>). Properti skalar adalah tipe dasar (int, string, ..) atau ComplexType (yang hanya merupakan struct dari tipe dasar).
Scott Stafford
2
Apakah public virtual byte[] bigData { get; set; }malas memuat?
AechoLiu
9
byte [] akan dimuat dengan penuh semangat, hanya kunci asing yang bisa malas. Jika Anda tidak ingin mengambil kolom itu, jangan pernah mengambil seluruh catatan - adil .Select(a=>new { fields you want }).
Scott Stafford
63

Kata kunci virtual ini terkait dengan topik memuat data dari kerangka entitas (lazy loading, eager loading, dan eksplisit loading).

Anda harus menggunakan kata kunci virtual , ketika Anda ingin memuat data dengan pemuatan malas.

lazy loading adalah proses di mana suatu entitas atau kumpulan entitas secara otomatis diambil dari database saat pertama kali diakses.

Misalnya, saat menggunakan kelas entitas Blog yang ditentukan di bawah, Posting terkait akan dimuat saat pertama kali properti navigasi Tulisan diakses:

public class Blog 
{  
     public int BlogId { get; set; }  
     public string Name { get; set; }  
     public string Url { get; set; }  
     public string Tags { get; set; }  
     public virtual ICollection<Post> Posts { get; set; }  
}

Pemuatan malas dari koleksi Posting dapat dimatikan dengan membuat properti Posting non-virtual.

jika lazy loading tidak aktif, Memuat koleksi Posts masih dapat dicapai menggunakan eager loading (menggunakan metode Sertakan) atau secara eksplisit memuat entitas terkait (menggunakan metode Load).

Bersemangat memuat:

using (var context = new BloggingContext()) 
{ 
    // Load all blogs and related posts 
    var blogs1 = context.Blogs 
                          .Include(b => b.Posts) 
                          .ToList(); 
}

Memuat secara eksplisit:

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 

    // Load the posts related to a given blog 
    context.Entry(blog).Collection(p => p.Posts).Load(); 
}
Parsa
sumber
1
Bagaimana cara menghindari masalah N + 1 saat menggunakan virtual (lazy-loading)? Misalnya, context.Blogs.ToList (); maka itu tidak akan bergabung dengan tabel, dan itu akan menjalankan kueri pemilihan sebanyak jumlah blog.
Pakar ingin jadi
1
@Expertwannabe Bahkan jika Anda menggunakan lazy-loading, Anda masih dapat secara eksplisit meminta pemuatan yang cepat dengan sebuah panggilan Include().
Monsinyur