Как распараллелить запрос к базе данных с помощью ThreadPool? - PullRequest
2 голосов
/ 19 июля 2010

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

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents]");

// Copy the DataTable data to list.
foreach (DataRow dr in dt.Rows)
{
    ContentInfo aContentDetail = new ContentInfo(
            (int)dr["ID"],
            (string)dr["ContentName"],
            getCategories((int)dr["ID"]),
            null,
            (string)dr["Publisher"],
            (string)dr["Price"],
            false);

    contentInfoList.Add(aContentDetail); ;
}

private string getCategories(int ContentID)
{
    String categories = String.Empty;
    String query = String.Format("EXEC [dbo].[CMS_Content_GetContentCategories] @ID = {0}", ContentID);

    DataTable dt = clsGlobal.GetDataTable(query);

    foreach (DataRow dr in dt.Rows)
    {
        categories = String.Concat((string)dr["ShortDescription"] + ", ");                
    }

    if (categories.EndsWith(", "))
        categories = categories.TrimEnd(new char[] { ',', ' ' });

    return categories;
}

Это жалко, так как для DataTable dt более 1000 строк, и я не могу разобратьсяс этим из уровня хранимой процедуры!

Мне просто интересно, могу ли я связать вызов getCategories(int) в Threadpool.QueueUserWorkItem() так, чтобы он мог идти параллельно, но не знаю, как вернуть строку обратно вызывающей стороне?

Или это плохая идея использовать Threadpool, потому что я слышал, что рабочие потоки Threadpool не предназначены для длительных запросов, таких как вызовы БД, поскольку поток портов IOCompletion может не возвращаться вовремя, поэтому работники, скорее всего,быть заблокированным из-за этого?

Любая помощь приветствуется.

Ответы [ 2 ]

1 голос
/ 19 июля 2010

Боюсь, что многопоточность не является ответом в этом случае (включение или выключение пула потоков).Исправление 1000 звонков в базу данных есть.Вы можете оптимизировать скорость ответа для небольшого числа пользователей, но время отклика все равно будет довольно мучительным, и ваше приложение упадет при очень низкой нагрузке.

Я не знаю, насколько вы контролируете базу данных, поэтому вот несколько идей, которые охватывают несколько слоев:

  1. Извлечение категорий с помощью контентаВы можете либо создать функцию для разделения строк, либо использовать процедуру, которая возвращает несколько наборов данных за один вызов.
  2. Загрузка всех категорий одновременно и помещение данных в память
  3. Измените свой пользовательский интерфейс, чтобы не использовать одновременно 1000 элементов CMS.Пейджинг или что-то.

Удачи.

0 голосов
/ 19 июля 2010

Хотя, вопрос был ответом.Но это как раз то, что может помочь.

Вы можете «переместить» свой код в рабочий поток и запустить его.Вы также можете создать добавить событие, и как только поток завершит работу, он сообщит вам.Таким образом, вы можете продолжить (или переместить индикатор выполнения до конца, если он у вас есть?) С остальной частью вашей работы.

  1. Здесь - это способ работы с потоками.
  2. Это то, что я люблю , на сегодняшний день.

В качестве примечания, я считаю, что это можно сделать в SP (если вы можете поделиться запросом);поэтому я бы создал SP, который выбирает детали содержимого, и для каждого ContentDetailID я подготовил бы разделенный запятыми список категорий, а затем вернулся бы с моим результатом.

Итак, ваш вызов будет просто:

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents_Ex]");//Note the _EX in the sp name (0:
...