Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: ADOConnection1.Connected := false - влияние на грид использующий TQuery  (Прочитано 11304 раз)
0 Пользователей и 1 Гость смотрят эту тему.
malor
Опытный

ru
Offline Offline

« : 22-11-2011 13:07 » 

Код: (Delphi)
procedure TForm2.FillGridHistory();
var
  SQLText : String;
begin
  try
    with DataManagerModule.ADOQueryHistory do
    begin

      SQL.Clear;
      SQLText :=  'SELECT * FROM history';
      SQL.Add(SQLText);
      Active := true;
      //ShowMessage(IntToStr(RecordCount));
    end;
  except
     on e:Exception do
  end;

end;

// Другая процедура
...............
  res := CheckConnection();
  if (not res) then
  begin
    DisableControls();
    Exit;
  end;

  FillGridHistory();

  DataManagerModule.ADOConnectionManager.Connected := false;

Если закомментить строку
DataManagerModule.ADOConnectionManager.Connected := false;

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


Что сделать чтоб данные попали в грид?

* EmptyGrid.png (3.11 Кб - загружено 976 раз.)
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 22-11-2011 18:33 » 

Логично.

А в чем вопрос то?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
malor
Опытный

ru
Offline Offline

« Ответ #2 : 22-11-2011 18:44 » 

Почему свойству требуется быть равным true. Компонент ADOQuery без этого не может предоставить (уже отобранные) данные в грид?
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 22-11-2011 18:50 » 

Так сделано. В мануале такие вещи пишут, однако.

Собственно, подключение к базе не обязано быть постоянным. От того есть вкл/выкл в лице Connected. Если хочется сохранить данные в промежутке между отключения от базы, используй независимое от подключение хранилище данных.

Такая идея (не проверял):
1. TADOConnection + TADOQuery -- подключиться и получить данные
2. TDataSource + TADOTable -- скопировать данные из запроса в эту таблицу (метод TCustomADODataSet.clone)
« Последнее редактирование: 22-11-2011 19:07 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
malor
Опытный

ru
Offline Offline

« Ответ #4 : 23-11-2011 15:20 » 

RXL>> Так сделано. В мануале...

Дайте plz ссылку...
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 23-11-2011 17:17 » 

F1

Выбираешь компонент на форме или ставишь курсор на нужное слово в исходнике. Потом F1.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #6 : 24-11-2011 05:18 » 

Злые вы. Улыбаюсь               

malor, здесь дело не столько в ADOConnection, а в том компоненте, который вы используюете для отображения данных в гриде. ADO-шные компоненты не являются кэширующими. нет ручек - нет конфеток, нет соединения - нет данных. если вы будете использовать, например, ClientDataSet - вам будет пофигу на соединение, но вы столкнетесь с проблемой "конкурентных" транзакций.

есть три типа логики построения БД. рассмотрим на примере, у нас есть база, есть соединение и датасет (DS), и есть модальная форма для редактирования записи (EditDlg).

1) онлайн. меняем все на подключенной базе. если кто-то пытается поменять запись одновременно с нами, которая у нас уже в режиме редактирования - это проблемы сервера, в большинстве случаев он просто не даст это сделать, запись лочится на уровне СУБД.

Код: (Delphi)
  DS.Edit;
  if EditDlg.ShowModal = mrOk then
    DS.Post
  else
    DS.Cancel;

на форме при этом находятся db-aware контролы, когда пользователь меняет в них значения - они сразу вносятся в DS.

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

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


Код: (Delphi)
  // копируем данные из DS на форму
  if EditDlg.ShowModal = mrOk then begin
    DS.Edit;
    try
      // копируем измененные данные из формы в DS
      DS.Post
    except
      DS.Cancel;
    end;
  end;

что произойдет в случае с нашей красотой из отдела кадров? да ничего. в этом случае сервер даже не узнает, что его запись три дня висела в режиме редактирования. собственно, технически - она и не висела. но здесь есть другой подводный камень - за эти три дня запись мог изменить кто-то другой. в понедельник приходит наша красота, видит форму, говорит "ой" и клацает но "Ok". и данные будут перезатерты, причем она даже не узнает, что она затерла чьи-то данные. поэтому в таких случаях всегда используется проверка на актуальность. например, в таблице заводится поле "LastUpdate", заполняемое сервером (в триггере). при открытии формы на редактирование значение поля запоминается. при закрытии формы значение поля запрашивается (в отдельной транзакции). если оно изменилось - значит кто-то успел поменять это поле, пока наша красота телилась, и ее надо об этом предупредить - что она сейчас затрет чужую инфу. при желании можно даже показать  какую.

3) всегда оффлайн. это делается с помощью многозвенной архитектуры, т.е. у нас есть СУБД, есть сервер приложений, и есть клиент. коннекты к базе, и запись в нее - привилегия строго сервера приложений. здесь клиент вообще не знает, куда он коннектиться, по-большому счету. и соединения с сервером СУБД у него нет в принципе. реализуется это достаточно просто, на том же Indy, обычным Message-сервером. логика следующая: клиент отдает команды серверу приложений, а тот их выполняет. например:

[Клиент]: - сделай мне подключение;
[Сервер]: - на, хэндл подключения = $1 (TDatabase.Handle, для клиента он нужен только как идентификатор)

[Клиент]: - слушай, для подключения $1 стартани мне транзакцию c параметрами [READ_COMMITED,NOWAIT]
[Сервер]: - на, хэндл транзакции = $2 (TTransaction.Handle)

[Клиент]: - в транзакции $2 надо прогнать вот такой селект: "SELECT * FROM USERS"
[Сервер]: - на (отдает результат, например, в виде XML)

...

пользователь тем временем сел в самолет и улетел в гваделупу. и вообще забыл, что делал. и комп у него остался в офисе. но в Гваделупе он вспомнил, открыл свой верный ай-фон, и залез в веб-интерфейс к своей БД. сервак ему показал, что у него есть активная транзакция $2, в рамках который он в последний раз выполнял такой-то запрос. то, что он сейчас сидит совершенно за другим компьютером - нам наплевать, потому что физический коннект к серверу держит наш сервер приложений. у него есть пул подключений, пул транзакций, а клиент просто говорит ему, что надо с ними делать.

< два дня спустя >

[Клиент]: - слышь, генеральный сказал, что только массовые рассстрелы спасут Родину. надо выкинуть из таблицы USERS урода №2 и урода №6, сделать это надо в транзакции $2 на подключении $1.
[Сервер]: - ok

[Клиент]: - подтвердить транзакцию $2
[Сервер]: - ok

[Клиент]: - закрыть подключений $1
[Сервер]: - ok.

как-то за банкой козла мы с Ромой (RXL) обсуждали такую логику, и он сказал, что что-то подобное мутил Гугль на базе SQLite, т.е. ты можешь работать с БД с любого компьютера без обрыва транзакции. можешь потрясти его на предмет подробностей, я не в курсе )

подобные механизмы используются редко, да и вообще для нормально спроектированного приложения трехзвенная архитектура нахрен не нужна, но такая схема работы с БД иногда встречается. у перцев, регулярно летающих в Гваделупу.

Резюме.

1. Курить RTFM (TDataBase => TTransaction => TDataSet => TDataSource => TDbGrid, для Сиквела: TAdoConnection => TAdoDataSet (TAdoCommand, TAdoQuery) => TDataSource => TDbGrid). "Почему при выключенном коннекте к базе данных я не вижу данных" - это вопрос из разряда почему блондинки носят очки от солнца не на носу, а на голове (потому что когда они опускают их на нос - им становится темно и страшно).

2. Курить понятие кэшируемых обновлений, TClientDataSet. попробовать самостоятельно вытащить данные из TAdoQuery в TClientDataSet, сбросить соединение, и убедится, что данные из TClientDataSet никуда не делись. в качестве бонуса - при отключенном соединении изменить данные, поднять соединение, и засунуть эти данные в базу (сразу говорю, что "руками" там делать почти ничего не надо, никаких Edit / Post там не будет).

3. для общего понимания того, что происходит, курить транзакции, уровни изоляций и понятие конкурентной транзакции.
 
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 24-11-2011 07:40 » 

как-то за банкой козла мы с Ромой (RXL) обсуждали такую логику, и он сказал, что что-то подобное мутил Гугль на базе SQLite, т.е. ты можешь работать с БД с любого компьютера без обрыва транзакции. можешь потрясти его на предмет подробностей, я не в курсе )

Игорь, ты сам мне это рассказывал. Тебе и вспоминать Ага
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines