MIDAS高手请进!(200分)

  • 主题发起人 主题发起人 fylzh
  • 开始时间 开始时间
F

fylzh

Unregistered / Unconfirmed
GUEST, unregistred user!
小弟我初学midas编程,有两个问题想请教:
1、同一个应用服务程序里的多个remotedatamodule如何共享一些全局信息?
我的想法是这样的,每一个remotedatamodule里都有一个adoconnection负责连接到后台数据库,
可是这些adoconnection的connection string怎么办?总不会都写死在源程序里吧?那样就没办法
分发程序了。我把这些参数通过一个连接参数设置程序保存到注册表里,本打算在应用服务程序运
行时从注册表里读出这些参数,然后保存在主程序的一个全局变量单元里(此单元还包括其他一些
全局参数),可是后来才发现在remotedatamodule里根本无法读取这些参数,虽然已经把该单元uses
进来,而且在编译时也没有问题,可是实际运行就出错,一旦客户端访问某个包含访问这些变量代码
的方法就报‘invalid variant operation’错误。如何解决?总不成在每个remotedatamodule里都要
自行读取注册表里的信息吧?那样在Remotedatamodule被频繁建立时速度肯定要比直接读内存慢。
2、在remotedatamodule里如何访问form?
在midas的应用服务程序里都有一个form,一般书上的例子只在这个form上访一个label,显示这是某个
程序,这在实际的应用中简直一点作用都没有,我想利用这个form显示一些更有用的信息,比如当前
已登录的用户信息,所以我就在这个form上放了一个grid,我的程序里面还有一个security remotedatamodule,
负责用户的login,logout,change password等功能,我想在用户调用login方法后就在grid增加一条信息,
调用logout后就删除相应的信息,可是直接在remotedatamodule的代码里操纵grid肯定不行,所以做了
一个普通的datamodule,在里面放一个内存表控件,并定义了一些方法供remotedatamodule来调用以修改
信息,form上的grid则连到这个dataset上。可是这样也不行,错误同上。
恳请赐教,不胜感激!
 
访问应该是没问题的,
估计你是没有处理好variant变量.
 
1.这种方法应该是没有错误的,你可以跟踪一下看错误出在那里.
2.你的数据模块运行在自己的STA线程里,与你的Form所在的主线程不在一
个线程,当然不能直接调用.
可以用自定义消息的方法,在TRemoteDatamodule里向MainForm去
PostMessage来实现这个功能
 
1、新建一个DataModule,把你的ADOConnection放到里面,
其它的RemoteDataMoudle中的ADO数据集控件引用这个DataModule中的ADOConnection控件
这样你就只使用了一个Connection并且操作起来也要方便不少。
其它的公共变量也可以放到这里。但“invalid variant operation’应当是你的代码有问题
你再仔细看看。
2、注意你的窗体创建顺序,你的思路没有错,但这个普通的datamodule是否先在Form前创建?
另外做的时候应当是这样的顺序:
Client ----> security remotedatamodule ----> 普通的datamodule----> Form
Loing pass... 验证,修改普通的datamodule的数据 数据集变化 界面Grid变化
 
to all:
对于第一个问题我知道可以用com+的SPM来解决,可是我不想用com+,怕遇到更多的问题,
因为这个项目的时间有限,我对com+了解得也不多。
我的代码也应该没有错误,因为我根本没有用到variant类型的变量,而且只要我把引用
公用变量的代码去掉程序就不会出错,应该还是这种方法本身的问题。我还没有把ADOConnection
放到那个普通的datamodule里,因为现在我连里面的方法都访问不了,如果再去引用里面的
控件估计也不可能。
另外窗体的创建顺序也应该不会错,否则会出现内存的访问违例,但是现在没有。最初我也
遇到了这样的情况,后来调整了一下创建顺序,错误就没有了。
在这里我最不能理解的就是我压根就没有用variant变量,怎么会出现‘invalid variant operation’?
我想可能这种做法可能本身就是错误的,因为remotedatamodule的运行线程和程序的主线程
是分开的,所以我才想到建一个普通的DM,让remotedatamodule调用DM中定义的方法来更新
数据,然后利用data aware机制更新form里的grid,这样可以避免在remotedatamodule的线程
里直接访问可视控件,这种做法居然不行!
 
没人给点意见吗?
 
2.假设你的Form的单元是ServerFrm_Unit,
则在RemoteDataModule的单元中 uses ServerFrm_Unit,
然后在你的注册的接口中直接调用即可:
procedure TResource_Server.Remote_Login(Login_Type: Smallint;
out Login_Result: OleVariant);
begin
//+------------------------------------------------+
//| 动态链接数据库,登录部分 |
//+------------------------------------------------+
case Login_Type of
1: if Login_DB(SubMatter_Pass,SubMatter_User)=0 then
Login_Result:=0;
//数据库登录失败
else
begin
Login_Result:=1;
Serverform.Label.Caption:='。。。。。登录成功';
//-----------就是此处,可以显示
end;

2: if Login_DB(Resource_Pass,Resource_User)=0 then
Login_Result:=0;
//数据库登录失败
else
begin
Login_Result:=1;
Serverform.Label.Caption:='。。。。。登录成功';
//-----------就是此处,可以显示
end;

3://以common用户登录
............
end;
.....................
end;
 
to jrq:
绝对不行.
你在另一个线程能调用VCL的方法吗?显然要看那个
方法是不是线程安全的.
Delphi中所有与界面有关的控件的方法基本上都不是线程安全的
 
to:fylzh 我就是像和你交流的方法那样写的,没有出过什么问题。
关于你描述的:一旦客户端访问某个包含访问这些变量代码的方法就报‘invalid variant operation’
是否可以贴出代码看看?
 
是要求基于多线程访问的吗?
接口方法是自己注册的。
 
首先感谢大家的支持!
to blue_mornig:
这是我的一段代码
procedure TSecurity.SysLog(LogID: Integer;
const MkDm, Flag: WideString);
var
dwdm, yhdm, ip, hostname: string;
begin
dwdm := PubDM.GetDwdm(LogID);
yhdm := PubDM.GetYhdm(LogID);
ip := PubDM.GetIP(LogID);
hostname := PubDM.GetHostName(LogID);
adoCmd.CommandText := Format(SysLogSql, [dwdm, yhdm, mkdm, ip, hostname, flag]);
adoCmd.Execute;
end;
这个方法的作用是记录系统日志,传入的三个参数分别是登录ID,模块代码,和登录登出标志,
PubDM是我建立的一个DataModule,其中有一个内存表用来记录已登录进来的用户详细信息,在
用户调用Login方法登录进来并通过系统验证后我在DM中的内存表中增加一条记录,记下用户的
信息,并分配给其一个LogID,以后用户在调用其他需要这些信息的方法是只要传入该ID即可。
在DM中实现了一些方法来获取已经记录的信息,如GetDwdm,GetYhdm,GetIP,GetHostName等,
现在可以保证这些方法没有错误,因为在这些方法里我只写了一条:Result := '***',但是
用上面的代码就是有问题,系统报告‘Invalid variant operation’,如果我这样写就没有问题:
procedure TSecurity.SysLog(LogID: Integer;
const MkDm, Flag: WideString);
var
dwdm, yhdm, ip, hostname: string;
begin
dwdm := '134120000';//PubDM.GetDwdm(LogID);
yhdm := '000';//PubDM.GetYhdm(LogID);
ip := '127.0.0.1';//PubDM.GetIP(LogID);
hostname := 'LocalHost';//PubDM.GetHostName(LogID);
adoCmd.CommandText := Format(SysLogSql, [dwdm, yhdm, mkdm, ip, hostname, flag]);
adoCmd.Execute;
end;
这是为什么?
我不知道你的代码是如何写的,能否贴出来让我学习一下?
 
To fylzh。你还是没有把问题说清楚:
首先:procedure TSecurity.SysLog(LogID: Integer;
const MkDm, Flag: WideString);
是一个应用服务器的接口函数还是你在客户端的方法?
另外这个异常是App抛出的,还是Client抛出的?
你是不是就按照李维的书上开头那几章介绍的做,在客户端就直接写SQL语句?
如果是你的能不能准确的定位错误出在什么那一句代码上:
我估计是
adoCmd.CommandText := Format(SysLogSql, [dwdm, yhdm, mkdm, ip, hostname, flag]);
adoCmd.Execute;
其中的一句对吧?
你把CommandText像这样写:
commandtext := insert into table values (dwdm + '''' + yhdm + '''')....
试试
 
to Blue_morning:
今天很忙,没顾得上网!
谢谢你的帮助,我的问题已经解决了,错误果然是出在我的代码上。上面的代码是一个服务端的
接口函数,当初我保证该函数调用的PubDM.Get*()不会出问题,后来又检查了一下发现问题就在这些
函数里面,调试的时候我在这些函数的第一句写上一句Result := '***',忘了把后面的语句给注释掉,
恰恰就是后面的语句出了问题!
另外还想向你请教个问题,midas做出来的应用服务器效率如何?我第一次用它,心里很没底。
我做的项目不大,正式运行时数据库大概不会超过10万条记录,总共有20多个表,同时在线用户不超过
50人。比较麻烦的是要放到广域网的环境下运行,网速比较慢。我以前用c/s的模式做过这个项目,
在局域网的环境下测试很正常,一放到广域网上就出问题,查询慢,带宽占用率很高,实在让我头大,
可能是我的水平太差,系统规划的不合理。不知你能否给些建议?
 
C/S模式下广域网50人在线估计跑不起来。应当使用三层结构的方式.
给出建议有些困难,你要自己尝试。另外MIDAS App Server支持五○个人应当没有问题。你客户端的SocketConnection不用一直保持连接状态,可以在呼叫服务完成后断开连接
因为MIDAS结构中问题一般出在自带的那个SocketServer上。(使用Scoket做为连接)
关于C/S结构的建议
一个可能有效的方法是把你原来C/S的Connection->DataSet->DataSource->GUI
的方式改为:Connection->DataSet->Provider->ClientDataSet->DataSource->GUI
注意不是MIDAS的结构方式,没有RemoteDataModule。这些Connection->DataSet->Provider->ClientDataSet->DataSource都可以在一个DataModule中
通过设定ClientDataSet的PacketRecords来缓冲数据以减少带宽的使用。
 
1.与注意全局信息在使用前是否分配空间。
2.直接在remotedatamodule可以实现,只是要注意主Form的全局变量是否已赋值,因为remotedatamodule通常在主Form之前创建。
 
谢谢大家的帮助!
 
后退
顶部