Очень низкая производительность ASP.NET MVC view - PullRequest
0 голосов
/ 12 сентября 2018

У меня проблема с приложением, которое я сделал для своей компании.Мы принимаем запросы из системы ERP.Люди могут искать статью, а затем приложение показывает им все соответствующие технические данные, изображения и / или таблицы данных.

Проблема в том, что она загружается очень медленно.Запросы, кажется, работают нормально, но генерация представления занимает много времени.

Это мой поисковый код (не обращайте внимания на нидерландские части):

public IQueryable<Item> GetItems(string vZoekString)
    {
        db.Configuration.LazyLoadingEnabled = false;

        //Split de ZoekString
        var searchTerms = vZoekString.ToLower().Split(null);

        // TODO: alles in een db query 
        //Resultaten oplijsten
        var term = searchTerms[0];
        var results = db.item_general.Where(c => c.ITEM.Contains(term) || c.DSCA.Contains(term));

        //Zoeken op alle zoektermen
        if (searchTerms.Length > 1)
        {
            for (int i = 0; i < searchTerms.Length; i++)
            {
                var tempTerm = searchTerms[i];
                results = results.Where(c => c.ITEM.Contains(tempTerm) || c.DSCA.Contains(tempTerm));
            }
        }

        //Show
        return results;

И затем эти результатывозвращаются к виду, как это:

public ActionResult SearchResults(string vZoekString, string filterValue, int? pageNo)
    {
        //Bewaking zoekstring
        if (vZoekString != null)
        {
            pageNo = 1;
        }
        else
        {
            vZoekString = filterValue;
        }

        //De zoekstring doorgeven
        if (vZoekString == null)
        {
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ViewBag.ZoekString = vZoekString;
        }

        //Ophalen Items via Business-Object
        //var vItems = new SearchItems().GetItems(vZoekString);
        SearchItems vSearchItems = new SearchItems();

        IQueryable<Item> vItems = vSearchItems.GetItems(vZoekString);

        //Nummering
        int pageSize = 10;
        int page = (pageNo ?? 1);

        //Show
        return View(vItems.OrderBy(x => x.ITEM).AsNoTracking().ToPagedList(page, pageSize));
    }

Что может быть не так в моей ситуации?Я что-то пропускаю?

ОБНОВЛЕНИЕ:

Я проверил свой код, и кажется, что все работает очень быстро, но на это уходит более 10 секунддостигает .ToPagedList().Так что я думаю, что с этим что-то не так.Я использую постраничный список от Nuget.

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

В большинстве случаев, когда вы сталкиваетесь с проблемами производительности с MVC и EF, это происходит из-за возврата сущностей в представления и утомленной отложенной загрузкой. Причина этого заключается в том, что когда ASP.Net предписывается отправить объект в браузер, он должен сериализовать его. Процесс сериализации перебирает объект, который касается прокси-серверов с отложенной загрузкой, вызывая загрузку этих связанных объектов по одному.

Вы можете обнаружить это, запустив профилировщик для вашей базы данных, установить точку останова до конца действия, а затем посмотреть, какие запросы выполняются при возврате вызова действия. Ленивая загрузка из-за сериализации будет отображаться в виде нескольких отдельных (TOP 1) запросов, выполняемых в быстрой последовательности после завершения действия до отображения страницы.

Самое простое предложение избежать этой боли - не возвращать сущности из контроллеров.

IQueryable<Item> vItems = vSearchItems.GetItems(vZoekString);
var viewModels = vItems.OrderBy(x => x.ITEM)
    .Select(x => new ItemViewModel
    {
       ItemId = x.ItemId,
       // .. Continue populating view model. If model contains a hierarchy of data, map those to related view models as well.
    }).ToPagedList(page, pageSize);

return View(viewModels);

Преимущество такого подхода:

  1. .Select() приведет к запросу, который извлекает только те данные, которые вам действительно нужны для заполнения моделей представлений. (Данные, которые нужны вашему просмотру) Более быстрый запрос, меньше данных по проводам между сервером БД -> Сервер приложений -> Браузер
  2. Это не приводит к ленивым нагрузкам.

Предостережение этого подхода:

  1. Необходимо позаботиться о том, чтобы выражение .Select() перешло в SQL, поэтому нет .Net или частных функций для таких вещей, как перевод / форматирование данных. Заполните необработанные значения в модели представления, а затем откройте свойства модели представления, чтобы выполнить перевод, который будет сериализовать эти отформатированные данные клиенту. Базовые вещи, такие как FullName = x.FirstName + " " + x.LastName - это хорошо, но избегайте таких вещей, как OrderDate = DateTime.Parse(x.DateAsISO), если в БД хранятся даты в виде строк.

Вы можете использовать сопоставители, такие как Automapper, чтобы помочь в сопоставлении между Entity и ViewModel. При условии, что картографический инструмент проверяет / пересекает место назначения для заполнения, а не источник, вы должны быть хорошими. Automapper поддерживает интеграцию в IQueryable, поэтому было бы целесообразно изучить, если вы хотите использовать картограф.

0 голосов
/ 12 сентября 2018

Хотя я не могу оценить ваш код представления, не видя его, проблема вполне может быть в запросе базы данных. IQueryable на самом деле ничего не загружает из базы данных, пока вы не используете результаты. Таким образом, запрос к базе данных будет выполняться только после запуска кода View.

Попробуйте изменить вид вызова на:

var items = vItems.OrderBy(x => x.ITEM).AsNoTracking().ToPagedList(page, pageSize);
return View(items);

А затем проверьте, является ли представление все еще узким местом.

(Это, вероятно, комментарий, но у меня нет репутации ....)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...