**三层结构让我很伤心,这可能是MIDAS的大臭虫吧** (100分)

  • 主题发起人 主题发起人 lizongqi
  • 开始时间 开始时间
L

lizongqi

Unregistered / Unconfirmed
GUEST, unregistred user!
具体问题如下
http://expert.csdn.net/Expert/topic/1584/1584125.xml?temp=.6263391

我已经用了一个星期的时间找原因。因为把企业逻辑和安全控制放到数据库中,获得资料存储过程GetXXXXX和更新资料存储过程XXXXAdd,XXXXEdit,XXXXDelete都要进行权限、资料id、用户id等等重要的检测。不符合企业逻辑的权限、id等通过
raiserror(@errorMsg,16,1)
return
触发错误,返回,使客户端获得必要的信息。取得数据和更新数据的设计方法都是统一的,我都检查了n遍了,存储过程绝对没有错误。
使用c/s结构,通过ADO直接操作存储过程,try..except正常工作,完全符合设计要求。而用在三层中,只有获取数据可以正常捕捉错误和正常工作,更新数据捕捉不到任何错误。
后台sql server2000
数据提供 adoquery+datasetProvider(获取数据)
adoStoredProc+datasetProvider(更新数据)
连接方式 socketConnection
客户端 Clientdataset取得数据是通过dataRequest取得,更新数据通过在相应datasetProvider的beforeUpdateRecord中处理。这些取得数据和数据更新的处理都是用adoquery执行相应的存储过程实现的。

有的人说,raiserror传递的是消息,不是异常错误,所以捕捉不到。
我觉得,c/s结构中,就可以捕捉到raiserror的“信息”,所以这种说法不成立。
要么是ado的问题,要么是midas和socketConnection的问题。


我现在面临的是
1.更改设计模式 三层--〉c/s结构,因为程序做了三个月了,如果更改结构,需要1个月的时间;
2.要么就是重新来(数据库后台已完成),需要更多的时间

对三层结构开发中遇到各种奇怪问题的兄弟进来说一说,up一下也好。也希望开发经验足的一个道上的给个意见,能尽快完成既定的项目(crm客户关系管理系统)。谢谢。

 
//下面是应用程序服务器更新客户资料完整的代码
//曾经在try..except中通过raise重新触发异常,跟踪调试
//发现根本没有错误发生(事实上有发生)
procedure TcrmServer.dspAccountExecBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet;
DeltaDS: TCustomClientDataSet;
UpdateKind: TUpdateKind;
var Applied: Boolean);
var
accountvId,accountvName,accountvType,accountvTrade,accountvSource:string;
accountvState,accountvNation,accountvProvince,accountvCity,accountvAddr:string;
accountvZip,accountvTel,accountvFax,accountvEMail,accountvWebSite:string;
accountvComments,accountvUserId,accountvLockedType:string;
begin
//***********************插入***************************
if UpdateKind=ukInsert then
begin
//begin
of the if statements
//取得相应字段的值
with DeltaDSdo
begin
accountvName:= trim(FieldByName('accountvName').AsString);
accountvType:= trim(FieldByName('accountvType').AsString);
accountvTrade:= trim(FieldByName('accountvTrade').AsString);
accountvSource:=trim(FieldByName('accountvSource').AsString);
accountvState:=trim(FieldByName('accountvState').AsString);
accountvNation:= trim(FieldByName('accountvNation').AsString);
accountvProvince:= trim(FieldByName('accountvProvince').AsString);
accountvCity:= trim(FieldByName('accountvCity').AsString);
accountvAddr:= trim(FieldByName('accountvAddr').AsString);
accountvZip:= trim(FieldByName('accountvZip').AsString);
accountvTel:= trim(FieldByName('accountvTel').AsString);
accountvFax:= trim(FieldByName('accountvFax').AsString);
accountvEMail:= trim(FieldByName('accountvEMail').AsString);
accountvWebsite:= trim(FieldByName('accountvWebSite').AsString);
accountvComments:= trim(FieldByName('accountvComments').AsString);
accountvUserId:=trim(FieldByName('accountvUserId').asString);
accountvLockedType:= trim(FieldByName('accountvLockedType').AsString);
end;
//end of the with statements
spAccountExec.Close;
spAccountExec.ProcedureName:='AccountInsert';
spAccountExec.Parameters.Clear;
spAccountExec.Parameters.CreateParameter('@accName',ftString,pdInput,100,accountvName);
spAccountExec.Parameters.CreateParameter('@accType',ftString,pdInput,100,accountvType);
spAccountExec.Parameters.CreateParameter('@accTrade',ftString,pdInput,100,accountvTrade);
spAccountExec.Parameters.CreateParameter('@accSource',ftString,pdInput,100,accountvSource);
spAccountExec.Parameters.CreateParameter('@accState',ftString,pdInput,4,accountvState);
spAccountExec.Parameters.CreateParameter('@accNation',ftString,pdInput,100,accountvNation);
spAccountExec.Parameters.CreateParameter('@accProvince',ftString,pdInput,100,accountvProvince);
spAccountExec.Parameters.CreateParameter('@accCity',ftString,pdInput,100,accountvCity);
spAccountExec.Parameters.CreateParameter('@accAddr',ftString,pdInput,400,accountvAddr);
spAccountExec.Parameters.CreateParameter('@accZip',ftString,pdInput,6,accountvZip);
spAccountExec.Parameters.CreateParameter('@accTel',ftString,pdInput,100,accountvTel);
spAccountExec.Parameters.CreateParameter('@accFax',ftString,pdInput,100,accountvFax);
spAccountExec.Parameters.CreateParameter('@accEMail',ftString,pdInput,100,accountvEMail);
spAccountExec.Parameters.CreateParameter('@accWebSite',ftString,pdInput,100,accountvWebSite);
spAccountExec.Parameters.CreateParameter('@accComments',ftString,pdInput,4000,accountvComments);
spAccountExec.Parameters.CreateParameter('@accUserId',ftInteger,pdInput,0,StrToInt(accountvUserId));
spAccountExec.Parameters.CreateParameter('@accLockedType',ftString,pdInput,6,accountvLockedType);
spAccountExec.Parameters.CreateParameter('@currUserId',ftInteger,pdInput,0,currUserId);
spAccountExec.Prepared:=true;
spAccountExec.ExecProc;
//**************************************
applied:=true;
//very important
//**************************************
end//if ukInsert

 
//********************************更新***************************
else
if UpdateKind=ukModify then
begin
//取得相应字段的值
with DeltaDSdo
begin
if varIsEmpty(FieldByName('accountvName').NewValue) then
accountvName:= trim(vartostr(FieldByName('accountvName').OldValue))
else
accountvName:= trim(vartostr(FieldByName('accountvName').NewValue));
if varIsEmpty(FieldByName('accountvType').NewValue) then
accountvType:= trim(vartostr(FieldByName('accountvType').OldValue))
else
accountvType:= trim(vartostr(FieldByName('accountvType').NewValue));
if varIsEmpty(FieldByName('accountvSource').NewValue) then
accountvSource:= trim(vartostr(FieldByName('accountvSource').OldValue))
else
accountvSource:= trim(vartostr(FieldByName('accountvSource').NewValue));
if varIsEmpty(FieldByName('accountvState').NewValue) then
accountvState:= trim(vartostr(FieldByName('accountvState').OldValue))
else
accountvState:= trim(vartostr(FieldByName('accountvState').NewValue));
if varIsEmpty(FieldByName('accountvTrade').NewValue) then
accountvTrade:= trim(vartostr(FieldByName('accountvTrade').OldValue))
else
accountvTrade:= trim(vartostr(FieldByName('accountvTrade').NewValue));
if varIsEmpty(FieldByName('accountvNation').NewValue) then
accountvNation:= trim(vartostr(FieldByName('accountvNation').OldValue))
else
accountvNation:= trim(vartostr(FieldByName('accountvNation').NewValue));
if varIsEmpty(FieldByName('accountvProvince').NewValue) then
accountvProvince:= trim(vartostr(FieldByName('accountvProvince').OldValue))
else
accountvProvince:= trim(vartostr(FieldByName('accountvProvince').NewValue));
if varIsEmpty(FieldByName('accountvCity').NewValue) then
accountvCity:= trim(vartostr(FieldByName('accountvcity').OldValue))
else
accountvCity:= trim(vartostr(FieldByName('accountvcity').NewValue));
if varIsEmpty(FieldByName('accountvAddr').NewValue) then
accountvAddr:= trim(vartostr(FieldByName('accountvAddr').OldValue))
else
accountvAddr:= trim(vartostr(FieldByName('accountvAddr').NewValue));
if varIsEmpty(FieldByName('accountvZip').NewValue) then
accountvZip:= trim(vartostr(FieldByName('accountvZip').OldValue))
else
accountvZip:= trim(vartostr(FieldByName('accountvZip').NewValue));
if varIsEmpty(FieldByName('accountvTel').NewValue) then
accountvTel:= trim(vartostr(FieldByName('accountvTel').OldValue))
else
accountvTel:= trim(vartostr(FieldByName('accountvTel').NewValue));
if varIsEmpty(FieldByName('accountvFax').NewValue) then
accountvFax:= trim(vartostr(FieldByName('accountvFax').OldValue))
else
accountvFax:= trim(vartostr(FieldByName('accountvFax').NewValue));
if varIsEmpty(FieldByName('accountvEMail').NewValue) then
accountvEMail:= trim(vartostr(FieldByName('accountvEmail').OldValue))
else
accountvEMail:= trim(vartostr(FieldByName('accountvEmail').NewValue));
if varIsEmpty(FieldByName('accountvWebsite').NewValue) then
accountvWebsite:= trim(vartostr(FieldByName('accountvWebsite').OldValue))
else
accountvwebsite:= trim(vartostr(FieldByName('accountvWebsite').NewValue));
if varIsEmpty(FieldByName('accountvComments').NewValue) then
accountvComments:= trim(vartostr(FieldByName('accountvComments').OldValue))
else
accountvComments:= trim(vartostr(FieldByName('accountvComments').NewValue));
if varIsEmpty(FieldByName('accountvLockedType').NewValue) then
accountvLockedType:= trim(vartostr(FieldByName('accountvLockedType').OldValue))
else
accountvLockedType:= trim(vartostr(FieldByName('accountvLockedType').NewValue));
if varIsEmpty(FieldByName('accountvUserId').NewValue) then
accountvUserId:=vartoStr(FieldByName('accountvUserId').OldValue)
else
accountvUserId:=vartoStr(FieldByName('accountvUserId').NewValue);
accountvId:=vartoStr(FieldByName('accountvId').oldValue);
end;
//end of the with statements
spAccountExec.Close;
spAccountExec.ProcedureName:='AccountEdit';
spAccountExec.Parameters.Clear;
spAccountExec.Parameters.CreateParameter('@accId',ftInteger,pdInput,0,strToInt(accountvId));
spAccountExec.Parameters.CreateParameter('@accName',ftString,pdInput,100,accountvName);
spAccountExec.Parameters.CreateParameter('@accType',ftString,pdInput,100,accountvType);
spAccountExec.Parameters.CreateParameter('@accTrade',ftString,pdInput,100,accountvTrade);
spAccountExec.Parameters.CreateParameter('@accSource',ftString,pdInput,100,accountvSource);
spAccountExec.Parameters.CreateParameter('@accState',ftString,pdInput,4,accountvState);
spAccountExec.Parameters.CreateParameter('@accNation',ftString,pdInput,100,accountvNation);
spAccountExec.Parameters.CreateParameter('@accProvince',ftString,pdInput,100,accountvProvince);
spAccountExec.Parameters.CreateParameter('@accCity',ftString,pdInput,100,accountvCity);
spAccountExec.Parameters.CreateParameter('@accAddr',ftString,pdInput,400,accountvAddr);
spAccountExec.Parameters.CreateParameter('@accZip',ftString,pdInput,6,accountvZip);
spAccountExec.Parameters.CreateParameter('@accTel',ftString,pdInput,100,accountvTel);
spAccountExec.Parameters.CreateParameter('@accFax',ftString,pdInput,100,accountvFax);
spAccountExec.Parameters.CreateParameter('@accEMail',ftString,pdInput,100,accountvEMail);
spAccountExec.Parameters.CreateParameter('@accWebSite',ftString,pdInput,100,accountvWebSite);
spAccountExec.Parameters.CreateParameter('@accComments',ftString,pdInput,4000,accountvComments);
spAccountExec.Parameters.CreateParameter('@accUserId',ftInteger,pdInput,0,StrToInt(accountvUserId));
spAccountExec.Parameters.CreateParameter('@accLockedType',ftString,pdInput,6,accountvLockedType);
spAccountExec.Parameters.CreateParameter('@currUserId',ftInteger,pdInput,0,currUserId);
spAccountExec.Prepared:=true;
spAccountExec.ExecProc;
//**************************************
applied:=true;
//very important
//**************************************
end//end of if ukModify
//***********************delete**************************
else
if UpdateKind=ukDelete then
begin
accountvId:=vartostr(deltaDS.fieldByName('accountvId').OldValue);
spAccountExec.Close;
spAccountExec.ProcedureName:='AccountDelete';
spAccountExec.Parameters.Clear;
spAccountExec.Parameters.CreateParameter('@accId',ftInteger,pdInput,0,strToInt(accountvId));
spAccountExec.Parameters.CreateParameter('@currUserId',ftInteger,pdInput,0,currUserId);
spAccountExec.Prepared:=true;
spAccountExec.ExecProc;
//**************************************
applied:=true;
//very important
//**************************************
end;

end;
//procedure
 
//其中 currUserId 是一个全局变量,是当前系统用户的id,通过接口实现写入,绝对没有错误。

现在不知道该怎么办,是找ado,midas的升级文件还是更改程序模式?最好能由升级文件,这样可以缩短项目时间。
补充一下:
delphi7+sqlserver2000
windows2000advServer

ado已升级到 2.7
 
[red]其中 currUserId 是一个全局变量,是当前系统用户的id,通过接口实现写入,绝对没有错误。[/red]
什么接口方法,Login吗?应该把它定义成远程数据模块的一个成员变量。
另外要注意,你的TSocketConnection的connected为True后login,再这之后千万
不成Close,否则后导致远程数据模块的重建。那个成员变量也就完蛋了.
 

楼上的兄弟,我是自定义的接口,接口肯定没有问题,我跟踪调试过。
问题在别的方面

 
To:lizongqi
这种现象是正常的,因为在DataSetProvider的事件BeforeUpdateRecord中
如果发生错误,那么这个错误没有办法raise 起来,只是把DataSetProvider的
ErrorCount加一而已;
一个比较笨的办法,把在这个事件里面捕捉到的错误信息保存到一个公用
资源里面,在更新完成后检查该资源,然后再作处理!
 
建议将ADO连接改为BDE。
ADO做中间层时,如果多个客户端连接应用服务器,数据库打开时会异常
(你在ADOAonnection.Action:=True处捕捉异常试试)
 
to myLiu:
确实是这样的。在BeforeUdpateRecord事件里,只有
raise exception.Create('test');
这样的语句都捕捉不到!!!!!!!!!
我晕!
不知道你怎么具体处理的?我只有282分了,如果解决了这个问题,你是我的大恩人哪!
分全部给你,这个问题我已经研究两周了,呜呜
 
to lizongqi:
从 Provider单元的源代码就可以看出:
这个错误被被传递给了TDatasetProvider的OnUpdateError
事件,而不触发异常.
你可以在OnUpdateError事件中去截获错误.
 
因为你的写的太乱了,我只能凭感觉回答你的问题了。
数据的提取与更新是两个不同的数据操作
在三层中,如果有设定为out和reval类的话,那么就有一个结果返回。
设定Result := YourFounction.Data;
在客户端调用的时候用YourDataSet.Appserver.YourFounction可以中间层函数的返回结果集
若在三层中用AdoQuery.Open则返回一个结果集,若是AdoQuery.ExecSQL则返回一个整型值,此值为你所取得记录的Count
大概能讲的就这么多,不知道还有没有别的东西漏了:)
 
to:
myliu
xeen
xianguo
阿西喊佛
每天进步
现在错误已经缩小到一个很小的范围了。我现在把BeforeUdpateRecord改成这样

procedure TcrmServer.dspAccountExecBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet;
DeltaDS: TCustomClientDataSet;
UpdateKind: TUpdateKind;
var Applied: Boolean);
begin
raise exception('test');
applied:=true;
end;

procedure TcrmServer.dspAccountExecUpdateError(Sender: TObject;
DataSet: TCustomClientDataSet;
E: EUpdateError;
UpdateKind: TUpdateKind;
var Response: TResolverResponse);
begin
//可以捕捉到错误,但是如何处理才能在
//try
// clientDataset.applyUpdates(0);
//except
//end;
//捕捉到相应的错误信息呢?
end;


 
现在在OnUpdateError能捕捉到有错误,但是客户端捕捉不到,如何才能让客户端也捕捉到呢?
我的这些错误信息是在存储过程中 raiserror 得到的
 
解决了,解决了
啊哈哈哈哈哈哈哈哈哈!!!!!!!!!!!!!!!!


raise e;就可以捕捉到了


天啦,原来BeforeUpdateRecord的错误在OnUpdateError中捕捉!!!!!!!!
 
hehe,你的异常被捕捉了一次,想被看见再抛出一次就行了。
以后有问题应该先看看 VCL 的源代码.
 
to lizongqi:
我在OnUpdateError中可以捕捉到错误,但如何让客户端也捕捉到错误。
 
客户端的更新语句
try
applyUpdates
except
捕捉即可
good luck
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部