PDA

View Full Version : مشکل DB Express در DataSnap 2009



mehdi_7
یک شنبه 19 مهر 1388, 19:28 عصر
سلام
من یک برنامه datasnap نوشتم با دلفی 2009
در برنامه مربوط به کلاینت، از DB express استفاده کرده ام.
برنامه به خوبی کار می کند.
اما موقعی که برنامه کلاینت را روی یک کامپیوتر دیگر، در شبکه قرار می دهم، اجرا نمی شود.
به نظرم به علت نبودن db express روی کامپیوتر دیگر هست. چرا که زمانی که دلفی 2009 را روی کامپیوتر دیگر نصب می کنم، برنامه اجرا می شود.
سوال من این هست، آیا باید روی کامپیوترهای دیگر در شبکه (که می خواهم برنامه کلاینت را روی آنها قرار بدهم) نرم افزار دلفی 2009 را نصب کنم؟! به نظر منطقی نمی رسد.
مشکل کار کجاست؟

young_man1365
یک شنبه 19 مهر 1388, 20:42 عصر
همونطور که خود شما گفتید منطقی نیست که برای اجرا دلفی نصب باشه. من با dbgo کار کردم ولی فکر کنم اصول کار یکی باشه. برای نصب روی کامپیوترهای دیگر شبکه لازمه که driver اتصال dbexpress که معمولا" یه فایل dll که در پوشه system32 ذخیره میشه روی باقی سیستم ها نصب بشه. البته نصب data source (با توجه به اینکه برنامه روی سیستم جدید به یه پایگاه راه دور وصل میشه) نباید فراموش بشه.
راه حل آسون میتونه ساختن یه فایل setup با windows installer یا install Aware باشه که دیگه نیازی به کار دوباره نباشه. البته استفاده از install aware خیلی آسون تره و تنظیمات آماده واسه این کارو داره(ODBC driver & ODBC data source).

موفق باشی

vcldeveloper
دوشنبه 20 مهر 1388, 06:06 صبح
اصولا وقتی برنامه DataSnap میسازید، از DBExpress در سمت سرور استفاده میشه، و از ClientDataset در سمت کلاینت.

برای DBexpress به ازاء هر درایوری که برای اتصال به بانک استفاده کردید، یک DLL وجود داره، که اون DLL رابط بین DBExpress با موتور بانک اطلاعاتی مورد نظر هست. این DLL باید به همراه برنامه به سیستم کاربر منتقل بشه. ClientDataset هم به طور عادی به یک DLL با نام Midas.dll نیاز داره، که می تونید بجای آن، یونیت MidasLib را به uses فرم مورد نظرتان اضافه کنید، تا نیاز به این DLL نباشه.

mehdi_7
دوشنبه 20 مهر 1388, 10:56 صبح
همونطور که می دونید، dataSnap در دلفی 2009 متفاوت هست با دلفی 7
روش ساخت هم تقریبا فرق می کنه.

vcldeveloper
دوشنبه 20 مهر 1388, 22:48 عصر
همونطور که می دونید، dataSnap در دلفی 2009 متفاوت هست با دلفی 7
روش ساخت هم تقریبا فرق می کنه.
تفاوت در شیوه اتصال و داده های رد و بدل شده هست. چگونگی توزیع آن فرقی نداره. همان کارهایی که گفتم، انجام بدید.

mehdi_7
سه شنبه 21 مهر 1388, 19:54 عصر
به هر حال در datasnap 2009 کامپننت Db Express در سمت کلاینت قرار می گیره.
فایل middas.dll رو روی کامپیوتر کلاینت در system32 کپی کردم. باز هم برنامه اجرا نشد.
جالب آن است که اگر دلفی رو نصب کنم روی کامپیوتر کلاینت، برنامه اجرا می شود.
آیا DB Express یک برنامه Setup نداره که تنهایی روی سیستم نصب بشه؟ نمی خوام همه دلفی رو نصب کنم. اصلا منطقی نیست همچین کاری!

vcldeveloper
سه شنبه 21 مهر 1388, 23:41 عصر
به هر حال در datasnap 2009 کامپننت Db Express در سمت کلاینت قرار می گیره.
DBExpress یک مکانیزم اتصال به بانک اطلاعاتی هست. DataSnap یک مکانیزم اتصال لایه های مختلف یک نرم افزار چند لایه و تبادل داده بین این لایه ها هست.

در نسخه های قبل از دلفی 2009، DataSnap از COM برای تبادل داده ها بین لایه ها استفاده می کرد. در دلفی 2009 و نسخه های بعد از آن، این کار از طریق سوکت با استفاده از Indy انجام میشه. تبادل داده ها با فرمت JSON صورت میگیره. اشیائی که بین لایه ها رد و بدل میشه، اشیاء DBExpress هستند.

در DataSnap، لایه میانی به سرور بانک اطلاعاتی متصل میشه، و کلاینت ها دسترسی مستقیم به بانک اطلاعاتی ندارند، بلکه داده ها را از DatasetProviderهای موجود در لایه میانی دریافت می کنند، آنها را بطور موقت در ClientDataset نگهداری می کنند، و از ClientDataset برای نمایش داده ها، یا ویرایش آن استفاده می کنند. در صورت تغییر داده ها، تغییرات از طریق ClientDataset به DatasetProvider در لایه میانی ارسال میشه، و از آنجا بر روی بانک اطلاعاتی اعمال میشه.

در DataSnap 2009 برای اتصال کلاینت به لایه میانی، از TSQLConnection استفاده میشه. TSQLConnection برای حالت Datasnap نیاز به درایوری که بصورت DLL همراه برنامه باشه، نداره. یک DSProviderConnection به ازاء هر DatasetProvider در لایه میانی، در سمت کلاینت قرار میگیره، و به TSQLConnection وصل میشه.
ClientDatasetهای سمت کلاینت به این DSProviderConnectionها وصل میشند، و داده ها را از اینها دریافت می کنند.

کار اصلی بانک اطلاعاتی در لایه میانی انجام میشه. در آنجا شما برای اتصال به بانک اطلاعاتی، یک TSQLConnection استفاده می کنید، که به یکی از درایورهای بانک اطلاعاتی موجود وصل میشه، و Datasetهای شما به این TSQLConnection وصل میشند. DatasetProviderهای شما هم به اون Dataset ها وصل میشند.
پس عملا اتصال به بانک اطلاعاتی فقط در لایه میانی اتفاق میافته، و برنامه Datasnap Server شما که در این لایه قرار داره، برای اجرا نیاز به DLL مربوط به درایور موتور بانک اطلاتی مورد نظرش داره. مثلا در صورت استفاده از MS SQL Server به عنوان بانک اطلاعاتی، اسم درایور مورد استفاده dbxmss.dll هست. این فایل باید به همراه برنامه روی سیستمی که نقش لایه میانی را بازی میکنه، منتقل بشه.

شما در سمت کلاینت به این DLL نیاز ندارید. در سمت کلاینت به Midas.dll برای ClientDataset نیاز دارید که می تونید بجای آن، از یونیت MidasLib استفاده کنید.

mehdi_7
چهارشنبه 22 مهر 1388, 02:12 صبح
ببینید، من یک سرور ماژول دارم که فقط یک تابع ساده داره



unit Unit1;
interface
uses
SysUtils, Classes, DSServer;
type
TDSServerModule1 = class(TDSServerModule)
private
{ Private declarations }
public
{ Public declarations }
function test : string;
end;
var
DSServerModule1: TDSServerModule1;
implementation
{$R *.dfm}
{TDSServerModule1}
function TDSServerModule1.test;
begin
result:= 'hello world';
end;
end.


حالا در فرم مربوط به سرور این کامپننت ها رو دارم

DSTCPServerTransport1
DSServer1
DSServerClass1

و این خاصیت ها رو هم تنظیم کردم
DSTCPServerTransport1.server:=DSServer1
DSServerClass1.server:=DSServer1

کد مربوط به این فرم (سرور) این جوری هست



unit serverfirmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DSCommonServer, DSServer, DSTCPServerTransport, StdCtrls;
type
TForm2 = class(TForm)
Label1: TLabel;
DSTCPServerTransport1: TDSTCPServerTransport;
DSServer1: TDSServer;
DSServerClass1: TDSServerClass;
procedure DSServerClass1GetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses Unit1;
{$R *.dfm}
procedure TForm2.DSServerClass1GetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
begin
PersistentClass:= TDSServerModule1;
end;
end.


در فرم کلاینت هم از یک label و یک SQLConnection1 استفاده کردم
این خاصیت رو هم اینجوری تنظیم کردم
SQLConnection1.Driver := Datasnap

این هم کد مربوط به صفحه کلاینت



unit clientformMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, WideStrings, DbxDatasnap, DB, SqlExpr, StdCtrls;
type
TForm3 = class(TForm)
SQLConnection1: TSQLConnection;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses clientclass;
{$R *.dfm}
procedure TForm3.Button1Click(Sender: TObject);
var
mehdi: TDSServerModule1Client;
begin
mehdi:= TDSServerModule1Client.Create(SQLConnection1.DBXCo nnection);
try
label2.Caption := mehdi.test;
finally
mehdi.Free;
end;
end;
end.

این هم یونت دیگری که کلاینت از اون استفاده میکنه



unit clientclass;
interface
uses DBXCommon, Classes, SysUtils, DB, SqlExpr, DBXDBReaders;
type
TDSServerModule1Client = class
private
FDBXConnection: TDBXConnection;
FtestCommand: TDBXCommand;
public
constructor Create(ADBXConnection: TDBXConnection);
destructor Destroy; override;
function test: string;
end;
implementation
function TDSServerModule1Client.test: string;
begin
if FtestCommand = nil then
begin
FtestCommand := FDBXConnection.CreateCommand;
FtestCommand.CommandType := TDBXCommandTypes.DSServerMethod;
FtestCommand.Text := 'TDSServerModule1.test';
FtestCommand.Prepare;
end;
FtestCommand.ExecuteUpdate;
Result := FtestCommand.Parameters[0].Value.GetWideString;
end;

constructor TDSServerModule1Client.Create(ADBXConnection: TDBXConnection);
begin
inherited Create;
if ADBXConnection = nil then
raise EInvalidOperation.Create('Connection cannot be nil. Make sure the connection has been opened.');
FDBXConnection := ADBXConnection;
end;

destructor TDSServerModule1Client.Destroy;
begin
FreeAndNil(FtestCommand);
inherited;
end;
end.


با کلیک روی باتون، کلمه hello world در label نوشته می شه به همین سادگی.
و همون طور که دیدید، TSOLConnection در لایه کلاینت قرار گرفت!

vcldeveloper
چهارشنبه 22 مهر 1388, 10:46 صبح
و همون طور که دیدید، TSOLConnection در لایه کلاینت قرار گرفت! این رو در پست قبل توضیح دادم:


در DataSnap 2009 برای اتصال کلاینت به لایه میانی، از TSQLConnection استفاده میشه. TSQLConnection برای حالت Datasnap نیاز به درایوری که بصورت DLL همراه برنامه باشه، نداره. یک DSProviderConnection به ازاء هر DatasetProvider در لایه میانی، در سمت کلاینت قرار میگیره، و به TSQLConnection وصل میشه.
ClientDatasetهای سمت کلاینت به این DSProviderConnectionها وصل میشند، و داده ها را از اینها دریافت می کنند.

ببینید، من یک سرور ماژول دارم که فقط یک تابع ساده دارهاز کدام نسخه از دلفی 2009 استفاده می کنید؟ دلفی 2009 اولیه یک باگ در رابطه با DataSnap 2009 داره که لازم هست فایل های dbxconnections.ini و dbxdrivers.ini به همراه Server و Client به سیستم مقصد منتقل بشند.
این باگ در Update 2 از دلفی 2009 برطرف شده، و اگر Update 2 را نصب کرده باشید، برای این پروژه ایی که در پست قبل نوشتید، و اتصال بانک اطلاعاتی نداره، نباید نیاز به انتقال فایلی به همراه فایل های EXE مربوط به سرور و کلاینت داشته باشید.

mehdi_7
چهارشنبه 22 مهر 1388, 12:42 عصر
این نسخه از دلفی که من دارم، Update نشده هست!
در حالت update نشده، فایل های dbxconnections.ini و dbxdrivers.ini رو باید کجا کپی کنم در کامپیوتر کلاینت؟ در system32 ؟ یا در این فولدر باید ذخیره بشه:
C:\Documents and Settings\All Users\Documents\RAD Studio\dbExpress

vcldeveloper
چهارشنبه 22 مهر 1388, 12:56 عصر
فایل های INI را در هر دو سیستم Server و Client در پوشه ایی که برنامه قرار داره، کپی کنید.

البته بهتر هست که دلفی خودتان را Update کنید. Updateهای 3 و 4 بسیاری از باگ های گزارش شده کاربران را برطرف کردند.

mehdi_7
چهارشنبه 22 مهر 1388, 14:53 عصر
هر دو تا فایل ini گفته شده رو در پوشه مربوطه (در کلاینت) کپی کردم، اما باز هم برنامه اجرا نشد!
یک چیزی این وسط عجیب هست.
آخه وقتی دلفی نصب میشه، چه کار میکنه. چطوری میشه که در اون صورت برنامه اجرا میشه! شاید یک تغییراتی در رجیستری بوجود می یاره
وگرنه من ، همه فایلهای مربوط به db express رو آوردم توی کامپیوتر کلاینت کپی کردم!

vcldeveloper
چهارشنبه 22 مهر 1388, 21:34 عصر
آخه وقتی دلفی نصب میشه، چه کار میکنه. چطوری میشه که در اون صورت برنامه اجرا میشه! شاید یک تغییراتی در رجیستری بوجود می یاره
وگرنه من ، همه فایلهای مربوط به db express رو آوردم توی کامپیوتر کلاینت کپی کردم!
شما مطمئن هستید که برنامه شما فقط از DataSnap استفاده کرده، و غیر از اون کدی که در پست قبلی گذاشتید، چیز دیگه ایی نداره؟
پیام خطایی که دریافت می کنید، دقیقا چی هست؟ در زمان اجرای برنامه در داخل IDE دلفی، از منوی مربوط به پنجره های Debug، پنجره مربوط به Moduleها را باز کنید، و ببینید برنامه چه Moduleهایی را در هنگام اجرا لود می کند. بخش عمده این Moduleها مربوط به ویندوز هستند. اگر Module ناشناسی دیدید، بررسی کنید آن فایل مربوط به چی هست، و آیا در کامپیوتر مقصد وجود دارد یا نه.

mehdi_7
پنج شنبه 23 مهر 1388, 02:30 صبح
آقای کشاورز ممنون از اینکه با صبر و حوصله مرا راهنمایی کردید.
مشکل حل شد.
فایل های dbxdrivers.ini و dbxconnections.ini را در پوشه مربوط به برنامه (بغل دستش) کپی کردم.
فایل middas.dll رو هم در system32 کپی کردم.

بدین ترتیب برنامه اجرا شد. مرسی