Форум: "Базы";
Текущий архив: 2005.09.18;
Скачать: [xml.tar.bz2];
ВнизКак грамотнее открывать/закрывать соединение с базой Найти похожие ветки
← →
Ольга (2005-08-07 09:24) [0]В программе есть TreeView, на каждый click идет запрос к базе.
Открываю ADOConnection на FormCreate, закрываю на FormClose.
А не правильнее ли открывать/закрывать соединение на каждый click? Ведь пользователь может открыть форму и пойти пить чай - зачем держать соединение открытым. С другой стороны, а если не пойдет пить чай - зачем дергаться на каждый click?
← →
msguns © (2005-08-07 10:41) [1]Смотря что "висит" на соединении. Если читающая транзакция, то нехай себе "висит" до второго пришествия, серверу не внапряг. Переконнетиваться "по каждому клику" - задавать серверу хоть и не слишком большую, но постоянную работу, "заморачивать" его по мелочам.
Если же "висячка" на апдейтах, то это, ИМХО, от наличия кривизны рук и отсутствия царя в голове. Т.е. изменилась запись (юзер вызвал соотв.экшн) - прошла транзакция на запись в БД, закоммитилась и НД перечитан. Сервер "перекуривает". При этом есть ли еще вагоны для разгрузки-погрузки и сколько их (т.е.соединение не закрыто) - его, по большому счету, не колышит.
← →
msguns © (2005-08-07 10:43) [2]Кстати, если речь идет о "деревянном" справочнике, то, если записей в нем не слишком много (скажем, до 10.000), не проще ли закачивать его "одним махом", при этом не дергая сервак при перемениях-разворачиваниях по узлам дерева ? И повесить кнопульку "Перечитать".
← →
Ольга (2005-08-07 11:03) [3]Речь идет только о чтении данных, но данные должны быть всегда свежими, поэтому одним махом читать нельзя.
Мой пользователь - диспетчер, потому программа должна быть отказоустойчива. Если во время бездействия программы произошел разрыв соединения, пользователь не должен это заметить.
И еще один вопрос до кучи (что-то я сегодня вся в сомнениях):
ADOConnection1, ADOConnection2: TADOConnection;
ADOConnection1:=TADOConnection.Create(nil);
ADOConnection2:=TADOConnection.Create(nil);
...
ADOConnection1.Open;
ADOConnection2:=ADOConnection1; - при этом реально будут два соединения с базой или одно?
← →
msguns © (2005-08-07 11:07) [4]>Ольга (07.08.05 11:03) [3]
>ADOConnection1.Open;
ADOConnection2:=ADOConnection1; - при этом реально будут два соединения с базой или одно
Если надо создать второй экземпляр объекта с такими же свойствами, то используют Assign
Это прикол что ль ?
← →
Ольга (2005-08-07 11:10) [5]Нет, это отупение после месяца работы по 12 часов в день без выходных.
Спасибо.
← →
msguns © (2005-08-07 11:25) [6]бедненькая..
← →
DiamondShark © (2005-08-07 12:06) [7]
> Ольга (07.08.05 11:03) [3]
При этом будет два соединения, но ссылка на второе будет утеряна.
← →
Ольга (2005-08-07 12:27) [8]Думала, что уже разобралась, но, видимо, недопонимание осталось, т.к. мой код не работает:
ADOConnection1, ADOConnection2: TADOConnection;
ADOConnection1:=TADOConnection.Create(nil);
...
ADOConnection1.Open;
InitADOConnection(ADOConnection2, ADOConnection1);
procedure TConsol.InitADOConnection(Conn, DefaultConn: TADOConnection);
begin
if not <некое условие> then
Conn.Assign(DefaultConn); - ошибка адресации
else ...;
end;
← →
sniknik © (2005-08-07 12:32) [9]ADOConnection2 не создано, nil-у свойства пытаешся передать...
← →
Ольга (2005-08-07 12:39) [10]Создаю в процедуре (пропустила строчку), может надо это делать выше?
procedure TConsol.InitADOConnection(Conn, DefaultConn: TADOConnection);
begin
Conn:=TADOConnection.Create(nil);
if not <некое условие> then
Conn.Assign(DefaultConn); - ошибка адресации
else ...;
end;
← →
sniknik © (2005-08-07 12:46) [11]> Создаю в процедуре (пропустила строчку), может надо это делать выше?
можно и сдесь, но тогда надо по var переменную передавать. меняется то не только значение по ссылке но и сама ссылка, значит и ссылку надо по ссылке передавать. ;о))
procedure TConsol.InitADOConnection(var Conn, DefaultConn: TADOConnection);
хотя... ошибка в самой процедуре а не после выхода из нее... в принципе там и так не должно ее выдавать (но исправить надо).
попробуй еше на закрытом а не открытом первом коннекте.
← →
Ольга (2005-08-07 12:56) [12]Попробовала все варианты - выходит ошибка на строке Conn.Assign(DefaultConn), правда уже на челевеческом языке:
Connot assign a TADOConnection to a TADOConnection
← →
sniknik © (2005-08-07 13:05) [13]> Connot assign a TADOConnection to a TADOConnection
а вот это, помоему, означает что в самом классе Assign не реализован, а родительский, унаследованный не справляется...
придется тебе как нибудь без этого обойтись, по другому.
← →
msguns © (2005-08-07 13:08) [14]Оля, оставь так, как было в [3], т.е. создавай оба коннекта сразу.
В процедуре открытия коннекта №2, которую ты будешь вызывать перед первым запросом в контексте этого соединения, делай просто Assign. Коннект №1, ессно, уже должен быть полностью инициализированным и даже открытым (чтобы избежать двойной ошибки при соединении, например, к несуществующему mdf)
ИМХО, зачем ты пихаешь это все в процедуру с параметрами, у тебя что, будет много разных пар коннектов ?
Все-таки я не получил удобоварительного ответа на вопрос "Зачем два коннекта к одной бД ?"
← →
msguns © (2005-08-07 13:12) [15]И еще, зачем именно Assign ? Ведь TADOConnection не такой уж и "тяжелый", чтобы его в лом было ручками инициализировать:
function TDMod.DBMove_DBOpen: boolean;
begin
result := true;
with cntMove do
try
if Connected then exit;
if Connected then exit;
ConnectionString := "Provider=Microsoft.Jet.OLEDB.4.0;"+
"Data Source="+DBPath_MoveFonds+";"+
"Persist Security Info=False";
LoginPrompt := false;
try
Open;
except
result := false;
end;
except
result := false;
end;
end;
Переменную DBPath_MoveFonds замени на параметрическую, которую и передавай.
← →
msguns © (2005-08-07 13:16) [16]Метод Assign у коннекта "заимствован" у TPersistent. Неудивительно, что про такие поля, как ConnetionString, CursorLocation, IsolationLevel, Provider etc он даже не догадывется ;))
← →
Ольга (2005-08-07 13:42) [17]На вопрос зачем:
Приложение имеет свою базу и 3 прилинкованные. Вся информация читается через ADOConn1. В нашем регионе мы диктуем решения - у всех клиентов 4 базы на MSSQL. Как только появились клиенты из других регионов - появились проблемы. Сервера у всех разные, линкуются с трудом. Решила я всю красоту порушить и создать 4 коннекции. Но у большинства клиентов все уже прилинковано и работает через 1 коннект. Отсюда и if:
if not <надо> then
Conn.Assign(DefaultConn); - оставить старую коннекцию
else создать новую;
Потом я эту коннекцию передаю параметром в процедуру считывания данных.
Если я пишу:
ADOConnection2:=ADOConnection1
ADOConnection3:=ADOConnection1
ADOConnection4:=ADOConnection1
то для клиентов с прилинкованными базами будут созданы 4 коннекции, хотя достаточно одной. Или наплевать?
← →
msguns © (2005-08-07 14:02) [18]>Ольга (07.08.05 13:42) [17]
>На вопрос зачем:
>Приложение имеет свою базу и 3 прилинкованные.
Я не орол в скале, поясни, что такое "прилинкованные" - это что, другие mdf-ки ? А к ним запросы через логику сервера ? Или запросы чисто клиентские ? Если второе, то это имхо гетерогенные запросы и зачем для них отдельный коннект ?
Насколько я понимаю, для каждой базы, с которой я собираюсь поддерживать достаточно длительный сеанс, причем с правами записи, надо создавать отдельный коннект. Если так, то у тебя должно быть создано столько коннектов, сколько баз. Т.е. на создание и инициализацию каждого коннекта должна быть выполнена процедура, схожая с [15]. И тогда передавай в исполнительные функции в качестве параметра указатель на экземпляр того коннекта, по которому надо обмениваться с соотв. БД.
Если же из "прилинкованных" БД ты разово считываешь данные, например, для добавления (репликацию) в корпоративную (интегрированную) БД, то вполне подойдет клиентский гетерогенный запрос в контексте основной транзакции.
Или я чего-то недопонял ?
>Если я пишу:
ADOConnection2:=ADOConnection1
ADOConnection3:=ADOConnection1
ADOConnection4:=ADOConnection1
то для клиентов с прилинкованными базами будут созданы 4 коннекции, хотя достаточно одной.
Нет, Оля, конечно. У тебя создан один экземпляр коннекта ADOConnection1, указатель на который ты запихиваешь в три переменные (типизированные указатели). Если ранее для каждой из этих переменных был выполнен метод Create (т.е. создан экземпляр TADOConnection), то этим присвоением ты фактически похоронишь "следы" к этим экземплярам. Т.е. как указал DaemondShark выше, адреса созданных объектов будут просто утеряны.
Так делать нельзя принципиально.
Или наплевать?
← →
Ольга (2005-08-07 14:45) [19]
> что такое "прилинкованные"
К серверуБД1 линкуется другой серверБД2 (коннекцию осуществляет серверБД1 от имени пользователя Х, который имеет определенные права на сервереБД2). Теперь на сервереБД1 я создаю функции чтения данных с сервераБД2, используя гетерогенные (или не гетерогенные) запросы, добавляя в название объектов сервераБД2 имя сервера.
Клиент про сервер серверБД2 ничего не знает, создается иллюзия, что все данные он получает с сервераБД1.
Все это хорошо в теории, а на практике... Прилинковала Oracle к MSSQL через MS Provider for Oracle - запрос выполняется 4 мин., когда напрямую из Oracle 2 сек.
Речь идет только о чтении данных из "неродных" баз, запись только в свою, после расчета по считанным данным.
Значит выход у меня один:
ADOConnection1 (к родной базе) создается обязательно.
ADOConnection2,3,4 если есть необходимость.
И на каждое обращение к функции выборки (а их много-о-о), пишу
if ADOConnection2,3,4<>nil then
GetData(ADOConnection2)
else
GetData(ADOConnection1);
Ох, утомительно...
← →
Ольга (2005-08-07 14:55) [20]Решила создать 4 самостоятельных коннекта, чтобы не делать море ифов. А то, что у большинства эти 4 коннекта будут близнецы-братья наплевать. Правильно?
← →
evvcom © (2005-08-08 08:44) [21]Тяжело давать советы, не зная задачи целиком и нюансов. Но иметь переменные ADOConnection1, ADOConnection2 и т.д. неправильно. Если заранее неизвестно, сколько будет таких переменных, то используем динамический массив. Если известно, то статический. Можно вместо статического сделать вариантную запись из стат.массива и Conn1, Conn2 и т.д. Тогда
> И на каждое обращение к функции выборки (а их много-о-о),
> пишу
> if ADOConnection2,3,4<>nil then
> GetData(ADOConnection2)
> else
> GetData(ADOConnection1);
> Ох, утомительно...
перепишется через цикл и не будет так утомительно.
← →
Polevi © (2005-08-08 09:22) [22]все же я не понял зачем необходимы несколько соединений с базой, ведь для клиента существует только одна база, интерфейс которой скрывает от него физическое местоположение данных
← →
evvcom © (2005-08-08 09:48) [23]
> ведь для клиента существует только одна база
Я так понял, что теперь не одна.
← →
Nikolay M. © (2005-08-08 10:24) [24]
> Прилинковала Oracle к MSSQL через MS Provider for Oracle
> - запрос выполняется 4 мин., когда напрямую из Oracle 2
> сек.
DTC запущен?
← →
Ольга (2005-08-08 15:13) [25]Баз у меня 4 штуки (одна родная и 3 чужеродные).
1 вариант. Программа работает с одним соединением к родной базе, к которой прилинкованы 3 чужих.
Т.к. запросы к прилинкованным базам не всегда хорошо работают (DTC запущен), пришлось сделать:
2 вариант. Если для неродной базы <флаг использовать линк>=False, то создаем прямое соединение с этой базой, иначе работаем с родной базой через линк.
Я сегодня выспавшимися глазками прочла сначала всю ветку и поняла, что в [7] и был ответ, т.е. когда я, выполняя условие "работаем с родной базой", пишу ADOConnection2:=ADOConnection1, я получаю 2 переменные, ссылающиеся на ADOConnection1, ссылка на ADOConnection2 убита. Так ведь "за что боролись, на то и напоролись"!
Оба варианта уже в действии.
Большое всем спасибо, что помогли разобраться.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2005.09.18;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.01 c