2015-06-17 2 views
0

Я написал сайт asp.net, который используется для создания отчетов (в Excel), полный указанных элементов. Я получаю эти элементы из базы данных SQL через EF. Query отлично работает и требует около 2000 предметов около 1 мс.нужен способ повышения производительности в коде aspx за

var itemsToQuery = (from i in context.item 
    where ...... 
    ..... 
    ..... 
    orderby ....... 
    select new 
    { 
    fields..... 
}); 

Теперь мне сложно. Элемент Foreach я должен запрашивать дополнительные данные из БД (нет возможности получить эти данные с первым запросом). Я использую только одно соединение БД в безопасное время (для основного запроса и любого другого запроса в методе). Я думаю, что моя проблема с работой начинается здесь. У меня 2000 элементов, и следующий цикл выглядит так:

foreach(var item in itemsToQuery) 
{ 
     another query; 
     another query; 
     another query; 
     etc..... 
     // at the end it looks like 
     datatable.add(item.name, item.number, item.stuff ......); 
} 

Так что я делаю для каждого из этих 2000 предметов еще 8 запросов. Этот foreach занимает около 5 минут (в зависимости от количества предметов). Впоследствии мне нужен этот DataTable для заполнения листа Excel. Это прекрасно работает и «быстро».

Можете ли вы дать мне несколько советов экспертов, как сделать этот цикл, запросы или заполнение DataTable более результативными?

Я думал об обходном пути с многозадачностью и создании сайта, на котором вы можете увидеть статус excel (через вызовы ajax), и когда все будет готово, вы можете скачать его. Теперь я просто блокирую пользовательский интерфейс этого сайта, и пользователь должен сидеть перед экраном, пока это не будет сделано без какой-либо информации, как долго он должен ждать. Пример экрана с GIF и JS для бегущего часы:

graphic while blocking ui

Одна важная вещь - я НЕ МОЖЕТ создавать представления и хранимые процедуры в базе данных, так как я не разрешается. Я должен выполнить каждый запрос и т. Д. В моем коде.

Я знаю, что программа написана дилетантской, но именно поэтому я должен срочно ее изменить.

[EDIT]

Вот примеры запросов о которых я говорил! Только для информации - я не писал каждый запрос. Некоторые из них (например, owner или monthlyWorkTime) - это внешний ресурс.

String changeDate = CalcÄnderungsDat(context 
        .ticket_history 
        .FirstOrDefault(x => x.history_type_id == 25 && x.ticket_id == item.ticketID).change_time.ToString()); 




String finishdate = CalcFinishDat((from tih in context.ticket_history 
         where (tih.name == "Reset of unlock time." && tih.ticket_id == item.ticketID) 
         || (tih.state_id == 2 && tih.history_type_id == 1 && tih.ticket_id == item.ticketID) 
         select tih.change_time).Max().ToString()); 


try 
{ 
    string owner= (from a in context.article 
       where 
       item.ticketID == a.ticket_id && 
       a.id == 
       (from art in context.article 
       where art.a_subject.Contains("esitzer") 
       && art.ticket.id == item.ticketID 
       && art.ticket_id == art.ticket.id 
       select new { art.id }).Max(p => p.id) 
       select new { a.a_from }).FirstOrDefault().a_from; 
} 
catch (Exception) 
{ 
string owner = (from a in context.article 
       where a.ticket.id == item.ticketID && a.ticket_id == a.ticket.id && 
       a.id == 
       (from art in context.article 
       where art.ticket.id == item.ticketID 
       && art.ticket_id == art.ticket.id 
       select new { art.id }).Min(p => p.id) 
       select new { a.a_from }).FirstOrDefault().a_from; 
} 

decimal? monatszeit = (from ta in context.time_accounting 
         where 
         ta.change_time >= startdat && 
         ta.change_time <= enddat && 
         ta.ticket_id == item.ticketID 
         group new { ta } by new 
         { 
         ta.ticket_id, 
         ta.ticket.id, 
         ta.ticket.tn 
         } into g 
         select new 
         { 
          Zeiteinheit = (Decimal?)g.Sum(p => p.ta.time_unit), 
         }).SingleOrDefault().Zeiteinheit; 

И так далее. В целом есть 7 запросов и 1 внешний метод для вычисления специальной даты (этот метод не должен быть проблемой) для каждого элемента из основного запроса. Как я могу поместить их в ОДИН полный запрос? Будет ли это увеличивать мою работу?

[EDIT - ДРУГОЙ TRY]

Что вы скажете об этом Flowchart? enter image description here

  • клиент отправляет запрос на сервер сервера записывает запись в таблицу «работы» в БД
  • после отправки запроса клиент получает JOB_ID из БД немедленно
  • с этим идентификатором клиент может сделать AJAX вызовы для прогресса (статус)
  • вебсервис проверяет каждый второй, если есть новая работа с статусом -1 в БД
  • для каждого у О.Б. со статусом -1 создать новую задачу
  • в этой задаче метод ReportMaker.GenerateReport (idAUFTRAG) будет называется
  • ReportMaker имеет ReportProgress события
  • звонящие (Task) присоединяется к этому событию и записывает каждый перейти в базы данных издания
  • DB Accessor -> Task
  • клиента выполняет Ajax звонки назад

Это приведет к увеличению производительности определенно !!! Звучит ли это слишком много работы для такого маленького проекта?

+0

Если результаты «другого запроса» не слишком велики, когда они выполняются без их квалификации с текущими значениями ItemToQuery, вы можете попробовать их кешировать и просто фильтровать их внутри цикла. –

+1

Какие еще вопросы? Почему вы должны делать их для каждого элемента вместо создания отношений и загрузки всего в одном запросе, например, с предложением 'Include'? –

+0

Кроме того, * отчетные * запросы относятся к наборам данных, а не к отдельным объектам. EF ничего не предлагает по этому поводу Dapper. Единственным жизнеспособным способом является создание запросов, которые загружают каждый набор данных одновременно, а не загружают элементы один за другим. Они требуют правильной схемы и обычно нуждаются в просмотрах, чтобы скрыть сложные запросы. –

ответ

0

Вы можете подумать о создании решения для кеша для уже полученных данных. Таким образом, результаты запроса будут сохранены в памяти, и они не будут извлекаться каждый раз, так что производительность значительно возрастет.

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

Смежные вопросы