Visual Studio is busy asp.net mvc

335
20 июня 2017, 22:26

При добавлении записи в бд, из контролера возвращается PartialView, который должен просто выводить все объекты в html-список.

Но, если в таблице только 0 или 1 запись(если больше, то работает нормально), студия зависает с таким сообщением:

"Microsoft Visual Studio is busy."

И ладно бы это была ошибка, можно как то отладить, но пол дня потрачено только на поиски причин...

Модели:

public class Basket
{
    public int Id { get; set; }    
    public int? ProductId { get; set; }       
    public virtual Product Product { get; set; }       
}

public class Product
{
    public int Id { get; set; }
    public string Title { get; set; }              
}

Контроллер:

  public ActionResult AddProduct(int productId, int  count)
        {
            if (ModelState.IsValid )
            {
                var basket = new Basket();
                //....
                db.Baskets.Add(basket);
                db.SaveChanges();
                return PartialView(db.Baskets);
            }
        }

И после записи в бд, возвращаеться такое PartialView

 @model IEnumerable<ShopStore.Models.Basket>
    @foreach (var item in Model)
    {
        <li><a href="#">@item.Product.Title</a></li>
    }

Ошибка тут: item.Product.Title, если написать item.Id, то все работает хорошо, то есть ошибка похоже именно в загрузке Product, но что происходит "за кулисами" мне пока не известно. И снова же, почему при двух и более записях все работает....

Спасибо!

Answer 1

Ну, во-первых, ещё раз повторю:

Загрузка связанных данных в EF бывает трёх видов:

  • Отложенная загрузка (lazy loading)
  • Прямая загрузка данных (eager loading)
  • Явная загрузка (explicit loading)

Во-вторых, попробуем описать механику. Когда вы пишете запрос как db.Baskets у вас на сервер уйдёт один SQL-запрос вида SELECT * FROM basket. И всё. Допустим, этот одиночный запрос вернёт "всего лишь" 800 строк.

А когда вы дойдёте до выполнения view вы в цикле создадите ещё 800 запросов, но уже к таблице продуктов. Что-то вида SELECT * FROM product WHERE id = 1 (потом 2, 3 и так восемьсот раз). На небыстром ноутбуке можно увидеть хорошее слайдшоу и тормоза.

Я же в своём запросе попросил сразу подтянуть таблицу продуктов -- поэтому у меня SQL-запрос выполняется всего 1 раз, а не 801 раз.

var model = db.Baskets
    .Include(x => x.Product)
    .ToArray();

Запрос SQL мой будет примерно такого вида:

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[ID] AS [ID1], 
    [Extent2].[Name] AS [Name1], 
    FROM  [dbo].[Baskets] AS [Extent1]
    INNER JOIN [dbo].[Product] AS [Extent2] ON [Extent1].[???] = [Extent2].[???]

Ничего сверхъестественного, всего лишь один JOIN.

Механика понятна?

В-третьих, если вы отключите lazy loading вы (помимо того, что увидите кучу ошибок на своём проекте) сразу научитесь думать, какие запросы делает компьютер, насколько они оптимальны. Сейчас наверное выгоды от этого режима вам сложно оценить, но это очень хорошая практика.

READ ALSO
Сервер - Клиент. Рейтинг

Сервер - Клиент. Рейтинг

Подскажите, пожалуйста, как разумнее\правильнее изменять информацию в файлах на сервере с компьютера клиента?

222
Вывести документ Word формата html через WebBrowser

Вывести документ Word формата html через WebBrowser

Как через элемент WebBrowser вывести текстовый документ Word, сохраненный в формате HTML?

202
С помощью чего реализуется авторизация?

С помощью чего реализуется авторизация?

В реальных проектах на aspmvc для аутентификации-авторизации пользуются дефолтными провайдерами членства и ролей, или наследуются и пользуются...

199
Открыть картинку на другом экране

Открыть картинку на другом экране

Мне нужно сделать что бы при нажатии на одну из карточек, открывалась аватарка автора в новом экране (полный размер)А так же отображалось...

280