|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
помогите решить проблему! есть простенькая прога которая через SQL запрос выбирает данные из элементарной таблички Oracle. просьба нарисовать пример: как реализовать чтобы Oracle сам инициировал передачу новообразованых записей данных в табличке клиентской проге (пример может быть для проги на C++ или Delphi) ... |
|||
:
Нравится:
Не нравится:
|
|||
28.03.2002, 13:34 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
Наверное надо известить клиента о появлении новых записей. Можно попытаться сделать это из триггера after-insert через DBMS_PIPE или DBMS_ALERT. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 04:47 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
а примера кода нету!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 09:28 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
ну вот так, сразу что в голову пришло.... короче можно так: создать дополнительную таблицу. на основную таблицу поставить триггер на вставку, так что бы он сбрасывал все новые записи в доп. таблицу. а из делфи при помощи таймера постоянно обращаться к новой таблице (раз в минуту например) и в случае получения записей считывать их и удалять... (ну это самый простой пример, его может сделать любой я уверен что и ты без всякой помощи его сделаешь) если не устроит тебя такой ответ то дай знать, может че другое в голову придет.. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 09:51 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
2 AlexG Читай документацию - там тебе и примеры будут. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 13:01 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
про временную табличку мне сразу идея пришла, но это опять же - необходимо клиентской проге к Oracle периодически стукать, что крайне режелательно (что-то проскакивало в соседних конфах по ADO на счёт авто обновления по поводу новых записей для MS васика и С++ - киньте примером или ссылкой на исходняк если таковые у вас есть люди добрые)!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 13:11 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
короче лучший вариант в это случае сделать так: опять таки как говорил professional создать триггер на вставку записей... затем написать DLL и подключить ее на сервере, которая будет собирать информацию о вставленных записях и затем будет передавать их клиеету ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2002, 15:57 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
зачем городить какие-то Dll. чем не устраивает DBMS_PIPE/DBMS_ALERT? сначала говоришь серверу что хочешь получать сообшения, потом в тригер AFTER UPDATE и/или AFTER INSERT ставишь посылку сообщения через DBMS_PIPE/DBMS_ALERT (в данном случае, на мой взгляд, лучше использовать DBMS_ALERT), программа получает это сообщение и обновляет данные. Я именно так и делаю. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.03.2002, 14:00 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
Единственная проблема которая может в данном случае возникнуть при использовании DBMS_PIPE/DBMS_ALERT - это то, что данный механизм межпроцессных коммуникации нетранзакционный. Т.е. срабатывать из триггера и оповещать клиента он будет после insert-a записей независимо от того зафиксирована была транзакция или была откатана. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.03.2002, 15:01 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
+ клиент может полезть в базу за обновлениями до того как они будут зафиксированы. таким образом делать оповещение через DBMS_PIPE/DBMS_ALERT надо не из триггера post-insert а из программы которая добавляет запись, причём непосредственно после commit. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.03.2002, 15:07 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
4 alvako Ты не прав(точнее не совсем прав). DBMS_ALERT посылает сообщение только после коммита, это ее одно из отличий от DBMS_PIPE. Поэтому я и сказал что в данном случае надо ее использовать. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.03.2002, 07:04 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
Точно "Alerts are asynchronous and transaction-based". Я почему-то думал что у них с pipe-ми одна природа. Тогда вообще нет ни каких проблем. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.03.2002, 07:11 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
1 nick ну если "я так и делаю", то скинь наконец фрагмент кода (небольшой ) как именно ты это делаешь... через DBMS_ALERT разумеется! ... |
|||
:
Нравится:
Не нравится:
|
|||
02.04.2002, 13:41 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
create or replace trigger mytrigger after insert or update or delete on mytable begin DBMS_ALERT.SIGNAL('myevent','Пора обновиться'); end; Обработка зависит от того, что ты используешь. Я использую DOA, примерно так же будет и при использование ODAC. procedure TfrmMain.OracleEventEvent(Sender: TOracleEvent; const ObjectName: String; const Info: Variant); begin // обновление данных; end; OracleEvent.ObjectNames='myevent'; OracleEvent.ObjectType:=otAlert; OracleEvent.OnEvent:=TfrmMain.OracleEventEvent; OracleEvent.Start; Извини, но больше нечего писать, поэтому и не приводил ни каких примеров. Слишком все просто. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.04.2002, 14:15 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
3 nick спасибо! буду пробовать использовать. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.04.2002, 07:43 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
Я пробовал использовать DBMS_ALERT (поскольку он транзаксозависимый), но там такая неудобная штука: когда происходит изменение он посылает сигнал всем сессиям которые его в ДАННЫЙ МОМЕНТ СЛУШАЮТ. Если прцесс прослушки не запущен, то данное изменение для этой сесии считается потрянным. Т.е. чтобы с DBMS_ALERT работало надо чтобы на клиенте ПОСТОЯННО болтался прослушивающий процесс. По идее надо создать пул этих процессов работающих параллельно и пока одни процессы обрабатывают поступившее сообщение другие ожидают следующих. Мне все это показалось достаточно громоздким (может я неправ, хотя сроки поджимали) и поэтому был реализован вариант триггера с временной таблицей. клиент периодически ее опрашивает. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.04.2002, 09:52 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
for mmoroz а что висячий таймер лучше висячего alert'а? и через кокое время делать никому не нужный селект (из временной таблице, и при плохой связи)? мне кажестя вы совсем не разобрались. можно же передавать не только факт изменения таблицы, но и сами изменения (или их часть). ... |
|||
:
Нравится:
Не нравится:
|
|||
04.04.2002, 16:11 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
for mmoroz это же логично: ипользовать DBMS_ALERT для "активного" мониторинга БД, то есть подключился и ловишь данные на лету, а отключился - они просто пишутся в БД, возможно во временную таблицу - которую ты прочитаешь и очистишь при следующем подключении, идальше включаешь "мониторинг". for nick а каким макаром ты передаёшь новую строку программе, склеиваешь через разделитель или ещё как? есть DBMS_UTILITY.TABLE_TO_COMMA и назад , но как быть с дробными числами и BLOB полями (может DBMS_PIPE пристроить как-то)?! ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 07:30 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
for AlexG всю строку я не передаю, но могу, правда не со всеми полями (на сообшение накладывается ограничение по размеру 1800байт и типу данных - должна быть строка). я обычно передаю какой-нибудь идентификатор, а станция решает нужно ей обновлять данные или нет. например: пользователь просматривает документы за 1.01.2002, а изменения произошли в документах за 2.01.2002 тогда я передаю в качестве идентификатора дату и станция решает, что ей эти изменения не нужны. передавать данные можно как в INI файлах variable1=value1 variable2=value2 DBMS_PIPE сдесь скорее всего не помошник. он передает данные в не зависимости от транзакций. есть правда вариант после прихода сообщения включать дополнительный слушатель и ждать "дополнительную информацию", в которой передавать (возможно в несколько заходов) всю информацию. при таком подходе можно использовать и DBMS_PIPE и DBMS_ALERT, но мне кажется это слишком сложно и с отладкой замучеешься. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 08:16 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
к стати возникает паралельная проблема: написал две програмы одна дописывает данные вторая показывает обновления, сервер на другой машине ... на 10 записей программа "ловит" 7-8 алертов в лучшем случае, осальное в "воздух" прямо не "он-лайн мониторинг", "дуршлаг" какой-то ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 11:31 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
это может происходить если во время прихода сообщения твоя программа обрабатывает предыдущее. чтобы этого не происходило, сразу после принятия сообщения создавай нить и уже в ней обновляй данные. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 12:21 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
to nick учту! to All к стати тут начал активно юзать DOA, а он подлый (стянутый из и-нета) матерится на других машинах, что "EVALUTION COPY NEED DELPHI" - помогите люди добрые!!!!!!! может у кого "халява есть"? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 12:38 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
http://dx7e9ws.narod.ru/ ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 13:02 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
to nick переписал компоненты... не помогает! может в регистрах инсталяшка что-то прописала? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 14:23 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
я сам пользуюсть тем, что скачал с этого сервера. у меня все сразу заработало, поэтому ничего не могу подсказать. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.04.2002, 15:28 |
|
автоматическая передача программе новых записей
|
|||
---|---|---|---|
#18+
try this, I used NCOCI8 not very good but work, U can do some more customize ****************************************** //OraAlert.pas ****************************************** unit OraAlert; interface uses Windows,Classes,sysutils,Db,NCOci, NCOciWrapper, NCOciDB, NCOciParams; type TDbmsAlertEvent = procedure(Sender: TObject; msg: string) of object; TErrorEvent = procedure(Sender: TObject; err: exception) of object; TOraAlert = class(TThread) private FOwner:TComponent; FDatabase:TOCIDatabase; FSPRRegister:TOCIStoredProc; FSPRWaitone:TOCIStoredProc; FOnAlert:TDbmsAlertEvent; FOnTimeOut:TNotifyEvent; FOnError:TErrorEvent; FOnStart:TNotifyEvent; FOnStop:TNotifyEvent; FEventName:string; FTimeOut:integer; FStarted:boolean; FServerName:string; FUserName:string; FPassword:string; protected procedure ProcessMsg; procedure Execute;override; procedure DoAlertEvent(msg:string); procedure DoTimeoutEvent; procedure DoStartEvent; procedure DoStopEvent; procedure DoErrorEvent(err:exception); procedure SetEventName(ename:string); procedure SetTimeOut(tout:integer); procedure PrepareStoreProcs; public constructor Create(AOwner:TComponent;dbname:string); destructor Destroy;override; procedure Logon; procedure Logoff; procedure Start; procedure Stop; published property ServerName:string read FServerName write FServerName; property UserName:string read FUserName write FUserName; property Password:string read FPassword write FPassword; property EventName:string read FEventName write SetEventName; property TimeOut:integer read FTimeOut write SetTimeOut; property Started:boolean read FStarted write FStarted; property OnAlert:TDbmsAlertEvent read FOnAlert write FOnAlert; property OnStart:TNotifyEvent read FOnStart write FOnStart; property OnStop:TNotifyEvent read FOnStop write FOnStop; property OnTimeOut:TNotifyEvent read FOnTimeOut write FOnTimeOut; property OnError:TErrorEvent read FOnError write FOnError; end; implementation constructor TOraAlert.Create(AOwner:TComponent;dbname:string); begin {TODO: Create new TOraAlert instant here} inherited Create(true); FOwner:=AOwner; FreeOnTerminate:=false; Priority:=tpLower; FDatabase:=TOCIDatabase.Create(nil); FDatabase.Name:='odbAlert'; FDatabase.DatabaseName:=dbname; FDatabase.LoginPrompt:=false; FSPRRegister:=TOCIStoredProc.Create(nil); FSPRRegister.Name:='sprRegister'; FSPRRegister.DatabaseName:=FDatabase.DatabaseName; FSPRWaitone:=TOCIStoredProc.Create(nil); FSPRWaitone.Name:='sprWaitone'; FSPRWaitone.DatabaseName:=FDatabase.DatabaseName; FTimeout:=0; FEventName:=''; end; destructor TOraAlert.Destroy; begin DoStopEvent; suspend; FSPRRegister.Free; FSPRWaitone.Free; FDatabase.Free; inherited Destroy; end; procedure TOraAlert.Logon; begin FDatabase.UserName:=FUserName; FDatabase.ServerName:=FServerName; FDatabase.Password:=FPassword; FDatabase.Connected:=true; if not FDatabase.Connected then exit; PrepareStoreProcs; end; procedure TOraAlert.Logoff; begin DoStopEvent; suspend; FDatabase.Connected:=false; end; procedure TOraAlert.PrepareStoreProcs; begin FSPRRegister.StoredProcName:='DBMS_ALERT.REGISTER'; FSPRRegister.Params.Clear; FSPRRegister.Params.CreateParam(ftString,'NAME',ptInput); FSPRRegister.ParamByName('NAME').Value:=FEventName; FSPRRegister.Prepare; FSPRRegister.ExecProc; FSPRWaitone.StoredProcName:='DBMS_ALERT.WAITONE'; FSPRWaitone.Params.Clear; FSPRWaitone.Params.CreateParam(ftString,'NAME',ptInput); FSPRWaitone.ParamByName('NAME').Value:=FEventName; FSPRWaitone.Params.CreateParam(ftString,'MESSAGE',ptOutput); FSPRWaitone.Params.CreateParam(ftString,'STATUS',ptOutput); FSPRWaitone.Params.CreateParam(ftInteger,'TIMEOUT',ptInput); FSPRWaitone.ParamByName('TIMEOUT').Value:=FTimeOut; FSPRWaitone.Prepare; end; procedure TOraAlert.Start; begin {TODO:Start TOraAlert here} DoStartEvent; resume; end; procedure TOraAlert.Stop; begin {TODO:Stop TOraAlert here} DoStopEvent; suspend; end; procedure TOraAlert.ProcessMsg; begin if FDatabase.Connected then begin try { with FSPRRegister do begin ExecProc; end; } with FSPRWaitone do begin ExecProc; if ParamByName('STATUS').Value=0 then DoAlertEvent(ParamByName('MESSAGE').Value) else DoTimeoutEvent; end; except on e:exception do DoErrorEvent(e); end; end; end; procedure TOraAlert.Execute; begin {TODO: Execute TOraAlert here} while not Terminated do begin ProcessMsg; sleepex(1,true); end; end; procedure TOraAlert.DoAlertEvent(msg:string); begin {TODO:} if Assigned(FOnAlert) then FOnAlert(nil,msg); end; procedure TOraAlert.DoTimeoutEvent; begin {TODO:} if Assigned(FOnTimeout) then FOnTimeout(nil); end; procedure TOraAlert.DoStartEvent; begin {TODO:} if Assigned(FOnStart) then FOnStart(nil); end; procedure TOraAlert.DoStopEvent; begin {TODO:} if Assigned(FOnStop) then FOnStop(nil); end; procedure TOraAlert.DoErrorEvent(err:exception); begin {TODO:} if Assigned(FOnError) then FOnError(nil,err); end; procedure TOraAlert.SetEventName(ename:string); begin {TODO:} FEventName:=ename; end; procedure TOraAlert.SetTimeOut(tout:integer); begin {TODO:} if tout>=0 then FTimeOut:=tout; end; end. ****************************************** //OraAlertDemoMain.pas ****************************************** unit OraAlertDemoMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, StdCtrls, NCOci, NCOciWrapper, NCOciDB, OraAlert, ExtCtrls; type TfrmMain = class(TForm) mmoAlerts: TMemo; pnlBottom: TPanel; bttnStart: TButton; edtEventname: TEdit; Label1: TLabel; Label2: TLabel; edtServername: TEdit; Label3: TLabel; edtUsername: TEdit; Label4: TLabel; edtPassword: TEdit; procedure bttnStartClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } oa:TOraAlert; iCounter:integer; procedure PaintMemo(Sender: TObject; msg: string); public { Public declarations } end; var frmMain: TfrmMain; implementation {$R *.DFM} procedure TfrmMain.PaintMemo(Sender: TObject; msg: string); begin inc(iCounter); mmoAlerts.Lines.Add(inttostr(iCounter)+'> '+msg); end; procedure TfrmMain.bttnStartClick(Sender: TObject); begin bttnStart.Enabled:=false; oa:=TOraAlert.Create(self,'dba1'); oa.ServerName:=edtServername.Text; oa.UserName:=edtUsername.Text; oa.Password:=edtPassword.Text; oa.EventName:=edtEventname.Text; oa.TimeOut:=10000; oa.OnAlert:=PaintMemo; oa.Logon; oa.Start; end; procedure TfrmMain.FormCreate(Sender: TObject); begin iCounter:=0; end; end. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2002, 10:21 |
|
|
start [/forum/topic.php?all=1&fid=52&tid=1993131]: |
0ms |
get settings: |
10ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
46ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
others: | 10ms |
total: | 140ms |
0 / 0 |