Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-1124867893
lehich
2005-08-24 11:18
2005.09.18
ProgressBar, который отрисовывает линейку програсса в Статусбаре


14-1124905300
Веретенников
2005-08-24 21:41
2005.09.18
Выбор ТВ-тюнера


14-1124180221
i-s-v
2005-08-16 12:17
2005.09.18
USB


9-1116775997
yurique
2005-05-22 19:33
2005.09.18
OpenGL


3-1122869002
Simon
2005-08-01 08:03
2005.09.18
Связь "многие ко многим"





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский