![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как грамотнее открывать/закрывать соединение с базой [MSSQL]
Ольга © (2005-08-07 09:24:00)В программе есть TreeView, на каждый click идет запрос к базе.
Открываю ADOConnection на FormCreate, закрываю на FormClose.
А не правильнее ли открывать/закрывать соединение на каждый click? Ведь пользователь может открыть форму и пойти пить чай - зачем держать соединение открытым. С другой стороны, а если не пойдет пить чай - зачем дергаться на каждый click?
Ольга (2005-08-08 15:13:00) [1]Баз у меня 4 штуки (одна родная и 3 чужеродные).
1 вариант.Программа работает с одним соединением к родной базе, к которой прилинкованы 3 чужих.
Т.к. запросы к прилинкованным базам не всегда хорошо работают (DTC запущен), пришлось сделать:
2 вариант.Если для неродной базы <флаг использовать линк>=False, то создаем прямое соединение с этой базой, иначе работаем с родной базой через линк.
Я сегодня выспавшимися глазками прочла сначала всю ветку и поняла, что в [7] и был ответ, т.е. когда я, выполняя условие "работаем с родной базой", пишу ADOConnection2:=ADOConnection1, я получаю 2 переменные, ссылающиеся на ADOConnection1, ссылка на ADOConnection2 убита. Так ведь "за что боролись, на то и напоролись"!
Оба варианта уже в действии.
Большое всем спасибо, что помогли разобраться.
Nikolay M. (2005-08-08 10:24:00) [2]
> Прилинковала Oracle к MSSQL через MS Provider for Oracle
> - запрос выполняется 4 мин., когда напрямую из Oracle 2
> сек.
DTC запущен?
evvcom (2005-08-08 09:48:00) [3]
> ведь для клиента существует только одна база
Я так понял, что теперь не одна.
Polevi (2005-08-08 09:22:00) [4]все же я не понял зачем необходимы несколько соединений с базой, ведь для клиента существует только одна база, интерфейс которой скрывает от него физическое местоположение данных
evvcom (2005-08-08 08:44:00) [5]Тяжело давать советы, не зная задачи целиком и нюансов. Но иметь переменные ADOConnection1, ADOConnection2 и т.д. неправильно. Если заранее неизвестно, сколько будет таких переменных, то используем динамический массив. Если известно, то статический. Можно вместо статического сделать вариантную запись из стат.массива и Conn1, Conn2 и т.д. Тогда
> И на каждое обращение к функции выборки (а их много-о-о),
> пишу
> if ADOConnection2,3,4<>nil then
> GetData(ADOConnection2)
> else
> GetData(ADOConnection1);
> Ох, утомительно...
перепишется через цикл и не будет так утомительно.
Ольга (2005-08-07 14:55:00) [6]Решила создать 4 самостоятельных коннекта, чтобы не делать море ифов. А то, что у большинства эти 4 коннекта будут близнецы-братья наплевать. Правильно?
Ольга (2005-08-07 14:45:00) [7]
> что такое "прилинкованные"
К серверуБД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);
Ох, утомительно...
msguns (2005-08-07 14:02:00) [8]>Ольга (07.08.05 13:42) [17]
>На вопрос зачем:
>Приложение имеет свою базу и 3 прилинкованные.
Я не орол в скале, поясни, что такое "прилинкованные" - это что, другие mdf-ки ? А к ним запросы через логику сервера ? Или запросы чисто клиентские ? Если второе, то это имхо гетерогенные запросы и зачем для них отдельный коннект ?
Насколько я понимаю, для каждой базы, с которой я собираюсь поддерживать достаточно длительный сеанс, причем с правами записи, надо создавать отдельный коннект. Если так, то у тебя должно быть создано столько коннектов, сколько баз. Т.е. на создание и инициализацию каждого коннекта должна быть выполнена процедура, схожая с [15]. И тогда передавай в исполнительные функции в качестве параметра указатель на экземпляр того коннекта, по которому надо обмениваться с соотв. БД.
Если же из "прилинкованных" БД ты разово считываешь данные, например, для добавления (репликацию) в корпоративную (интегрированную) БД, то вполне подойдет клиентский гетерогенный запрос в контексте основной транзакции.
Или я чего-то недопонял ?
>Если я пишу:
ADOConnection2:=ADOConnection1
ADOConnection3:=ADOConnection1
ADOConnection4:=ADOConnection1
то для клиентов с прилинкованными базами будут созданы 4 коннекции, хотя достаточно одной.
Нет, Оля, конечно. У тебя созданодин экземпляр коннекта ADOConnection1, указатель на который ты запихиваешь в три переменные (типизированные указатели). Если ранее для каждой из этих переменных был выполнен метод Create (т.е. создан экземпляр TADOConnection), то этим присвоением ты фактически похоронишь "следы" к этим экземплярам. Т.е. как указал DaemondShark выше, адреса созданных объектов будут просто утеряны.
Так делать нельзя принципиально.
Или наплевать?
Ольга (2005-08-07 13:42:00) [9]На вопрос зачем:
Приложение имеет свою базу и 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 13:16:00) [10]Метод Assign у коннекта "заимствован" у TPersistent. Неудивительно, что про такие поля, как ConnetionString, CursorLocation, IsolationLevel, Provider etc он даже не догадывется ;))
msguns (2005-08-07 13:12:00) [11]И еще, зачем именно 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:08:00) [12]Оля, оставь так, как было в [3], т.е. создавай оба коннекта сразу.
В процедуре открытия коннекта №2, которую ты будешь вызывать перед первым запросом в контексте этого соединения, делай просто Assign. Коннект №1, ессно, уже должен быть полностью инициализированным и даже открытым (чтобы избежать двойной ошибки при соединении, например, к несуществующему mdf)
ИМХО, зачем ты пихаешь это все в процедуру с параметрами, у тебя что, будет много разныхпар коннектов ?
Все-таки я не получил удобоварительного ответа на вопрос "Зачем два коннекта к одной бД ?"
sniknik (2005-08-07 13:05:00) [13]> Connot assign a TADOConnection to a TADOConnection
а вот это, помоему, означает что в самом классе Assign не реализован, а родительский, унаследованный не справляется...
придется тебе как нибудь без этого обойтись, по другому.
Ольга (2005-08-07 12:56:00) [14]Попробовала все варианты - выходит ошибка на строке Conn.Assign(DefaultConn), правда уже на челевеческом языке:
Connot assign a TADOConnection to a TADOConnection
sniknik (2005-08-07 12:46:00) [15]> Создаю в процедуре (пропустила строчку), может надо это делать выше?
можно и сдесь, но тогда надо по var переменную передавать. меняется то не только значение по ссылке но и сама ссылка, значит и ссылку надо по ссылке передавать. ;о))
procedure TConsol.InitADOConnection(var Conn, DefaultConn: TADOConnection);
хотя... ошибка в самой процедуре а не после выхода из нее... в принципе там и так не должно ее выдавать (но исправить надо).
попробуй еше на закрытом а не открытом первом коннекте.
Ольга (2005-08-07 12:39:00) [16]Создаю в процедуре (пропустила строчку), может надо это делать выше?
procedure TConsol.InitADOConnection(Conn, DefaultConn: TADOConnection);
begin
Conn:=TADOConnection.Create(nil);
if not <некое условие> then
Conn.Assign(DefaultConn); - ошибка адресации
else ...;
end;
sniknik (2005-08-07 12:32:00) [17]ADOConnection2 не создано, nil-у свойства пытаешся передать...
Ольга (2005-08-07 12:27:00) [18]Думала, что уже разобралась, но, видимо, недопонимание осталось, т.к. мой код не работает:
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;
DiamondShark (2005-08-07 12:06:00) [19]
> Ольга (07.08.05 11:03) [3]
При этом будет два соединения, но ссылка на второе будет утеряна.
msguns (2005-08-07 11:25:00) [20]бедненькая..