一些常见的问题

来源:互联网 发布:买烟用什么软件下载 编辑:程序博客网 时间:2024/05/29 11:35

 

1. 新事务不能登记到指定的事务处理器中

现象:登录时输入用户和密码回车后,报错,这个只在连接数据库服务器时才会出现,如果中间层和数据库都地本机上,是不会出现的。  

 

临时处理方法:

只有在中间层的事务方式为:“必需/要求新建”时才会报这个错误,调试程序时可以临时把中间层的事务方式改为“支持”,但是记住这只是临时的处理方式,这种方式会引起使用主从表的数据集保存失败,例如用户管理里的功能调整,就会报错

2. 找不到指定模块

现象:从组件服务看中间层已经安装,程序中还是报错“找不到指定模块”

原因:中间层DLL文件所在的目录不对

处理方法:

在中间层小球上点右键,看属性,把DLL文件所在的目录拷出来,记住只拷目录,不带文件名,粘贴到我的电脑的地址栏里,回车,然后看目录里到底有没有需要的中间层DLL文件了。

3. 没有注册类别

现象:程序登录或使用中报错“没有注册类别”

原因:1.系统所需要的中间层没装,2.程序中连接本地中间层了

处理方法:(我觉得处理方法就是处理的步骤,不知道这样改行不行)

1.通过查看INI文件来判断程序连接的是本地中间层还服务器中间层。

2.如果是服务器中间层,查是否连接了本地中间层:是不是把中间层在本地装一下,就不报错了,如果是这种现象,那就是连本地中间层了。

3.如果把中间层在本地装上之后还是报错,那就是模块需要的中间层没装全,现在的程序很多都需要相关的中间层,例如使用wpws需要yz的中间层。

4.程序需要的中间层已经装全了,还是报没有注册类别,有可能是客户端目录里有被程序调用的DLL文件,这些DLL文件中有一个或几个需要独立的中间层,可以先把客户端exe所在目录的所有DLL清空,再试一下,如果不报错了,那就是这个原因,通过逐步增加DLL的方式判断出哪个DLL的中间层没装,然后装上。

4. 找不到1%。

原因:C:\Program Files\Common Files\System\Ole DB\Data Links 目录下缺少 chis.udl 文件

 

 

 

5. 不正确地定义参数对象。提供了不一致或不完整的信息。

 

 

 

 

原因:1.中间层 adoquery 的参数和客户端组件 clientdataset 的参数数量不一致

      2.参数的默认值为 null并且open之前没给参数赋值,这种错误在调试的时候经常出现,修改过adoquery的SQL语句之后,直接在delphi环境里双击clientdataset控件的active属性就有可能出现。

6. 报错adq….缺少字段

原因:1.数据库中没有这个字段

      2.数据库中有,但是adq.…的SQL语句里没有取这个字段,取固定列的时候发生。

7. 报错 cds....缺少字段

原因:1.数据库中没有这个字段

      2.数据库里有,但是对应的adq….的SQL语句里没取这个字段

      3.数据库里有,对应的adq….的SQL语句里也取了这个字段,但是adq….是取固定列的,固定列中不包括这个字段

      4.cds….是取固定列的,固定列中没有包含这个字段

      5.主从表的时候如果复制主表的clientdataset,原固定列没清除。

8. 更新、删除数据失败

原因:1.clientdataset.applyupdates 时自动生成的 update 或 delete 语句条件中某个字段的数据带毫秒

      2. 如果clientdataset刚做过数据添加,在没有重新读取数据的情况下,做更新或删除,where条件中某个字段的数据在数据库的设置中有默认值,并且在记录insert 的时候并没有给默认值赋值

      3.where条件中某个文本字段中有特殊值,例如“,,”

      4.触发器

处理方法:

    1.清除带毫秒的datetime型数据中的毫秒部分

    2. 通过adoquery属性设置为datetime型的字段不做为条件

 

 

    3.通过中间层的设置或代码控制,使带毫秒的datetime型字段不做为条件

在中间层的adoquery的afteropen事件里写代码:

procedure Tyz_act_order_stop.adqGetdataAfterOpen(DataSet: TDataSet);

begin

  DataSet.FieldByName('order_name').ProviderFlags := [];

  DataSet.FieldByName('order_name').ProviderFlags := [pfInUpdate];

End;

4.在客户端添加数据的时候给带默认值的字段赋值

5.使带有特殊字值的文本字段(yz_comment、instruction、discription)不做为条件

9. rpc服务器不可用

原因:1.客户端闲置时间过长,中间层自动关闭

      2.调试程序的过程中,手动关闭了中间层

处理方法:clientdataset1.remoteserver.close;把这句代码放在clientdataset1.close之前。

10. 点击按钮时,什么错都不报,跟踪什么都没有

原因:1.代码中使用了(try  except  end)直接的错误提示信息被拦截了

处理方法:

try

    ……..

    except

      on E: Exception do

      begin

        ShowMessage('dll_ypApply初始化失败:'+E.Message);

        Exit;

      end;

   end;    

11. 循环更新数据集时,只更新了一部分(有时是一半),另一部分没更新(或者循环计算汇总,汇总出来数据不对,有时候多,有时候少)

原因:1.数据集上有filter,并且修改数据集的数据时修改了和filter有关的字段,导致post之后,当前数据集已经不可见,但还是继续执行了循环中的next。

      2.循环的数据集上有排序,循环过程中修改了排序字段,导致有部分数据重复参与汇总,有部分数据没有参与汇总

12. 数据集savetofile之后明明有满足条件的数据,但是locate不到

原因:数据集有filter,所以locate查不到,而且RecordCount也是受filter影响的,但是savetofile是忽略filter的,会把数据集里所有的数据都输入到指定的文件里。

13. 怎么样只显示当前这一组父子医嘱,无关的不显示

Var

  sActorderno: string;

begin

    if clientdataset1.FieldByName(‘parent_no’).asfloat > 0 then

       sActorderno := clientdataset1.FieldByName(‘parent_no’).asfloat

    else

       sActorderno := clientdataset1.FieldByName(‘act_order_no’).asfloat;

 

    clientdataset1.filtered := false;

    clientdataset1.filtered := ‘parent_no = ‘ + sActorderno + ’ or act_order_no = sActorderno’;

    clientdataset1.filtered := true;

end;

14. 根据条件界面上的内容显示不同的颜色

procedure TfrmChargeOrder.grdChargeShowGetCellParams(Sender: TObject;

  Column: TColumnEh; AFont: TFont; var Background: TColor;

  State: TGridDrawState);

begin

  inherited;

  //以背景色区分费用细目的状态。

  with Sender as TDBGridEh Do

  begin

    if TDataSet(DataSource.DataSet).FieldByName('charge_status').Value = '2' then

      BackGround := RGB(255,0,50)

    else if

      TDataSet(DataSource.DataSet).FieldByName('charge_status').Value = '3' then

      BackGround := RGB(0,255,0)

    else if

      TDataSet(DataSource.DataSet).FieldByName('charge_status').Value = '4' then

      BackGround := RGB(0,0,255);

 

    AFont.Color := clRed;

  end;

end;

15. 客户端增加的窗体看不到

原因:功能里没加这个窗体的权限 ,增加以后要重新登录程序

16. 中间层增加的窗体看不到,中间层新增的函数用不了

原因:1.中间层没有重新安装或没有关闭

      2.中间层实际使用的文件和编译输出的文件不在同一个目录里

17. 网页调用delphi写的OCX的时候,没有任何反应

原因:网页中调用OCX时的入参数量和OCX对外公布的入参数量不符

18. 字段只读,无法编辑

原因:1.字段来自固定内容或者计算内容

      2.字段来自存储过程,并且是在存储过程中计算得出的

处理方法:

    1.在中间层的adoquery的afteropen事件里写代码:

procedure Trt_com_yz_zy_detail_charge.adqPageNoAfterOpen(

  DataSet: TDataSet);

begin

  DataSet.FieldByName('page_type_external').ReadOnly := False;

end;

    2.修改存储过程,使字段从表里取,或者在clientdataset中使用内部计算字段 fkInternalCalc

3.存储过程和视图里写固定值的字段、用函数或表达式处理过的字段是不允许编辑的,如果需要编辑可以建个小的字典表,把值写在表里,然后关联一下。

19. 更新数据集(包括修改、删除)时,报XX字段不存在

原因:报错的字段来自关联表

处理方法:

在中间层的adoquery的afteropen事件里写代码:

procedure Tyz_act_order_stop.adqGetdataAfterOpen(DataSet: TDataSet);

begin

  DataSet.FieldByName('order_name').ProviderFlags := [];

End;

20. 更新数据集时,没有可以更新的数据Record not found or changed by another user,记录已经被别人修改

原因:1.当前clientdataset更新的数据,在你取出来之后,提交之前,被其它人修改过。

      2.当前要更新的表上某个字段有默认值,并且程序里没有给这个字段赋值,在第一次提交的时候是执行的insert,如果此时没有重新获取数据,编辑之后再次提交,就会报这个错误。

      3.数据中某日期时间型字段的有“毫秒”

21. null 导致的取值取错


原因:从字段中取值的时候,字段的值为null

  a := ClientDataSet1.FieldByName('deleted_flag').Value;

处理方法:

  a := ClientDataSet1.FieldByName('deleted_flag').AsString;

22. chis.ini里的值取不到

原因:组标题有重复。

23. 退出时报地址错

原因:有动态创建的窗体/动态加载的函数未释放

24. 录入控件在自己机器上没问题,但是在工程或现场报错(因为wh_tag_sql 激活状态未设置)

 

25. 调用接口函数时报地址为 00000000的错误

 

原因:在调用函数之前未加载

处理方法:在函数使用之前加判断  

  if Assigned(InitVariant) then

26. 窗体未创建直接show。

 

如果报地址错了,查到是窗体的show或showmodal报错,可以考虑是不是没有创建或者已经释放了。

27. 窗体创建并使用后未释放,导致再次打开后还留有上次使用的旧数据(取数据的语句放在formcreate里)

原因:初始化窗体的语句放在了formcreate事件里

处理方法:将初始化语句放在formshow事件里

28. 临时数据集未createdataset直接使用

 

原因:临时数据集(就是取固定列并且没有连接DataSetProvider的数据集),没有经过CreateDataSet或者已经Close就直接使用了

处理方法:在对数据集执行操作之前CreateDataSet

29. FindField的使用,和引出的问题

  With cdsZyConfigureAllField Do

  begin

   Close;

    Data := null;

    Open;

    if FindField('yb_responce_type') <> nil then

      gv_yb_responce_type := trim(FieldByName('yb_responce_type').AsString);

 

  end;

 

    可以在使用之判断某字段是否存在,然后根据判断结果执行不同的动作,缺点是由于不报错,工程不知道需要增加这个字段,通用程度不高的字段可以用这种方法处理,通用性比较强的字段如果没有要增加错误提示。

30. 序列号的使用

function Trt_comYzConfiger.iGetOccPageNo: OleVariant;   //by swl 2009-11-10  南京鼓楼升级

begin

  try

    Result := 0;

    With adqResult Do

    begin

      SQL.Clear;

      SQL.Append('update yz_configure set occ_page_no = occ_page_no + 1');

      ExecSQL;

 

      SQL.Clear;

      SQL.Append('select occ_page_no from yz_configure');

      Open;

      IF RecordCount <> 0 then

      begin

        Result := FieldByName('occ_page_no').AsInteger ;

      end;

      Close;

    end;

    SetComplete;

  except

    on Exception Do

    begin

      SetAbort;

      Raise;

    end;

  end;

end;

 

要注意在设置事务模式的时候,有序列号生成函数的数据窗体,必须选择 Requires a new transaction

 

31. 调用EXE文件并传入参数

program Project1;

 

uses

  Forms,

  Dialogs,

  Unit1 in 'Unit1.pas' {Form1};

 

var

  i: Integer;

 

{$R *.res}

 

begin

  Application.Initialize;

 

  for i := 1 to ParamCount do

  begin

    ShowMessage(ParamStr(i));

  end;

 

  Application.CreateForm(TForm1, Form1);

  Application.Run;

end.

//调用EXE

WinExec(PChar('d:\project2 a b'), SW_SHOWDEFAULT);

32. 数据类型 char 和 test 在 equal to 运算符中不兼容

 

原因:adoquery中的sql语句是用 = 作为比较,并且clientdataset中有参数是string类型,在给该赋值的时候实际值是‘’空字符串。

处理方法:在给参数赋值之前,判断一下,如果为‘’空字符串,则赋一个不可能存在的值给参数,或者赋quotedstr(‘’)。

33. 窗体未create,引用其中的clientdataset报错,在with DataModule2.ClientDataSet1 do这条语句就报错了

 

34. 克隆(什么时候适合用克隆,什么时候适合用ClientDataSet1.Data := ClientDataSet2.Data)

  ClientDataSet2.CloneCursor(ClientDataSet1, true);

  和

  ClientDataSet2.CloneCursor(ClientDataSet1, false);的区别

 

 

 

在复制的数据需要修改并同步到主数据集的时候用克隆,不需要提交的时候用Data赋值,要注意使用克隆的时候,两个数据集不能同时处理编辑状态,否则会出现一方数据修改,另一方没有影响的情况

ClientDataSet里的计算列、内部计算列在通过.Data赋值,或者客户端传给中间层的时候是无法传递的,但是通过 CloneCursor 克隆数据集,克隆出来的数据集和原始数据集是完全一致的,计算列、内部计算列都有。

35. 多步OLE DB操作产生错误,如果可能,请检查每个OLE DB状态值。没有工作被完成

原因:中间层的adoquery有3个参数,客户端的clientdataset有4个

处理方法:中间层和客户端的参数数量要一致,这种情况一般发生在客户端clientdataset复制的时候,复制完之后没改参数,直接使用报错。

36. 常用调试方法,跟踪程序、跟踪SQL、日志、showmessage。

在程序报错的时候用跟踪的方法找报错的语句,跟踪程序的过程中可以使用Ctrl + F7,调出

 

查看某一变量的值或者某一控件的属性,并可以修改

 

Ctrl + F5调出

 

可以跟踪变量的值的变化情况。

在查询结果或者SQL语句的执行结果和预期不同的时候用跟踪SQL语句的方法,语句优化的时候也可以用,查找运行耗时过长的SQL,有异常数据查产生原因,都和跟踪SQL语句有关。

37. 通过修改表名等方式模拟HIS失败。

 

38. 主从表

通过datasource连接主表和从表,主从表就是蜂巢结构,这种结构不好控制,有时候莫名其妙的报错,还找不到原因

39. 循环初始化数据时要考虑filter

在对数据集循环进行初始化(例如把某个字段赋值为‘1’或者通过数据和单价计算金额)时,要考虑数据集上有没有打开的filter,如果有,要注意循环里边修改的内容不能包括filter里的条件字段,如果修改了filter里的字段值,会导致初始化结果有问题,可能会有部分数据初始化失败。

40. WINDOWS 消息体系的基础培训

//消息定义(exedll都要定义)

  WM_CP_test = WM_USER + 3000;

//消息发送(dll)

SendMessage(gv_MainForm_Handle, WM_CP_test, 0, 0);

//消息接收(exe)

procedure _test(var WM_CP_test: Msg); message WM_CP_test;

 

procedure TfrmMainInput._test(var WM_CP_test: Msg);

begin

  showmessage('ok');

end;

 

 

通过SendMessage传递字符串

 

在DLL文件中使用如下代码:

MyId 定义为全局变量 String 类型

SendMessage(Form1.Handle,WM_TEST_END,Integer(@MyId),1);  
其中MyId是要返回的字符串


在主窗口中使用如下代码:
先在public中加入消息函数的声明
Delphi代码
procedure WMTestEnd(var AMsg:TMessage);message WM_TEST_END;//消息函数  
其中WM_TEST_END是自定义的消息
再在implementation写函数
Delphi代码
procedure TForm1.WMTestEnd(var AMsg:TMessage);        
var       
s:string;        
begin       
  s:=string(Pointer(AMsg.wParam)^);        
  Memo1.Lines.Add(s);        
end;    


需要注意的是,如果你在线程中,一定要使用SendMessage来发送消息,如果使用PostMessage会出错。原因我想是因为 PostMessage发送消息后线程会继续执行下去,当主窗口收到这个消息并处理时,线程可能已经结束了,这时指向字符串的那个指针就会出错;而 SendMessage发送消息后会将线程挂起,直到消息处理完成后,才继续执行下面代码。 

41. 多次open有时会影响效率,对于字典可以在窗体创建的时候一次open,中间使用时通过filter或locate取指定的值。

 

42. ClientDataSet1.DisableControls和 ClientDataSet1.EnableControls

在数据集循环时,界面上的数据感知控件是否响应数据的变化,如果响应界面上显示的内容会狂闪,而且速度很慢,一般在数据量比较大的数据集循环时先关闭DisableControls,循环之后再开启EnableControls。

43. 录入控件的相关的Lookup字段在数据集open之后dbgrid里不显示该字段的值

原因:录入控件只对当前记录进行处理,并保存处理过的Lookup字段的结果值,对于没有滚动过的记录不会处理,所以数据集open之后只有当前行的Lookup字段以及和当前行的code相同的数据行是显示值的,其它的不显示。

处理方法:1.在数据集open之后,把数据集循环一遍,每一条记录执行一次twDBEditDD1. ScrollSelf(twDBEditDD1),这种处理方法适和于数据量比较小的情况。

    2.adoquery里通过关联取出对应的字典name(假设字段名为dept_name,要设置为不提交也不作为条件),在客户端显示字典name,不显示录入控件的Lookup字段的值,在通过录入控件对数据进行修改时,编辑对应的字典name字段dept_name,适用于所有情况。

44. 循环时使数据集的acterscroll事件不执行。

var

  eAfterScroll: TDataSetNotifyEvent;

begin

  inherited;

  try

    eAfterScroll := cds_a_employee_mi.AfterScroll;

    cds_a_employee_mi.AfterScroll := nil;

    with cds_a_employee_mi do

begin

  Next;

    end;

  finally

    cds_a_employee_mi.AfterScroll := eAfterScroll;

  end;

45. OCX控件在IE中的调试方法

 

 

46. 三层程序在win7的环境下使用的主要注意事项

1.midas.dll文件要单独下载,放在windows\system32目录下

2.64位win7除midal.dll之外的dll文件放在SysWOW64目录下而不是System32目录下

 

47. ini_set_tag_sql配置tag_sql

在窗体的 FormCreate(Sender: TObject);

 

procedure TfrmInPatient.FormCreate(Sender: TObject);

var

  tcm_diag_tag: Integer;

begin

  inherited;

 

.........

 

  tcm_diag_tag := 57;

  with cdsExec do

  begin

    Data := Null;

    Close;

    CommandText :=

      'select tag_count=count(*),tag_sql_id=max(tag_sql_id) from ini_set_tag_sql where subsys_id=''adt'' and form_name=''frmInPatient'' and object_name=''edtTCMDiag'' ';

    Open;

    if FieldByName('tag_sql_id').AsInteger > 0 then

      tcm_diag_tag := FieldByName('tag_sql_id').AsInteger;

  end;

  Self.edtTCMDiag.SqlTag := tcm_diag_tag;

 

在给录入控件的 SqlTag 属性赋时,必须保证相连接的 DCOMConnection 的 computername 已经赋值,否则会引起连接本地中间层的Bug。

48. ini_set_report_code配置报表号

 

procedure TdlgDeposit_yjj.FormCreate(Sender: TObject);

begin

  inherited;

 

  iYjjZyReport := 4082; //窗体的私有变量,预交金(在院病人)报表号  

  with cdsExec do

  begin

    Close;

    Data := Null;

    CommandText := 'select yjj_count=count(*),report_code=max(report_code) from ini_set_report_code where subsys_id=''adt'' and form_name=''frmDeposit_yjj'' and form_no=''yjj_zy''';

    Open;

    if FieldByname('yjj_count').AsInteger > 0 then

      iYjjZyReport := FieldByName('report_code').AsInteger;

 

  end;

 

 

49. 在界面上显示报表预览

select * from rt_report_data

select * from rt_report_params

 

rt_report_data.report_flag表示报表类型 普通报表 交叉报表 f FastReport

 

步骤:

1.窗体继承自 frmChildprintForm

//以下在窗体的FormCreate中:

2.取自定义报表号(如果是固定报表号,可以省略这个步骤)

//以下在预览按钮的单击事件里:

3.通过 getreportEx(报表号) 或getreport(报表号),getreportEx比getreport多一段代码,暂时没看懂那段代码的功能。

4.给报表中的特殊 qrlabel.caption 赋值,一般是对表头赋值

  for i:=0 to self.componentcount-1 do

  begin

    if components[i] is Tqrlabel then

    begin

      if components[i].Name='lbl_pid' then

         Tqrlabel(components[i]).caption:=

                cds_zyactpatient.fieldbyname('inpatient_no').value;

      if components[i].Name='lbl_name' then

         Tqrlabel(components[i]).caption:=

                cds_zyactpatient.fieldbyname('name').value;

      if components[i].Name='lbl_bedno' then

         Tqrlabel(components[i]).caption:=

                cds_zyactpatient.fieldbyname('bed_no').value;

    end;

  end;

5.给报表参数赋值

  with cdsSQLParams do

  begin

    //病人ID

    if Locate('param_name','patient_id',[loPartialKey]) then

    begin

      Edit;

      FieldByName('param_defaultvalue').Value := sPatient_id;

    end;

    //入院次数

    if Locate('param_name','times',[loPartialKey]) then

    begin

      Edit;

      FieldByName('param_defaultvalue').Value := sTimes;

    end;

  end;

6.  getdataEx;

7.  PreviewReport;

//以下在打印按钮的单击事件里:

8.  PrintReport;

 

50. 对将要提交的数据集做限制,满足某些条件时才允许提交

1.如果要限制的数据集已经有一些现在的限制,增加的时候采用与现有限制相同的方式来做

2.在befortpost里判断

procedure TdmYzInput.cdsActOrderBeforePost(DataSet: TDataSet);

begin

  inherited;

 

......

 

  if (DataSet.FieldByName('Serial').AsString <> '**') and

    (DataSet.FieldByName('supply_code').AsString = '') then

  begin

    SelectMessageBox('药品医嘱必须录入给药方式!', 1, 1);

    TfrmMainInput(CurrentInputForm).edt_supply.SetFocus;

    Abort;//这里必须用Abort,用exit起不到限制的作用

  end;

3.在数据真正保存之前,循环判断,要注意,在循环之前 DisableControls,循环之后 EnableControls

51. 判断当前记录的状态status(clientdataset1. UpdateStatus)

      while not cdsCheck.Eof do

      begin

        case cdsCheck.UpdateStatus of

          usInserted: //插入

            begin

              ......

            end;

 

          usDeleted: //删除

            begin

              ......

            end;

 

          usModified: //修改

            begin

              ......

            end;

        end;

        cdsCheck.Next;

      end;

52. 判断数据集的当前状态(dsinsert,dsedit)

    //判断数据

    if CdsActOrder.State in [dsEdit, dsInsert] then  

      CdsActOrder.Post;

判断数据集的当前状态,一般的用法是:

  1.在开始编辑之前,判断一下,如果不在编辑状态,则 ClientDataSet1.Edit或ClientDataSet1.Append

  2.在ApplyUpdates之前,判断数据集是否在编辑状态,如果在,则post。

53. 通过dll_print.dll打印报表

在ADT源码里,搜索 dll_print.dll 根据找到的内容拷贝。

54. cannot focus a disabled or invisible window

在 DBGrid1.setfocus 的时候,如果 DBGrid1 不能接受焦点(例如Enable = false),就会报这个错误。

55. data := null

对于通过参数赋值再open的数据集,在Close之后,要执行 ClientDataSet1.Data := null,清空旧的数据,再对参数赋值,再open,否则有可能因为旧数据已经存在,导致不执行SQL语句。

56. adoquery 的参数默认值的作用

在ClientDataSet1.applyupdates的时候,系统会首先以默认参数发出adoquery1里写的select 语句,如果这时默认的参数值可以查出10W条数据,就会产生相应的网络流量,数据量越大,速度就会越慢,所以adoquery1里的参数默认值尽量设定为不可能查到数据。

57. EmptyDataSet

保持字段结构不变,清空数据

58. MergeChangeLog

清空所有记录的修改日志,并将ChangCount属性重置为0,如果数据不是直接applyupdtes的,真是通过Delta到中间层里提交,那每次提交之后必须调用 MergeChangeLog。

 

======================================未讲内容

59. 事务

当一组语句构成一个事务处理时,如果一个语句没有执行成功,则所有的语句都不成功。如果你需要更新多个表中的数据,你不希望对一个表的操作失败,而对其它表的操作成功了。这时就需要用到事务。

60. SQL优化

61. 排序、动态排序

一般是对数据集ClientDataSet中的数据进行排序,可以通过以下几种方式:

1.IndexFieldNames

2.

62. 焦点的控制

63. 中间层安装时如果报“对象已被注册”,必须处理之后再装一下,否则会有异常,有可能连接的中间层还是老的。

如果当前模块的中间层已经安装,现在想要重新安装一下,如果以前安装的没删除,新安装的时候会报错,“对象已被注册”,这时候新的中间层是没有安装的,必须处理之后再安装一下,否则还是执行的老版本的中间层。

64. 中间层数据类型冲突

 

这个错误提示表明:数据集ClientDataSet1里的字段py_code定义的是Integer型,SQL语句返回的这个字段的值是String类型

 

 

 

65. Filter对于中文支持不好,如果用 like ‘%中文%’,会查不到数据

 

66. 凡是客户端dll文件,必须有初始化函数和释放函数。

 

67. 根事务需要确认,但事务终止了操作(触发器执行失败)

 

68. 在数据明显超过一屏幕的情况下,DBGrid右侧没有显示上下的滚动条

DBGrid换成DBGridEh,然后把上下的滚动条设置成始终显示

 

69. List index out of bounds (0)

 

参数数量不符,一般是在调用中间层函数的时候,客户端提供的参数和中间层函数实际的参数数量不一致,大部分时候是由于客户端版本和中间层版本不一致造成的,应对方法是发出最新版本的配套程序,或者工程自行找到配置的程序。

 

70. 在使用颜色的时候尽量不要用类似“clWindowText”这种系统颜色

这种颜色会随着操作系统主题改变,用“clBlue”这种指定的颜色就不会有这种问题

 

71. 调用动态创建的变量或动态加载的dll函数之前,必须用Assigned判断一下,不能直接调用

原因是如果这个变量(函数)没有创建(加载)会报地址错。

 

72. Expression expected but nothing found

 

  with ClientDataSet1 do

  begin

    CreateDataSet;

    AppendRecord(['01', '']);

    AppendRecord(['02', '']);

 

    Filtered := False;

    Filter := 'code = ' + '';

    Filtered := True;

  end;

 

73. 在程序中禁止使用录入控件的ListSource指定的clientdataset做查询,例如:cdsDict。

 

74. 中文做为参数的注意事项

使用参数的方式做查询或执行SQL语句的时候,要注意,如果参数的内容有可能是汉字,则需要在参数的内容右边加几个空格,因为参数会把汉字做为一个字符来计算宽度,然后传到中间层的参数尾部就会有一部分内容被截掉,造成参数的内容错误。

75. 关于中间层事务

    写中间层函数,必须有SetComplete 和 SetAbort,不管有没有数据需要提交,如果是纯查询的函数,必须写nolock(锁定不更改),建议纯查询的内容放在data中间层,用adoquery来实现,不要写中间层函数。

 

程序中使用的字典数据集,如果除了即用于filterlocate也用于lookup字段,就必须要清楚,lookup字段的内容是会在数据集Edit的时候对LookupDataSet里关联的数据集进行隐性的locate

 

Locate 命令的第三个参数:Options: TLocateOptions,其中参数值 loPartialKey 的作用是:模糊查询、部分匹配,就是从最左侧开始算,只要locate命令中的值在字段值当中存在就可以,不需要完全相等,例如对code字段进行查询,数据集的有三条记录,其中字段 code 的值如下:

00102

00103

00201

locate('code', '002', []);是查不到数据的

locate('code', '002', [loPartialKey]);是可以查到数据的

所以,如果你不需要模糊查询的时候,第三个参数,不要加 loPartialKey。

 

在中间层函数里,如果有类似下面这种代码,一定要先写SetAbort,再写Raise,就是说要先回滚事务,再抛出异常。

            SetAbort;

            Raise Exception.Create('打开分摊最高限价表“zd_charge_item_limit”异常:' + e.Message);

            Exit;

 

 

通过appserver方式调用中间层函数的时候报错“无效的被呼叫方”

参数的in,out类型,或TLB定义的类型与你传入的参数类型不匹配,一般是中间层参数定义的类型是out,但是在客户端调用的时候使用了常量。

 

 

Raise 在中间层抛出异常给客户端,在客户端可以用

try 

except 

      on E: Exception do

  begin

    showmessage(E.message);

  end;

end 

来捕获,这样就可以获取中间层抛出的错误信息。

 

 

报表参数问题,现在系统维护做报表的时候,参数最多支持到10位,如果再长,在给参数定义类型的时候会被截断,所以如果程序里的参数名字是超过10位的,系统维护又做不出超过10位参数名的报表,结果就是这报表废了。

 

 

Data Controls 控件组里的 DBRadioGroup 在数据集的前当记录变更的时候,如果关联字段的值改变,这个控件会自动触发OnChange事件,DBCheckBox 在相同的情况下,会自动触发单击事件OnClick,如果这两个控件的这两个事件里写过代码,需要注意这事,在数据集关闭、打开的时候,如果字段值改变也会触发这两个事件。

 

====以下内容未经过确认==========================

 

如果Delphi在编译的时候不该加点的地方加了编译蓝点,单步时乱走乱跳,可以把代码copy到记事本中,用纯文本查看,有可能有怪字符。

 

 

在安装中间层DLL时报TYPELIB无法加载,是由于DELPHI生成的DCOM不是标准的DCOM,必须要MIDASDLL来支持,必须在system32COPY Midas.dll,再在COM+中安装DLL

 

 

在写SQL语句有UNION的地方请注意写UNION ALL,否则出来的结果莫名其妙,有时候正确,有时候不正确,不正确的数据即不是上部分的结果也不是下部分的结果,这一般出现在UNION中的一块没有结果集。

 

 

一预览报表,程序就消失,有可能的原因:本地没有安装打印机驱动

 

 

COM+组件进行了调用,但是组件方法已被终止。

这是由于在SetAbort后没有写退出语句仍然往下执行,下面还有对数据库的操作,所以报错.

 

 

无效的索引。原因:中间层ADOQUERY定义的参数与客户端CLIENTDATASET的参数数量不一致。

 

 

分布式事务已完成,请将此会话登记到新的事务或Null事务中。原因:是SQL的参数是非法数据。例如需要一个日期参数,但是进去的是一个Float,转换不过去 ,就报错

 

 

仔细介绍入院录入的配置文件“InPatientInput.xml”

 

 

暂时关闭某个控件的事件响应,例如afterscroll

 

 

 

添加 fkInternalCalc 计算字段后打开记录集出错 name not unique in this context

 

 

 

除了有可能是dcomconnectionconnected没有置为true之外,还有可能是老版本的中间层,这个函数根本不存在 

关于savetofile

    1.如果clientdataset active 为 false,则savetofile不会生成文件

    2.如果clientdataset active 为 true,则savetofile会生成cds文件,如果clientdataset 里有数据,那生成的cds文件也会有数据,并且不受filter的影响(就是说如果clientdataset里是有数据的,即使filter导致当前的recordcount0savetofile生成的cds文件里也会有数据),如果clientdataset中没有数据,则生成的cds文件有结构,没有数据

 

DBGridEh里,如果有字段在footer里计算合计,则关联数据集在open的时候,会自动遍历所有数据(触发afterscroll事件,相当于从头到尾循环一遍)

 

TDBCheckBox控件,在关联的字段赋值的时间会自动触发OnClick事件,如果不想触发,在关联的数据集赋值之前用 DisableControls ,关闭自动感知控件的响应就可以了。

 

录入控件相关的编码,如果需要扩位,有时会出现录入控件选择了新宽度的项目之后,不显示名称,编码尾部被截断的情况,这种现象的原因是中间层取了固定列,并且相关编码的位数比较小。

 

 

至少一个参数没有被指定值

1.录入控件中,如果有参数没有被赋值有可能会报这个错误

2.open的时候,数据集的入参有为null或没有赋值而且没有默认值的。

76. 确定程序中会执行SQL语句,但是在数据库上跟踪不到

1.查一下SQL Server Profiler是不是有筛选器

2.查一下数据库的连接,是不是指向另外的库了。

77. 浮点数比较的精度问题

    在SQL SERVER数据库中,由于运算精度的原因,有时float类型的数据会出现把1存成0.9999999或1.00000001这样的数据,这样的数据在进行浮点数之间的比较尤其是相等比较时会出现误差,

    例如下面这段代码:

procedure TForm1.Button1Click(Sender: TObject); 
var 
  a,b: double; 
begin 
  a := 2.0; 
  b := 1.99999999; 
  if a = b then 
    ShowMessage('相等') 

  else 
    ShowMessage('不相等'); 

end;

 

会弹出提示,“不相等”,如果比较的是金额,就会把本来相等的金额,误判成不相等。

解决方案1:

  if Round(a * 100) = Round(b * 100) then 
解决方案2:

  if abs(a - b) < 0.001 then 

 

78. Filter速度比较慢

    1.有可能是数据集有index,去掉之后可以加快速度

 

 

 

0 0
原创粉丝点击