Який (-и) ефект (-и) можуть мати віртуальне ключове слово в Entity Framework 4.1 Перш за все POCO Code?


229

Чи virtualмає ключове слово вплив при використанні властивостей у коді EF? Чи може хтось описати всі його наслідки в різних ситуаціях?

Наприклад, я знаю, що це може керувати ледачим завантаженням - якщо ви використовуєте віртуальне ключове слово на властивості ICollection / one-to-many Relations, воно за замовчуванням буде ледаче завантажене, тоді як якщо ви залишите віртуальне ключове слово поза, воно буде бути нетерплячим.

Які ще ефекти можуть virtualмати ключові слова в EF з суб'єктами POCO ?. Чи варто зробити його за замовчуванням використовувати virtualдля всіх моїх властивостей, або за замовчуванням не використовувати його?

Відповіді:


194

Поки що я знаю про ці наслідки.

  • Ледаче завантаження : Будь-які virtualICollections будуть ледачими, якщо ви спеціально не позначаєте їх.
  • Більш ефективне відстеження змін . Якщо ви відповідаєте всім наведеним нижче вимогам, то для відстеження змін можна використовувати більш ефективний метод, підключивши свої віртуальні властивості. За посиланням:

    Щоб отримати проксі-сервери відстеження змін, основним правилом є те, що ваш клас повинен бути відкритим, неабразованим або не запечатаним. Ваш клас також повинен впроваджувати загальнодоступні віртуальні геттери / сетери для всіх ресурсів, що зберігаються. Нарешті, ви повинні оголосити властивості навігації на основі колекції ICollection<T>лише як . Вони не можуть бути конкретною реалізацією чи іншим інтерфейсом, який походить від ICollection<T>(відмінність від проксі-сервера відкладеного завантаження)

Ще одне корисне посилання, що описує це - вимоги MSDN до створення проксі-серверів POCO .


52
Немає іншої причини зробити властивості віртуальними. Навігаційні властивості позначаються як віртуальні для ледачого завантаження, а скалярні властивості позначаються як віртуальні для відстеження змін.
Ladislav Mrnka

10
що таке властивості навігації та які скалярні властивості?
Абід Алі

9
@AbidAli: Я вважаю, що властивість навігації - це зовнішній ключ (тип класу сутності) або співвідношення один до багатьох (типу ICollection <>). Скалярна властивість - це базовий тип (int, string, ..) або ComplexType (який є лише структурою базових типів).
Скотт Стаффорд

2
Чи public virtual byte[] bigData { get; set; }ліниве завантаження?
AechoLiu

9
байти [] будуть нетерпляче завантажені, лише сторонні ключі можуть лінуватися. Якщо ви не хочете отримати цей стовпець, ніколи не отримуйте весь запис - просто .Select(a=>new { fields you want }).
Скотт Стаффорд

63

Це віртуальне ключове слово пов'язане з темою завантаження даних із фреймворку сутності (ледаче завантаження, прагнення завантаження та явне завантаження).

Ви повинні використовувати віртуальне ключове слово, коли ви хочете завантажити дані з ледачим завантаженням.

ледаче завантаження - це процес, при якому суб'єкт або колекція сутностей автоматично завантажується з бази даних при першому зверненні до нього.

Наприклад, при використанні визначеного нижче класу сутності блогу відповідні повідомлення будуть завантажуватися при першому доступі до властивості навігації Повідомлення:

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

Ледаче завантаження колекції повідомлень можна відключити, зробивши властивість Posts невіртуальною.

якщо завантаження ледачих вимкнено, завантаження колекції повідомлень все ще можна досягти, використовуючи прагнення до завантаження (використовуючи метод Включити) або явно завантажуючи пов'язані сутності (використовуючи метод Load).

З нетерпінням завантажуємо:

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

Явно завантажується:

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

1
Як уникнути проблеми N + 1 при використанні віртуальної (ледача завантаження)? Наприклад, context.Blogs.ToList (); тоді він не приєднається до таблиць, і він виконає запит вибору стільки, скільки кількість блогів.
Експерт хоче бути

1
@Expertwannabe Навіть якщо ви користуєтеся ледачим завантаженням, ви все одно можете попросити невдовзі завантажуватись із закликом до Include().
Монсеньйор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.