基于Midas 技术的多层应用开发包!(0分)

  • 主题发起人 vinson_zeng
  • 开始时间
我现在碰到服务器器端发布问题,就是数据当发布的目录不同时,服务器不会生成另外一个session副本。。把头都高晕了。请问各位大虾有解决的办法吗?
 
To xchen.d:
不好意思,你的问题“ 就是数据当发布的目录不同时,服务器不会生成另外一个session副本”,有点看不懂,能详细点吗?
 
我认为midas的好处在于它的透明性,可控制性,当然对于大项目来言他是不合适的。但事实上大项目并不适合当今众多小客户。所以我是用了他,对于客户采用分时是容易解决[请vinson_zeng不要生气不是否定你的成果,呵呵]。我个人认为关健在于服务器接口功能的扩展才是实现midas的价值。谁能说没有vcl的delphi能有多好,扯远了。。。
 
To xchen.d:
在UA SDK 中,你所说的“关健在于服务器接口功能的扩展才是实现midas的价值”
它是一种个性化的处理过程代码,也就是某一个 服务对象的某个Method !这是完全
支持的!我说 UA SDK 是基于 midas 技术,只不过我用了 TClientDataSet ,
TDataSetProvider 两个组件,因为我现在还没有一个 TClientDataSet 更好的
数据容器!
 
中间服务器端是需要从性能, 稳定多方面去考虑, 比如, server对象state的保存和钝化, session object cache的共享, 对与长事务的处理.
用CS的思路去做多层肯定会有问题的. java在服务器端的成功很大因素不是他提供了一个基本的framework, 而是他提供了很多分布式design pattern, 供开发人员根据项目情况去选择实施, 比如, 用来减少远程交互的session facade pattern, 实现数据接口portable的data access object pattern.
 
to vinson_zeng:
1。我在rmd的create 中动态配置数据库目录然后再connect
2。制作服务器安装程序之后,安装了服务器并运行服务器
3。运行客户端是出现不能复制数据库的错误。。呵呵
 
DbConnection 也是一个Entry 对象,老大!
它只不过是在你的AppServer 进行内部调用,
你在Create 就要一个Session ,那也太浪费了,
只有事务处理请求,才可以从 DbConnection Pooling 中
Lock 一个 DbConnection Entry 啊,你说呢!
 
中间服务器端是需要从性能, 稳定多方面去考虑, 比如, server对象state的保存和钝化, session object cache的共享, 对与长事务的处理。
server对象 是没有 state 的吧!
长事务的处理好让我头疼!
不是“用CS的思路去做多层肯定会有问题的” 而是要新技术兼容以前的技术平台!
framework 也好,design pattern也好,能实用就更好!
Com/Dcom /Dcom+ 这概念弄的高深没策,可不知害了多少 同行!

 
server对象 是没有 state 的吧!
midas里没有, .net remoting和EJB都有.
长事务的处理好让我头疼!
长事务一般用versioning 和Optimistic Locking去解决, 在JAVA里的一些framework都提供了这方面的支持.
说白了, 就是delphi包装的太多了. 在强调易用性的时候很难兼顾其他问题
 
TO vinson_zeng
因为在服务器端动态配置数据库路径,没办法。所以每一次CLIENT REQUEST 都要到DbConnection Pooling 中Lock 一个 DbConnection Entry 这是没办法而为之呀!更不用说我是个新手。看到那些接口事件我的头就直冒金星。。呵呵。另外,我现在是做金钱的小弟,‘不做老大已经很久了‘。。。哈哈.
不过我赞同您的'framework 也好,design pattern也好,能实用就更好!Com/Dcom /Dcom+ 这概念弄的高深没策,可不知害了多少 同行!',在96年的时候有一个朋友对我说学编程怎么能不学COM+,还拿一本厚厚书给我看。天啊。。。后来JAVA热起来又来跟我讲。。害人不浅。。呵呵。。我们是在聊天吗?!
 
我把我在B计划中写的贴子贴过来好了.
http://www.delphibbs.com/keylife/images/g28/Stru.rar (业务层结构图)
(内存篇)
  作为一个中间件,其要求必须非常严格,毕竟,它是整系统的栋梁,打个比喻来说,它是上有老(SQLSERVER),下有小(客户端系统),打开五个客户端和打开五十个客户端远远不同,在这一点,我们就要讲一讲关於内存方面的设计和注意方面。
 合理使用内存就象借钱一样,有借有还,再借不难。如果我们老是申请内存而不释放,系统很快就会当机了。所以,以下几点在设计中间件是大家要注意一下。
  1. 主界面尽量简单,仅仅是作为一个监视系统的运作情况即可,无需太花哨或太多功能。
  2. 内存用完必须释放,否则你就会看到你的系统所占的内存越来越多,直到当机。
  3. 能动态建立的就动态建立。当然“动态”和“整体速度”有点成反比,但它和“整体内存使用”成正比。
  4. 把业务规则封装成DLL,动态加载。不同的用户需要的规则不同,同一个用户不需要把所用的规则都同时加载。
  5. 指针的本质意义是指本机的内存地址,所以,传送指针意义不大,也有导致其它想不到的事情出现。(包括:Pointer,pChar等等)。
  6. 尽量少用第三方控件(Component),尽量不引用无作用单元(UNIT)
  7. SQL语句尽量不要包含在系统程序里,最好让它独立出来。再用另一个程序来管理。
  8. 中间件的管理可以用另一个程序远程管理。
  9. 还是一句,有借有还,再借不难。
大家有什么更好的建议,一起来探讨一下。
 
部分原碼 (一)
unit DataServer_form;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, swServer2_TLB, Provider, ADODB, DB, hmUniKey,
Variants, hmOleVariant, dmBaseModule, dmBaseService, StdVcl,
hmClientDataSet, hmADQ, hmADC;
type
TDataServer2 = class(TRemoteDataModule, IDataServer2)
dspTest: TDataSetProvider;
SqlLang: TADOQuery;
Connection: TADOConnection;
mdLibrary: TADOQuery;
cdsDelta: THMClientDataSet;
Query: THMADQ;
Pub1: THMClientDataSet;
Cmd: THMADC;
Pub2: THMClientDataSet;
Pub3: THMClientDataSet;
procedure RemoteDataModuleCreate(Sender: TObject);
private
FDataBase: string;
FUKI: string;
FOle: THMOleVariant;
FParams: THMOleVariant;
FBaseService: TBaseService;
protected
class procedure UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
override;
function DataModule(ModuleIndex: Integer;
Param: OleVariant;
var Data, Msg: OleVariant): WordBool;
safecall;
function Get_Database: WideString;
safecall;
procedure Set_Database(const Value: WideString);
safecall;
function DefaultModule(Param: OleVariant;
var Data, Msg: OleVariant): WordBool;
safecall;
function CreateModule(const BaseService: IBaseService;
ModuleIndex: integer): IBaseDataModule;
procedure OnLoadOleData(Sender: TObject;
Name: WideString);
public
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
procedure SetDefaultDatabase;
procedure DebugText(Msg: string);
property UKI: string read FUKI;
property Ole: THMOleVariant read FOle;
property OleParams: THMOleVariant read FParams;
end;

implementation
uses MainForm_form, swModuleIndex, dmSystemService;
{$R *.DFM}
class procedure TDataServer2.UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end
else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;

constructor TDataServer2.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FUKI := UniKeyInit;
FOle := THMOleVariant.Create;
FParams := THMOleVariant.Create;
Connection.ConnectionString := frmDataServer.ConnectionString;
SetDefaultDatabase;
FBaseService := TBaseService.Create(Self);
mdLibrary.SQL.Text := 'Select md_ID,md_moduleIndex,md_State,md_ModuleAddr from ' + LibUniKey;
mdLibrary.Open;
Inc(OnLineUserCount);
end;

destructor TDataServer2.Destroy;
begin
FBaseService.Free;
FOle.Free;
FParams.Free;
Dec(OnLineUserCount);
mdLibrary.Close;
inherited Destroy;
end;

function TDataServer2.CreateModule(const BaseService: IBaseService;
ModuleIndex: integer): IBaseDataModule;
var
Module: PModuleLibrary;
begin
if not mdLibrary.Locate('md_ModuleIndex', ModuleIndex, []) then
Exception.Create('服務器裝載出錯:DataMoudule(' + inttostr(ModuleIndex) + ') not found.');
if mdLibrary.FieldByName('md_State').AsInteger <> 1 then
Exception.Create('服務器裝載出錯:DataMoudule(' + inttostr(ModuleIndex) + ') not start.');
Module := Pointer(mdLibrary.FieldByName('md_ModuleAddr').AsInteger);
if (Module <> nil) then
Result := Module^.CreateDataModule(BaseService)
else
raise
Exception.Create('服務器裝載出錯:DataMoudule(' + inttostr(ModuleIndex) + ') not found.');
end;

function TDataServer2.DataModule(ModuleIndex: Integer;
Param: OleVariant;
var Data, Msg: OleVariant): WordBool;
var
FdmModule: IBaseDataModule;
begin
if ServiceState = srStart then
begin
try
FdmModule := CreateModule(FBaseService, ModuleIndex);
FdmModule.Module := ModuleIndex;
except
on E: Exceptiondo
begin
Result := False;
Msg := '服務器出錯:無法建立數據模組,' + E.Message;
exit;
end;
end;
end
else
begin
Msg := '服務器沒有啟動,請通知管理員.';
Result := False;
exit;
end;

try
FBaseService.Reset;
FOle.Clear;
FParams.Clear;
if not VarIsNull(Param) then
FParams.LoadFromOle(Param);
Result := FdmModule.Operation(Data, Msg);
if Result then
begin
case FBaseService.ReceiveDataType of
rdNoData:
begin
Data := Null
end;
rdDefault:
begin
Data := dspTest.Data;
end;
rdCustom:
begin
Ole.SaveToOle(Data);
Ole.Clear;
end;
else
begin
// Data:=Data;
rdResult;
end;
end;
end;
FdmModule := nil;
FOle.Clear;
FParams.Clear;
Query.Close;
if cdsDelta.Active then
cdsDelta.EmptyDataSet;
cdsDelta.Close;
if Pub1.Active then
Pub1.EmptyDataSet;
if Pub2.Active then
Pub2.EmptyDataSet;
if Pub3.Active then
Pub3.EmptyDataSet;
Pub1.Close;
Pub2.Close;
Pub3.Close;
except
on E: Exceptiondo
begin
Msg := '服務器裝載出錯,請通知管理員,錯誤信息:' + E.Message;
Result := False;
end;
end;
end;

function TDataServer2.DefaultModule(Param: OleVariant;
var Data, Msg: OleVariant): WordBool;
begin
Result := DataModule(dmDefault, Param, Data, Msg);
end;

procedure TDataServer2.DebugText(Msg: string);
begin
//if frmDataServer.Status.CheckSQL then
frmDataServer.Status.AddItem(Msg);
end;

function TDataServer2.Get_Database: WideString;
begin
Result := FDatabase;
end;

procedure TDataServer2.Set_Database(const Value: WideString);
begin
FDataBase := Value;
Connection.DefaultDatabase := Value;
DebugText('Change Database:' + Value);
end;

procedure TDataServer2.SetDefaultDatabase;
begin
FDataBase := frmDataServer.DafaultDataBase;
Connection.DefaultDatabase := FDataBase;
end;

procedure TDataServer2.RemoteDataModuleCreate(Sender: TObject);
begin
cdsDelta.OnLoadOleData := OnLoadOleData;
Pub1.OnLoadOleData := OnLoadOleData;
Pub2.OnLoadOleData := OnLoadOleData;
Pub3.OnLoadOleData := OnLoadOleData;
end;

procedure TDataServer2.OnLoadOleData(Sender: TObject;
Name: WideString);
begin
if Sender is THMClientDataSet then
begin
(Sender as THMClientDataSet).Close;
(Sender as THMClientDataSet).Data := FParams[Name];
(Sender as THMClientDataSet).Open;
end
else
raise Exception.Create('(OnLoadOleData)Sender is not a THMClientDataSet');
end;

initialization
TComponentFactory.Create(ComServer, TDataServer2,
Class_DataServer2, ciMultiInstance, tmApartment);
end.
 
部分原碼(二)
unit dmBaseModule;
interface
uses
Classes, SysUtils, Variants, hmOleDataSet, hmOleVariant;
type
IBaseOle = interface;
IBaseService = interface
['{D40CB2CF-23FF-4C41-BB7E-C9FCD28AE7E7}']
function GetSqlLanguage(Index: integer;
var Params, Body: WideString): Boolean;
stdcall;
function InTranstion: WordBool;
stdcall;
function GetInfo: WideString;
stdcall;
procedure ShowMessage(Msg: WideString);
stdcall;
procedure OpenQuery(Sql: WideString);
stdcall;
procedure CloseQuery;
stdcall;
procedure Execute(Sql: WideString);
stdcall;
procedure GetFieldNames(TableName: WideString;
var FieldNames: WideString);
stdcall;
procedure begin
Trans;
stdcall;
procedure CommitTrans;
stdcall;
procedure RollbackTrans;
stdcall;
procedure ApplyUpdates(const Delta: OleVariant;
TableName, KeyField: WideString);
stdcall;
procedure ApplyUpdatesWithOle(const DeltaName, TableName, KeyField: WideString);
stdcall;
procedure ApplyUpdatesWithDataSet(const DataSet: integer;
TableName, KeyField: WideString);
stdcall;
procedure ReceiveDataWithDefault;
stdcall;
procedure ReceiveDataWithCustom;
stdcall;
procedure ReceiveDataWithResult;
stdcall;
procedure ReceiveDataWithNoData;
stdcall;
procedure RaiseError(Msg: WideString);
stdcall;
procedure DropTable(TableName: WideString);
stdcall;
function UniKey: WideString;
stdcall;
function GetQuery: IHMOleADOQuery;
stdcall;
function GetDataSet(Index: integer): IHMOleClientDataSet;
stdcall;
function GetOle: IBaseOle;
stdcall;
function GetParams: IHMOleVariant;
stdcall;
function GetRecordsAffected: integer;
stdcall;
property RecordsAffected: integer read GetRecordsAffected;
property Query: IHMOleADOQuery read GetQuery;
property DataSet[index: integer]: IHMOleClientDataSet read GetDataSet;
property Ole: IBaseOle read GetOle;
property Params: IHMOleVariant read GetParams;
end;

IBaseDataModule = interface
['{0CEF4911-3E0C-4AC9-AAD7-69CA907E3979}']
function GetModuleInfo: WideString;
stdcall;
function GetBaseService: IBaseService;
stdcall;
procedure SetBaseService(const Value: IBaseService);
stdcall;
function GetModule(): integer;
stdcall;
procedure SetModule(const value: integer);
stdcall;
function Operation(var Data, Msg: OleVariant): WordBool;
stdcall;
procedure LoadOleParam(const Param: OleVariant);
stdcall;
property BaseService: IBaseService read GetBaseService write SetBaseService;
property Module: integer read GetModule write SetModule;
property ModuleInfo: WideString read GetModuleInfo;
end;

IDataModuleInfo = interface
['{B1B99EE8-E0B5-475C-9E21-92E6B416065E}']
function GetModuleName: WideString;
stdcall;
function GetVersion: Widestring;
stdcall;
function GetDesignner: Widestring;
stdcall;
function GetMemo: Widestring;
stdcall;
function GetLastUpdate: WideString;
stdcall;
function GetModuleIndex: Integer;
stdcall;
property ModuleIndex: Integer read GetModuleIndex;
end;

IBaseOle = interface
procedure AddDspAsName(Name: WideString);
stdcall;
procedure Clear;
stdcall;
function GetValue(Name: WideString): OleVariant;
stdcall;
procedure SetValue(Name: WideString;
Value: OleVariant);
stdcall;
property Value[Name: WideString]: OleVariant read GetValue write SetValue;
end;

implementation
end.
 
部分原碼(三)
unit dmBaseModule;
interface
uses
Classes, SysUtils, Variants, hmOleDataSet, hmOleVariant;
type
IBaseOle = interface;
IBaseService = interface
['{D40CB2CF-23FF-4C41-BB7E-C9FCD28AE7E7}']
function GetSqlLanguage(Index: integer;
var Params, Body: WideString): Boolean;
stdcall;
function InTranstion: WordBool;
stdcall;
function GetInfo: WideString;
stdcall;
procedure ShowMessage(Msg: WideString);
stdcall;
procedure OpenQuery(Sql: WideString);
stdcall;
procedure CloseQuery;
stdcall;
procedure Execute(Sql: WideString);
stdcall;
procedure GetFieldNames(TableName: WideString;
var FieldNames: WideString);
stdcall;
procedure begin
Trans;
stdcall;
procedure CommitTrans;
stdcall;
procedure RollbackTrans;
stdcall;
procedure ApplyUpdates(const Delta: OleVariant;
TableName, KeyField: WideString);
stdcall;
procedure ApplyUpdatesWithOle(const DeltaName, TableName, KeyField: WideString);
stdcall;
procedure ApplyUpdatesWithDataSet(const DataSet: integer;
TableName, KeyField: WideString);
stdcall;
procedure ReceiveDataWithDefault;
stdcall;
procedure ReceiveDataWithCustom;
stdcall;
procedure ReceiveDataWithResult;
stdcall;
procedure ReceiveDataWithNoData;
stdcall;
procedure RaiseError(Msg: WideString);
stdcall;
procedure DropTable(TableName: WideString);
stdcall;
function UniKey: WideString;
stdcall;
function GetQuery: IHMOleADOQuery;
stdcall;
function GetDataSet(Index: integer): IHMOleClientDataSet;
stdcall;
function GetOle: IBaseOle;
stdcall;
function GetParams: IHMOleVariant;
stdcall;
function GetRecordsAffected: integer;
stdcall;
property RecordsAffected: integer read GetRecordsAffected;
property Query: IHMOleADOQuery read GetQuery;
property DataSet[index: integer]: IHMOleClientDataSet read GetDataSet;
property Ole: IBaseOle read GetOle;
property Params: IHMOleVariant read GetParams;
end;

IBaseDataModule = interface
['{0CEF4911-3E0C-4AC9-AAD7-69CA907E3979}']
function GetModuleInfo: WideString;
stdcall;
function GetBaseService: IBaseService;
stdcall;
procedure SetBaseService(const Value: IBaseService);
stdcall;
function GetModule(): integer;
stdcall;
procedure SetModule(const value: integer);
stdcall;
function Operation(var Data, Msg: OleVariant): WordBool;
stdcall;
procedure LoadOleParam(const Param: OleVariant);
stdcall;
property BaseService: IBaseService read GetBaseService write SetBaseService;
property Module: integer read GetModule write SetModule;
property ModuleInfo: WideString read GetModuleInfo;
end;

IDataModuleInfo = interface
['{B1B99EE8-E0B5-475C-9E21-92E6B416065E}']
function GetModuleName: WideString;
stdcall;
function GetVersion: Widestring;
stdcall;
function GetDesignner: Widestring;
stdcall;
function GetMemo: Widestring;
stdcall;
function GetLastUpdate: WideString;
stdcall;
function GetModuleIndex: Integer;
stdcall;
property ModuleIndex: Integer read GetModuleIndex;
end;

IBaseOle = interface
procedure AddDspAsName(Name: WideString);
stdcall;
procedure Clear;
stdcall;
function GetValue(Name: WideString): OleVariant;
stdcall;
procedure SetValue(Name: WideString;
Value: OleVariant);
stdcall;
property Value[Name: WideString]: OleVariant read GetValue write SetValue;
end;

implementation
end.
 
其中,原碼(一)是負責與客戶端交易,并可以動態裝載和管理業務層.
原碼(二)是管理層與業務層的交易接口.
原碼(三)是業務層模型,所有業務層都由它派生.
 
好,研究一下!
 
这些代码我滚来滚去好多遍,看得累死人,如果bbs能用跟cnpack ide 输出html一样,那就容易看的多了!不知道斑竹在不在场?呵呵
 
to aleyn
代码2和代码3好像是一样的。。呵呵。是不是我的眼睛有问题?
 
不好意思,原碼(三)貼錯了,我打開Delphi再貼一次.
 
另外一個,就是數據通訊的保密問題,vinson_zeng,你的ClientDataSet是如何連接Provider的,如果是直接連接,再在Provider中處理Params的話,可能就不保險了,任何一個人都可以連接到你的Provider.
 
顶部