Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2012.02.12;
Скачать: [xml.tar.bz2];

Вниз

FibPlus в клиент-серверном приложении   Найти похожие ветки 

 
Rusland ©   (2010-04-13 12:48) [0]

Добрый день.
Пишу клиент-вебсерверное приложение (SOAP).
В серверной части в WebModule (Unit1.pas) добавил компоненты FibPlus: TpFIBDatabase, TpFIBTransaction, TpFIBDataSet.

Настроил подключение к своей базе данных и хочу просто передать какое-нибудь значение из базы в клиентскую часть

(потом хочу передавать весь датасет, но это потом).
Написал функцию для обращения к таблице из базы (S1Impl.pas)
...
function Ts1.GetDataFromBase(s:AnsiString): AnsiString; stdcall;
begin
  Log("Начало функции"); // ведем лог в файл
try
     WM.FbDatabase.Connected:=true; // здесь выдает Access Violation
     WM.FbFirms.Active:=true;
     Result:=WM.FbFirmsFIRMA.AsString;
     WM.FbDatabase.Connected:=false;
except
     on E: Exception do Log("Произошла ошибка "+E.Message); //, E.HelpContext
end;
  Log("Конец функции");
end;

WM - это TWM = class(TWebModule)
FbDatabase: TpFIBDatabase;
FbFirms: TpFIBDataSet;

При вызове функции из клиентского приложения я получаю "Access violation at address 0055F78F in module "webserv1.exe". Read of address 000000AC" на строке WM.FbDatabase.Connected:=true;  
Если не обращаться к базе данных, то все нормально - никаких ошибок.
После долгих экспериментов увидел, что "Ахсекс виалейшн" вываливается при любом обращении к любому свойству/методу FbDatabase.
Похоже что на момент обращения не создан сам WebModule (WM). Как это проверить?

PS. Использую BDS2006, FibPlus, Firebird2.0.1, сервер Apache
Ссылка на исходники:
http://www.onlinedisk.ru/file/405488/ (клиентская часть)
http://www.onlinedisk.ru/file/405493/ (серверная часть)


 
Медвежонок Пятачок ©   (2010-04-13 13:04) [1]

зачем это проверять, это и так из контекста ясно что не создан.


 
Anatoly Podgoretsky ©   (2010-04-13 13:28) [2]

Это проверять не надо, а надо делать так чтобы не проверять


 
Rusland ©   (2010-04-13 15:38) [3]

Медвежонок Пятачок, Anatoly Podgoretsky
Ткните носом пожалуйста что и где прописать?
У меня же прописано создание WM

program WebServ1;

{$APPTYPE CONSOLE}

uses
 WebBroker,
 CGIApp,
 Unit1 in "Unit1.pas" {WM: TWebModule},
 S1Intf in "S1Intf.pas",
 S1Impl in "S1Impl.pas";

{$R *.res}

begin
 Application.Initialize;
 Application.CreateForm(TWM, WM); // разьве этого недостаточно?
 Application.Run;
end.


 
Медвежонок Пятачок ©   (2010-04-13 15:49) [4]

Note

The Web module that you set up at design time is actually a template. In ISAPI and NSAPI applications, each request message spawns a separate thread, and separate instances of the Web module and its contents are created dynamically for each thread.


Иными словами при поступлении запроса используется не тот модуль, на который указывает проинициализированная переменная, а другой.

Application.CreateForm(TWM, WM); // разьве этого недостаточно?


 
Anatoly Podgoretsky ©   (2010-04-13 16:08) [5]

Вроде бы как бы достаточно, если только Ts1 не вызывается до создания WM или где нибудь WM не разрушается. И конечно все компоненты участвующие в процессе также созданы. А сообщение "Read of address 000000AC" говорит, что это не так. Дело к тому же может быть в обработчиках, может там что либо не в порядке, а не WM
Сообственно ты код почти не показываешь.


 
Anatoly Podgoretsky ©   (2010-04-13 16:12) [6]


> Медвежонок Пятачок ©   (13.04.10 15:49) [4]

Это к вопросу не относится, вот когда он будет делать isapi вот тогда будет по делу. А вот загадочный TS1 это интереснее, но информации о нем нет.


 
Rusland ©   (2010-04-13 16:49) [7]

Показать код не проблема. Вот для серверной части проекта.
Код для S1Impl.pas
unit S1Impl;

interface

uses InvokeRegistry, Types, XSBuiltIns, S1Intf, Unit1, Classes, SysUtils, FIBDatabase, pFIBDatabase, DB, FIBDataSet, pFIBDataSet, Unit2;

type

 { TS1 }
 TS1 = class(TInvokableClass, IS1)

 public
   LogLst: TStringList;
 function  GetTT(d:integer): TArrString; stdcall;
 function  GiveX2(d:integer): integer; stdcall;
 function  GetDataFromBase(s:AnsiString): AnsiString; stdcall;
 procedure Log(str:AnsiString); stdcall;
 end;

implementation

function Ts1.GetTT(d:integer): TArrString; stdcall;
var A1: TArrString;
begin
SetLength(A1,2); A1[0] := "val1"; A1[1] :="val2";
end;

function Ts1.GiveX2(d:integer): integer; stdcall;
begin
   Log("вызываю GiveX2");
   Result:=d*2;
end;

function Ts1.GetDataFromBase(s:AnsiString): AnsiString; stdcall;
begin
  Log("Начало функции");
try
     WM.FbDatabase.Connected:=true; // тут получаю Access Violation
     wM.FbFirms.Active:=true;
    Result:=WM.FbFirmsFIRMA.AsString;
     WM.FbDatabase.Connected:=false;
except
     on E: Exception do Log("Произошла ошибка "+E.Message);
end;
  Log("Конец функции");
end;

procedure Ts1.Log(str:AnsiString); stdcall;
begin
   LogLst:=TStringList.Create;
   if (FileExists("WLog.txt")) then LogLst.LoadFromFile("WLog.txt");
   LogLst.Add(str);
   LogLst.SaveToFile("WLog.txt");
end;

initialization
{ Invokable classes must be registered }
  InvRegistry.RegisterInvokableClass(TS1);
end.


Код для S1Intf.pas
unit S1Intf;

interface

uses InvokeRegistry, Types, XSBuiltIns, Unit1;

type

 { Invokable interfaces must derive from IInvokable }
 TArrString = array of string;
 IS1 = interface(IInvokable)
 ["{181AF89B-CDAC-43FE-AF7F-83660617C558}"]

 function GetTT(d:integer): TArrString; stdcall;
 function GiveX2(d:integer): integer; stdcall;
 function GetDataFromBase(s:AnsiString): AnsiString; stdcall;
   { Methods of Invokable interface must not use the default }
   { calling convention; stdcall is recommended }
 end;

implementation

initialization
 { Invokable interfaces must be registered }
 InvRegistry.RegisterInterface(TypeInfo(IS1));

end.


Код для Unit1
unit Unit1;

interface

uses
 SysUtils, Classes, HTTPApp, InvokeRegistry, WSDLIntf, TypInfo,
 WebServExp, WSDLBind, XMLSchema, WSDLPub, SOAPPasInv, SOAPHTTPPasInv,
 SOAPHTTPDisp, WebBrokerSOAP, FIBDatabase, pFIBDatabase, DB, FIBDataSet,
 pFIBDataSet;

type
 TWM = class(TWebModule)
   HTTPSoapDispatcher1: THTTPSoapDispatcher;
   HTTPSoapPascalInvoker1: THTTPSoapPascalInvoker;
   WSDLHTMLPublish1: TWSDLHTMLPublish;
   FbDatabase: TpFIBDatabase;
   FbTransRead: TpFIBTransaction;
   FbTransWrite: TpFIBTransaction;
   FbFirms: TpFIBDataSet;
   FbFirmsFIRMA: TFIBStringField;
   FbFirmsFIRMKOD: TFIBSmallIntField;
   FbFirmsFIRMNAME: TFIBStringField;
   FbFirmsFIRMPASS: TFIBStringField;
   procedure WebModule1DefaultHandlerAction(Sender: TObject;
     Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
   procedure WebModuleCreate(Sender: TObject);
   procedure WebModuleDestroy(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 WM: TWM;

implementation

{$R *.dfm}

procedure TWM.WebModule1DefaultHandlerAction(Sender: TObject;
 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
 WSDLHTMLPublish1.ServiceInfo(Sender, Request, Response, Handled);
end;

procedure TWM.WebModuleCreate(Sender: TObject);
begin
FbDatabase.Connected:=true;
  FbFirms.Active:=true;
end;

procedure TWM.WebModuleDestroy(Sender: TObject);
begin
       if (FbDatabase.Connected) then
       begin
               if (FbTransRead.InTransaction) then FbTransRead.Rollback();
               if (FbTransWrite.InTransaction) then FbTransWrite.Rollback();
               FbDatabase.CloseDataSets();
               FbDatabase.Close();
       end;
end;
end.


Для клиентской части код нужен?

PS. Не стесняйтесь обзывать меня балбесом, но только помогите понять как писать вебсерверы с БД :)


 
Anatoly Podgoretsky ©   (2010-04-13 16:53) [8]

Разве TS1 можно не создавать?


 
Rusland ©   (2010-04-13 17:27) [9]


> Разве TS1 можно не создавать?


Anatoly Podgoretsky, не знаю даже что ответить... Этот код генерирует сам BDS, если выбрать File -> New -> Other... -> WebServices -> SOAP Server Application (я лишь пытаюсь прикрутить подключение к БД).

Если нужно создавать TS1, то где и как?

Хочу заметить, что функция GiveX2 нормально вызывается из клиентского приложения и возвращает то что надо (исходное число умноженное на 2).


 
Плохиш ©   (2010-04-13 19:26) [10]


> Rusland ©   (13.04.10 16:49) [7]

А теперь переноси всё своё барахло из WebModule в реализацию своего интерфейса TS1. Ибо, делфи создаёт наследника WebModule не для того, что бы туда не думая всякий мусор пихали.


 
Плохиш ©   (2010-04-13 19:35) [11]


> Anatoly Podgoretsky ©   (13.04.10 16:12) [6]

CreateForm у TWebApplication не создаёт никаких форм и не инициализирует втрой передаваемый параметр.


 
Anatoly Podgoretsky ©   (2010-04-13 20:21) [12]

> Плохиш  (13.04.2010 19:35:11)  [11]

Он создает datamodule


 
Плохиш ©   (2010-04-13 21:33) [13]


> Anatoly Podgoretsky ©   (13.04.10 20:21) [12]
>
> > Плохиш  (13.04.2010 19:35:11)  [11]
>
> Он создает datamodule

Вообще-то, в данном случае, WebModule, а уже в нём ищется требуемый интерфейс и создаётся компонент с реализацией.


 
Плохиш ©   (2010-04-13 21:36) [14]


> Он создает datamodule

Кстати, у автора никаких datamodule нету ;-)


 
Anatoly Podgoretsky ©   (2010-04-13 21:40) [15]

> Плохиш  (13.04.2010 21:36:14)  [14]

TWebModule наследник от Тdatamodule


 
Плохиш ©   (2010-04-14 00:24) [16]


> Anatoly Podgoretsky ©   (13.04.10 21:40) [15]
> TWebModule наследник от Тdatamodule

Да.
Но, у автора проблема в том, что он наивно думает, что у webapplication CreateForm делает то же самое, что и в vcl, а она только регистрирует единственный класс webmodule в проекте. Создаётся его экземпляр уже в методе Run, а его переменная WM никогда не инициализируется.

PS. О создании веб-приложений очень подробно расписано в руководстве разработчика, там эта тема примерно четверть руководства занимает.


 
Rusland ©   (2010-04-14 14:47) [17]

Плохиш,

> А теперь переноси всё своё барахло из WebModule в реализацию
> своего интерфейса TS1. Ибо, делфи создаёт наследника WebModule
> не для того, что бы туда не думая всякий мусор пихали.

То есть неиспользовать webmodule, а создавать все компоненты ручками? Типа такого?
function Ts1.GetDataFromBase2(s:AnsiString): AnsiString; stdcall;
var FbDatabase: TpFIBDatabase;
   FbTransRead: TpFIBTransaction;
   FbTransWrite: TpFIBTransaction;
   FbFirms: TpFIBDataSet;
   FbSql: TpFibQuery;
begin
  Log("Начало функции");
FbDatabase:=TpFibDatabase.Create(nil);
try
  with FbDatabase.DBParams do
  begin
   Add("user_name="+"SYSDBA");
   Add("password="+"masterke");
   Add("lc_ctype="+"WIN1251");
  end;
  FbDatabase.DatabaseName:="C:\Ruslan\...\Base\avtobase.fdb";
  try
   FbDatabase.Connected := True;
   FbTransRead:=TpFibTransaction.Create(nil);
   try
    FbTransRead.DefaultDatabase:=FbDatabase;
    FbSql:=TpFibQuery.Create(nil);
   .................................
//итд?



>Да.
>Но, у автора проблема в том, что он наивно думает, что у webapplication >CreateForm делает то же самое, что и в vcl, а она только регистрирует >единственный класс webmodule в проекте. Создаётся его экземпляр уже в >методе Run, а его переменная WM никогда не инициализируется.

Да, именно так я и думал.


> PS. О создании веб-приложений очень подробно расписано в
> руководстве разработчика, там эта тема примерно четверть
> руководства занимает.

Вы имеете ввиду книгу? Вот эту www.ozon.ru/context/detail/id/1135615/ ?
Сейчас скачаю, почитаю. Спасибо за наводку.


 
Плохиш ©   (2010-04-14 17:02) [18]


> Rusland ©   (14.04.10 14:47) [17]
> То есть неиспользовать webmodule, а создавать все компоненты
> ручками? Типа такого?

Будь проще. Оставь webmodule так, как его создало, пусть занимается общим управлением.
Удали свой TS1 и создай его заново, но не как "SOAP Server Interface", а как "SOAP Server Data Module".

> Вы имеете ввиду книгу? Вот эту www.ozon.ru/context/detail/id/1135615/?
> Сейчас скачаю, почитаю. Спасибо за наводку.

Я имел в виду руководство из комплекта поставки, но и этой надеюсь достаточно будет, для начала.


 
Плохиш ©   (2010-04-14 17:04) [19]

А ветке место в "Corba и COM" :-)


 
Игорь Шевченко ©   (2010-04-14 17:18) [20]

Плохиш ©   (14.04.10 17:04) [19]

Раньше надо было говорить


 
Rusland ©   (2010-04-16 17:43) [21]


> Будь проще. Оставь webmodule так, как его создало, пусть
> занимается общим управлением.
> Удали свой TS1 и создай его заново, но не как "SOAP Server
> Interface", а как "SOAP Server Data Module".

Плохиш, большое вам спасибо. Помогло! Теперь не придется вручную создавать компоненты.

Уважаемые мастера, подскажите как передавать целиком датасет? (пока что только строку умею передавать из БД) Где про это почитать?


 
Плохиш ©   (2010-04-16 18:21) [22]

DeveloperGuide.pdf от Delphi7 разделы начиная с "Ch29: Using client datasets".

Ты вроде книгу скачал, неужели там нет этого?


 
Rusland ©   (2010-04-20 16:36) [23]

Плохиш, "чукча не читатель, чукча писатель" :-D
Сейчас буду более внимательно читать.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2012.02.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.004 c
3-1272018364
снежок
2010-04-23 14:26
2012.02.12
Помогите с решением запроса


11-1241182092
DmitriyR
2009-05-01 16:48
2012.02.12
KOL & WinCE


15-1319498590
Kerk
2011-10-25 03:23
2012.02.12
Умер John McCarthy


6-1250609834
raslmc
2009-08-18 19:37
2012.02.12
Проблема с WebModule1


15-1319446323
Dennis I. Komarov
2011-10-24 12:52
2012.02.12
Что за моде пошла - инсталлить exe в AppData?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский