Member 11040029 Ответов: 2

Ленивая загрузка недопустимое поведение при использовании tolist() или load()


Я учусь эф. Во время практики я заметил странное поведение при ленивой загрузке.

Я читал, что ленивая загрузка включена по умолчанию и может работать только в том случае, если свойства навигации помечены как виртуальные вместе с LazyLoadingEnabled = ture в конфигурации контекста.
Поэтому я решил отключить ленивую загрузку, установив переключатель в положение off, то есть LazyLoadingEnabled = false.

Вот код, который пытался получить доступ к dbset после этого:
if (context == null)
         context = new InventoryEntities(".");
     context.Configuration.LazyLoadingEnabled = false;
     List<STOCK_ITEM_GROUPS> res = (from groups in context.STOCK_ITEM_GROUPS
                                  orderby groups.name
                                  select groups).ToList<STOCK_ITEM_GROUPS>();           
           string msg = "";
           foreach (var groups in res)
               msg += "Name: " + groups.name + "\tParent Name: " +                 (groups.STOCK_ITEM_GROUPS2 == null ? "none" : groups.STOCK_ITEM_GROUPS2.name) + Environment.NewLine;
              
           Console.WriteLine(msg);


Ниже приведен dbset, сгенерированный для STOCK_ITEM_GROUPS:
public partial class STOCK_ITEM_GROUPS
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public STOCK_ITEM_GROUPS()
        {
            this.STOCK_ITEM_GROUPS1 = new HashSet<STOCK_ITEM_GROUPS>();
            this.STOCK_ITEM_MASTER = new HashSet<STOCK_ITEM_MASTER>();
        }
    
        public short id { get; set; }
        public string name { get; set; }
        public Nullable<short> idParent { get; set; }
        public bool itemAddable { get; set; }
        public bool isactive { get; set; }
        public System.DateTime active_timestamp { get; set; }
        public Nullable<System.DateTime> deactivation_timestamp { get; set; }
        public byte[] rv { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<STOCK_ITEM_GROUPS> STOCK_ITEM_GROUPS1 { get; set; }
        public virtual STOCK_ITEM_GROUPS STOCK_ITEM_GROUPS2 { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<STOCK_ITEM_MASTER> STOCK_ITEM_MASTER { get; set; }
    }


Теперь, в идеале, я не должен получать данные для навигационного свойства
public virtual STOCK_ITEM_GROUPS STOCK_ITEM_GROUPS2 { get; set; }
, так как ленивая загрузка не включена. Но я получаю соответствующие данные!
Я также попытался отключить ленивую загрузку в конструкторе контекста, но безрезультатно.

Возможно, я упускаю какую-то концептуальную вещь или есть что-то еще, чего я действительно не знаю.
Глядя на отладчик для генерируемых запросов, я нахожу только один запрос, который ищет все данные из базы данных.
таким образом, существует не только несколько запросов, но и связанные с ними данные. Я не понимаю, где я ошибаюсь.

Что я уже пробовал:

Я попробовал то же самое с методом Load() на DbSet, он также возвращает тот же результат, что и toList ().
Поискал в google, но нашел только 1 комментарий, который на самом деле не является тем состоянием, в котором я нахожусь, вот ссылка для этого:
c# - Entity Framework - ленивая загрузка, работающая даже с ToList() - переполнение стека[^]

2 Ответов

Рейтинг:
2

F-ES Sitecore

Отключение ленивой загрузки не останавливает загрузку связанных данных, оно останавливает их загрузку по требованию, поэтому вместо этого они загружаются сразу. Возможно, вам лучше использовать функцию "Включить", чтобы диктовать, какие данные загружаются лениво или нет в каждом конкретном случае. Это сделает его явным, что лениво загружается, а что нет.


Member 11040029

Я не уверен в вашем ответе f-ES, он звучит совершенно противоположно тому, что я узнал из книг и интернета. Diabling lazy loading вообще не загружает связанные данные. Должно быть, так оно и есть. Использование Include - это явная загрузка, которую можно выполнить. Это его выбор.
И, если отключение ленивой загрузки не остановит загрузку связанных данных, то вы столкнетесь с чертовски большой проблемой всего с тысячью записей со связанными данными во многих таблицах для ежедневных транзакций, скажем. Я уверен, что ребята из MS держали это в уме при построении фреймворка.
Мне очень жаль, но первое предложение, которое вы упомянули, полностью противоречит концепции загрузки связанных данных.
Если связанные данные загружаются каждый раз, несмотря на отключение ленивой загрузки, то представьте себе, что произойдет. Я думаю, что от эф будет мало пользы.

Пожалуйста, поправьте меня, если я неправильно понял ваш ответ?

F-ES Sitecore

Я сказал, что отключение ленивой загрузки останавливает загрузку данных по требованию и вместо этого загружает данные сразу. С ленивой загрузкой

покупатель.Firstname - > используются только данные клиента, другие данные не загружаются
покупатель.Заказы.First (). OrderNumber - > В этот момент загружаются данные ордеров

Без ленивой загрузки

покупатель.Firstname - > Данные заказов уже загружены и могут быть использованы, если вы используете их или нет
покупатель.Заказы.First (). OrderNumber- & gt; коллекция ордеров уже заполнена, поэтому здесь нет доступа к БД

Member 11040029

(покупатель.Firstname - > используются только данные клиента, другие данные не загружаются)..именно это я и пытаюсь сказать..Только на этом этапе, во время отладки, я нашел (customer.Заказы.Данные First (). OrderNumber) тоже загружаются!

F-ES Sitecore

Когда вы получаете доступ к этим свойствам для отладки, они загружаются EF. Доступ к данным для отладки ничем не отличается от доступа к ним в вашем коде. Чтобы отладить то, что делает EF, вы должны использовать SQL Profiler. Это покажет вам, когда EF делает запросы к БД и что он запрашивает.

Richard Deeming

Эта страница MSDN[^] кажется, это противоречит вашему ответу.

"Ленивая загрузка может быть отключена для всех сущностей в контексте, установив флаг в свойстве конфигурации. ... Загрузка связанных сущностей все еще может быть достигнута с помощью eager loading (см. Eagerly Loading выше) или метода Load (см. явно Loading ниже)."

Это говорит о том, что EF только охотно загружает связанные данные, когда вы используете Include метод; в противном случае коллекции свойств навигации должны оставаться пустыми.

Рейтинг:
19

Richard Deeming

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

Я не могу найти эквивалентную документацию для EF6, но в основной документации EF есть примечание, которое объясняет это поведение:

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

Если вы посмотрите на STOCK_ITEM_MASTER вместо этого коллекция не должна загружаться автоматически.


Member 11040029

Именно Ричард! вот что происходит. Thnx для этого.
И я нажимал на 5-й старт, случайно нажал на 4-й..извините :)