Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с БД в отдельном треде. [D7, XP]


Страницы:   1 2 3 4

Alex_C ©   (2012-03-11 11:52:00) 

В продолжении темы о необходимости нескольких ADOConnection, если работа с базой происходит в отдельном треде.
Вот есть какая проблема.
Дано ADO+Access.
Есть ClientDataSet - база клиентов фирмы.
Есть SpravDataSet - общий справочник жителей города N.
После того, как в ClientDataSet вносится новый клиент нужно в справочной базе SpravDataSet проверить, есть ли такой человек, если есть - отметить, что он теперь клиент фирмы.
Делаем это на событие AfterPost для ClientDataSet.
Дабы не происходило зависания программы при поиске соответствующей записи в базе справочника SpravDataSet , было принято решение работу с ним вынести в отдельный тред.
В отдельном треде создаем свой ADOConnection и ADODataSet для соединения с базой справочника. Делаем необходимые корректировки в базе - тут все ок, корректировки проходят как надо.
Теперь нам нужно обновить содержание окна, которое содержит таблицу со SpravDataSet . Для этого перед завершением работы треда вызываем метод Synchronize, в котором делаем  

SpravDataSet.CommandText := 'SELECT * FROM...'
SpravDataSet.Active := True;

И видим, что у нас отображаются "старые" данные по справочнику, без учета внесенных в треде изменений.
Если же затем мы вручную, по кнопке выполним код

SpravDataSet.CommandText := 'SELECT * FROM...'
SpravDataSet.Active := True;

то видим, что все изменения внеслись.
Вопрос: как сделать так, чтоб изменения были видны из метода Synchronize?


Alex_C   (2012-03-12 14:40:00) [21]

Хорошо. Согласен. Задача достаточно сложна, чтоб понять ее, не зная тем более всех исходных данных.
Ок! разделим ее на простые и понятные части.

Основная цель: максимально возможно избежать тормозов у основного потока программы.

Часть 1. Получение спотов с интернета и занесение их в таблицу Access, с последующих показом их пользователю.

Справочная информация:
Что такое спот: это текстовые данные, содержащие информацию о работающих сейчас в эфире станциях.
Один спот содержит:
- позывной станции
- частоту
- время занесения спота на сервер спотов
- доп. инфо.
При занесении спотов в таблицу Access программы следует избегать занесения повторных спотов. Спот считается повторным, если позывной и частота в нем совпадают.
Идеология занесения спотов такая:
- если такой спот не существует - заносим его.
- если существует - проверяем время спота. Если оно больше - делаем UPDATE доп. инфо, если оно меньше - спот старый, не заносим его в базу.

Как я делал:
- в отдельном треде получал споты (их может быть от 1 до 1000)
- парсил
- ... теперь вопрос: хотелось бы и в базу заносить споты в отдельном треде, с использованием отдельного ADOConnect. Но при этом возникают проблемы при отображении принятых спотов в основном треде. Проблема заключаются в том, что споты реально на диск в саму Access-базу заносятся через 5 сек (информация взята из интернета.) Майкрософт в принципе написал как обходить это:

 JE := (CreateOleObject('JRO.JetEngine') as JetEngine);
 try
   JE.RefreshCache(FDataBaseConnection.ConnectionObject as ADODB_TLB._Connection);
 finally
   JE := nil;
 end;

Однако по какой то причине у меня это не сработало.

Почему я хочу заносить споты в отдельном треде, а не делать это допустим в методе Synchronize треда получения данных с инета: в некоторых случаях споты идут практически беспрерывно, очень сильно замедляя работу основного треда.
Вот первая часть моей задачи.


RWolf   (2012-03-12 10:40:00) [22]

прозреваю, что имеется в виду не тот индекс, что в БД, а просто некий спецтермин из предметной области.


Anatoly Podgoretsky   (2012-03-12 10:04:00) [23]

Задача придумана, чтобы не работать, на что только человек не пойдет ради данной цели.


sniknik   (2012-03-12 09:58:00) [24]

> Это чрезвычайно сложная и длительная задача, которая к тому же требует несколько запросов.
вообще у меня подозрение, что он так и не отказался от "идеи" каждая таблица в своей базе...
а гетерогенные запросы так и не освоил.


sniknik   (2012-03-12 09:55:00) [25]

> Я описывал выше индекс нужности:
твои слова несут глубокий, НУЛЕВОЙ смысл происходящего, противореча сами себе.

>> есть ли такая страна в основной базе, есть ли такая страна
>> на таком диапазоне, виде модуляции, подтверждена. Если подтверждена,
>>  то способ подтверждения
= простая выборка с условием в диапазоне, если есть то возврат способа подтверждения (что бы это ни значило).
ничего не стоит вставить ее же в условие апдейта (т.е. как уже говорилось > "максимум в пару запросов все решается." пока сказанное этому не противоречит).

и тут же -
>> - индекс достаточно сложный и одним
>> SQL-запросом его получить нельзя
??? что за бред?


Anatoly Podgoretsky   (2012-03-12 09:53:00) [26]

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


Alex_C   (2012-03-12 09:33:00) [27]


> динамически расчитывается хоть каждую миниту


Раньше я его динамически расчитывал при отрисовке таблицы. Но тогда я отдельно хранил статистику по каждой сработанной стране отдельно и естественно все расчитывалось практически мгновенно.
Если сейчас расчитывать индекс нужности для каждой станции из основной базы - получается задержка при отрисовке.


> он так сложен в расчете


Я описывал выше индекс нужности:

> есть ли такая страна в основной базе, есть ли такая страна
> на таком диапазоне, виде модуляции, подтверждена. Если подтверждена,
>  то способ подтверждения - индекс достаточно сложный и одним
> SQL-запросом его получить нельзя


Inovet   (2012-03-11 23:29:00) [28]

> [38] знайка   (11.03.12 23:20)
> А что такое индекс нужности и зачем его в базе держать (явно)
> ? он так сложен в расчете?

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


знайка   (2012-03-11 23:20:00) [29]

А что такое индекс нужности и зачем его в базе держать (явно)? он так сложен в расчете?


sniknik   (2012-03-11 23:00:00) [30]

посмотри историю
http://www.delphimaster.ru/cgi-bin/forum.pl?n=1&user=Alex_C
у тебя до сих пор одни и те же проблемы, а там тебе на разные голоса твердили "так делать нельзя", ты же при внешнем "да да я слушаю и все все учитываю",  внутренне ничего не поменял/не усвоил "мне нужно именно так, а не иначе, у меня ТЗ. логика такая... сам придумал". приехали. сейчас ты на том же уровне что тогда, уже правда немного обучен "шаманским трюкам", но знания/понимания как не было так и нет.


sniknik   (2012-03-11 22:06:00) [31]

> Думаю, после этого подробного объяснения мой приведенный выше код стал более понятным.
ценность этого пояснения для понимания = 0 целых х...рен десятых. тут же вообще НИЧЕГО кроме слов.

тем более словам даны собственные значения (???)...
> Из интернета скачиваем базу
вот прямо таки базу? с таблицами, индексами и т.д... тогда скачивай только данные, и тут же все ускорится...

> Там же ее парсим
базы, и даже таблицы не парсят, это структурированные данные. парсят текст.  

> высчитываем индекс нужности
ну прямо офигеть как все понятно стало, это же известный и везде изучаемый алгоритм... известнее пузырька. (сарказм, как и во всем этом посе в принципе)

> индекс достаточно сложный и одним SQL-запросом его получить нельзя
индекс вообще то сам по себе, его запросом не получают, его запросы используют. для ускорения обработки данных по условию.

> которая называется база спотов.
опять база? не таблица? и опять очень понятно стало только от названия... нет с большой буквы надо "Названия". а вот как это делается, это конечно неважно, и даже вредно. т.к. может позволить оспорить необходимость заявленного...

> Но это еще не все.
а все... не надо больше... нафиг. "глушняк" это. не выберешься ты из ламеризма с таким подходом.


Alex_C   (2012-03-11 21:36:00) [32]


> а сколько еще скрыто в "запасниках"...
>


Хорошо. Приведу максимально полное описание проблемы.
Есть основная база (50-200тыс записей) проведенных радиосвязей.
Из интернета скачиваем базу сейчас работающих в эфире станций. Количество записей в ней от 1 до 1000.
Естественно делаем это в отдельном треде. Там же ее парсим, для каждой станции высчитываем индекс нужности (есть ли такая страна в основной базе, есть ли такая страна на таком диапазоне, виде модуляции, подтверждена. Если подтверждена, то способ подтверждения - индекс достаточно сложный и одним SQL-запросом его получить нельзя). И в этом же треде заносим полученные данные в базу данных, которая называется база спотов. Теперь эту базу нам нужно отобразить. Думаю в данном случае необходимость отдельного треда очевидна?
Но это еще не все. При изменении основной базы, в базе спотов необходимо пересчитывать индексы нужности.
Пример: в базе спотов у нас присутствует информация о 100 работающих станциях из USA. Мы в основную базу занесли новую связь с USA. Теперь для каждой записи в базе спотов нам необходимо пересчитать индекс нужности. А если мы пакетом добавили 100 связей в основную базу? Но естественно интекс нужности пересчитывать нужно для всех записей. И при этом основная программа не должна тормозиться.
Думаю, после этого подробного объяснения мой приведенный выше код стал более понятным.


Ega23   (2012-03-11 17:20:00) [33]


> внедряем асинхронность и событийность... потоки тут тоже
> в последнюю очередь.


Ну тут спорный вопрос. Можно по-разному извратиться. Но от DB-Aware отказаться придётся с большой долей вероятности.
А многие не хотят. Хотят и штоб DBGrid-ы мастре-детальные, и штоб событийность и асинхронность.


Anatoly Podgoretsky   (2012-03-11 17:00:00) [34]

> Alex_C  (11.03.2012 15:59:21)  [21]

Ну так никакого сервера нет и в помине.


sniknik   (2012-03-11 16:30:00) [35]

> но как тест
это в общем то пример, отличия "описательной" части от реальной, и чем может помочь "кивание" на рекомендации - http://delphi.about.com/od/kbthread/a/query_threading.htm
а сколько еще скрыто в "запасниках"...

> 2. Двухзвенка. Тут вариант простой: нужно ли нам залипание гуя во время длительных операций? Нужно -
внедряем асинхронность и событийность... потоки тут тоже в последнюю очередь.


Сергей М.   (2012-03-11 16:28:00) [36]


> имя его должно быть типа SpisokClientDataSet: TADODataSet.
>  Неудачное название для примера подобрал


Да не суть важно какое у него название.

Важно что это подчиненный НД.


Ega23   (2012-03-11 16:28:00) [37]

Зачем нужна многопоточность в БД-приложении:
1. Пишем сервер приложений. Например - бэкенд за http-сервером. Надеюсь, тут объяснять не нужно.
2. Двухзвенка. Тут вариант простой: нужно ли нам залипание гуя во время длительных операций? Нужно - внедряем. Так сойдёт - не внедряем. В каких случаях залипание нежелательно? Ну, например, формируем некий офигенный отчёт. Когда snapshot-транзакция и пошло-поехало. Или длительный поиск по Full-Text Search индексу. Больше, честно говоря, не могу придумать.

А вот сборная солянка, когда что-то в основном потоке, что-то в отдельном - это скорее какая-то фигня в архитектуре. Либо всё, либо ничего (не считая этих самых отчётов и поисков).


sniknik   (2012-03-11 16:23:00) [38]

> ilCursorStability установлены.
пофигу. но как тест, где? код твой приведен выше, создание компонент динамическое, где присваивается ilCursorStability?


знайка   (2012-03-11 16:21:00) [39]


> Для каждой выбранной из SpotTable записи необходимо проверить/изменить
> ее статус.
Одним запросом это никак?


RWolf   (2012-03-11 16:21:00) [40]

моё мнение — надо исключить цикл с апдейтами, перестроив логику программы соответствующим образом.
и вообще, модификация результатов агрегатного запроса выглядит как-то подозрительно.


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо