Какой эффект (ы) может оказать ключевое слово virtual в Entity Framework 4.1 POCO Code First?

#entity-framework-4 #ef-code-first #entity-framework-4.1

#entity-framework-4 #ef-code-first #entity-framework-4.1

Вопрос:

Оказывает ли virtual ключевое слово какой-либо эффект при использовании в свойствах в EF Code First?. Может ли кто-нибудь описать все его последствия в различных ситуациях?

Например, я знаю, что оно может контролировать отложенную загрузку — если вы используете ключевое слово virtual в свойстве ICollection / отношения «один ко многим», оно будет загружено с задержкой по умолчанию, тогда как если вы не используете ключевое слово virtual, оно будет загружено с нетерпением.

Какие еще эффекты может virtual иметь ключевое слово в EF с объектами POCO?. Должен ли я сделать его используемым по умолчанию virtual для всех моих свойств или по умолчанию его не использовать?

Ответ №1:

Пока что я знаю об этих эффектах.

  • Отложенная загрузка: любые virtual ICollections будут загружаться отложенно, если вы специально не пометите их иначе.
  • Более эффективное отслеживание изменений. Если вы удовлетворяете всем следующим требованиям, то для отслеживания изменений можно использовать более эффективный метод путем привязки ваших виртуальных свойств. По ссылке:

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

Еще одна полезная ссылка, описывающая это, — это требования MSDN к созданию прокси-серверов POCO.

Комментарии:

1. Нет другой причины делать свойства виртуальными. Свойства навигации помечены как виртуальные для отложенной загрузки, а скалярные свойства — как виртуальные для отслеживания изменений.

2. что такое навигационные свойства и что такое скалярные свойства?

3. @AbidAli: Я полагаю, что свойство навигации — это внешний ключ (тип класса сущности) или отношение «один ко многим» (типа ICollection<>). Скалярное свойство — это базовый тип (int, string, ..) или complexType (который является просто структурой базовых типов).

4. Является ли » public virtual byte[] bigData { get; set; } » отложенной загрузкой?

5. байты [] будут загружены быстро, только внешние ключи могут быть отложены. Если вы не хотите извлекать этот столбец, никогда не извлекайте всю запись целиком — просто .Select(a=>new { fields you want }) .

Ответ №2:

Это виртуальное ключевое слово связано с темой загрузки данных из entity framework (отложенная загрузка, быстрая загрузка и явная загрузка).

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

отложенная загрузка — это процесс, при котором объект или коллекция объектов автоматически загружается из базы данных при первом обращении к ней.

Например, при использовании класса сущности Blog, определенного ниже, связанные записи будут загружены при первом обращении к свойству навигации Posts:

 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 можно отключить, сделав свойство Posts невиртуальным.

если отложенная загрузка отключена, загрузка коллекции Posts все еще может быть достигнута с помощью быстрой загрузки (используя метод Include) или явной загрузки связанных объектов (используя метод 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 при использовании virtual (отложенная загрузка)? Например, контекст. Блоги. ToList(); тогда он не будет объединять таблицы, а будет выполнять запрос select столько, сколько блогов.

2. @Expertwannabe Даже если вы используете отложенную загрузку, вы все равно можете явно запросить ускоренную загрузку с помощью вызова Include() .