Злые вы.
malor, здесь дело не столько в ADOConnection, а в том компоненте, который вы используюете для отображения данных в гриде. ADO-шные компоненты не являются кэширующими. нет ручек - нет конфеток, нет соединения - нет данных. если вы будете использовать, например, ClientDataSet - вам будет пофигу на соединение, но вы столкнетесь с проблемой "конкурентных" транзакций.
есть три типа логики построения БД. рассмотрим на примере, у нас есть база, есть соединение и датасет (DS), и есть модальная форма для редактирования записи (EditDlg).
1) онлайн. меняем все на подключенной базе. если кто-то пытается поменять запись одновременно с нами, которая у нас уже в режиме редактирования - это проблемы сервера, в большинстве случаев он просто не даст это сделать, запись лочится на уровне СУБД.
DS.Edit;
if EditDlg.ShowModal = mrOk then
DS.Post
else
DS.Cancel;
на форме при этом находятся db-aware контролы, когда пользователь меняет в них значения - они
сразу вносятся в DS.
это - самый "жесткий" способ, который максимально гарантирует целостность данных. если какая-то красота из отдела кадров открыла на редактирование запись в справочнике сотрудников, забыла закрыть, ушла обедать, потом заглянула в парикмахерскую, а потом отзвонилась шефу и уехала домой (потому что это был пятница) - транзакция будет висеть, пока она не закроет форму (т.е. до понедельника). или пока осатаневшие пользователи не заставят доброго админа перегрузить сервер. не вдаваясь в технические нюансы, долго открытая транзакция - хреновая примета.
2) почти онлайн. на форме находятся обычные контролы. когда пользователь вызывает запись на редактирование, данные
копируются в них. но сам датасет в режим редактирования не переводится. а вот когда редактирование закончено, датасет одним чохом переводится в режим редактирования, данные обновляются, датасет постится.
// копируем данные из 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. для общего понимания того, что происходит, курить транзакции, уровни изоляций и понятие конкурентной транзакции.