Я написал сайт 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 для бегущего часы:
Одна важная вещь - я НЕ МОЖЕТ создавать представления и хранимые процедуры в базе данных, так как я не разрешается. Я должен выполнить каждый запрос и т. Д. В моем коде.
Я знаю, что программа написана дилетантской, но именно поэтому я должен срочно ее изменить.
[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?
- клиент отправляет запрос на сервер сервера записывает запись в таблицу «работы» в БД
- после отправки запроса клиент получает JOB_ID из БД немедленно
- с этим идентификатором клиент может сделать AJAX вызовы для прогресса (статус)
- вебсервис проверяет каждый второй, если есть новая работа с статусом -1 в БД
- для каждого у О.Б. со статусом -1 создать новую задачу
- в этой задаче метод ReportMaker.GenerateReport (idAUFTRAG) будет называется
- ReportMaker имеет ReportProgress события
- звонящие (Task) присоединяется к этому событию и записывает каждый перейти в базы данных издания
- DB Accessor -> Task
- клиента выполняет Ajax звонки назад
Это приведет к увеличению производительности определенно !!! Звучит ли это слишком много работы для такого маленького проекта?
Если результаты «другого запроса» не слишком велики, когда они выполняются без их квалификации с текущими значениями ItemToQuery, вы можете попробовать их кешировать и просто фильтровать их внутри цикла. –
Какие еще вопросы? Почему вы должны делать их для каждого элемента вместо создания отношений и загрузки всего в одном запросе, например, с предложением 'Include'? –
Кроме того, * отчетные * запросы относятся к наборам данных, а не к отдельным объектам. EF ничего не предлагает по этому поводу Dapper. Единственным жизнеспособным способом является создание запросов, которые загружают каждый набор данных одновременно, а не загружают элементы один за другим. Они требуют правильной схемы и обычно нуждаются в просмотрах, чтобы скрыть сложные запросы. –