欢迎大家来谈谈在做数据库系统时,如何更好的做到数据库完整性? (DELPHI异常捕捉???) (200分)

  • 主题发起人 主题发起人 KeepObject
  • 开始时间 开始时间
可以在建立数据库的时候 设定各个表之间的关系
实施参照完整性
级联更新相关字段
级联删除相关字段
 
级联删除 可不允许啊~!!!
 
肯定是有办法提取ado错误的!
我是一直用bde的!上次还和一个人讨论过这个问题!
ado也有类似的一端程序!不过提取的方法和BDE不一样!
我再找找!
 
抄书:
D O E x p r e s s组件在发生错误时产生的例外对象并不像B D E / I D A P I
一样是E D B E n g i n e E r r o r对象,因此我们无法像B D E / I D A P I的应用程序一样从
E D B E n g i n e E r r o r取得原生的错误代码。如果你检查封装A D O E x p r e s s组件的
A D O D B程序单元,也会发现A D O的错误是由E A D O E r r o r类别封装的。
{ Errors }
EADOError = c l a s s( E D a t a b a s e E r r o r ) ;
因此要取得A D O详细的错误信息,就必须通过A D O的E r r o r s和E r r o r对象。让
我们修改前面O n P o s t E r r o r的事件处理程序如下所示:
p r o c e d u r e TForm4.ADODataSet1PostError(DataSet: TDataSet;
E:
EDatabaseError;
v a r Action: TDataAction);
v a r
adoErrors : Errors;
adoError : Error;
iCount : Integer;
b e g i n
/ /开始处理A D O的E r r o r s对象
adoErrors := ADOConnection1.Errors;
f o r iCount := 0 t o adoErrors.Count - 1 d o // Iterate
b e g i n
adoError := adoErrors.Item[iCount];
lbADOErrors.Items.Add('Error Number : ' + IntToStr(adoError.Number));
lbADOErrors.Items.Add('Error Source : ' + adoError.Source);
lbADOErrors.Items.Add('Error Description : ' + adoError.Description);
lbADOErrors.Items.Add('Error HelpFile : ' + adoError.HelpFile);
lbADOErrors.Items.Add('Error SQLState : ' + adoError.SQLState);
lbADOErrors.Items.Add('Error NativeError : ' +
I n t T o S t r ( a d o E r r o r . N a t i v e E r r o r ) ) ;
e n d ;
// for
e n d ;
A D O E x p r e s s的TA D O C o n n e c t i o n组件封装的E r r o r s属性就是A D O的E r r o r s集合
对象。
 
这段程序应该可以改装放到application的onexception中这样就可以不用
每个posterror写程序了!然后根据adoError.Number汉化你的错误信息!就应该
和bde的处理方法一样了!
原生错误码
case AdoConnection.Errors.NativeError of
1 : .......
.....
end;

其中错误码及其含义可直接查阅Sql Server帮助
Errors 1-999
Errors 1000-1999
 
vmao,刚作了个试验,我在作删除外键引用了的主键时,捕获AdoConnection1.Errors.Count
竟然为0.不知是哪儿有问题.不过,这段代码我是写于DataModul的一个过程中,然后在出错
时事务Rollback后调用这个过程.我的事务不是在DataModul中,而是在执行代码当中启用.
代码大致如下:
TAdoQuery(grdDataList.DataSource.DataSet).Connection.begin
Trans;
try
grdDataList.DataSource.DataSet.Delete;
TADOQuery(grdDataList.DataSource.DataSet).UpdateBatch();
TAdoQuery(grdDataList.DataSource.DataSet).Connection.CommitTrans;
except
TADOQuery(grdDataList.DataSource.DataSet).CancelBatch();
TAdoQuery(grdDataList.DataSource.DataSet).Connection.RollbackTrans;
DmData.CaptureDatabaseErrorMsg;
end;
////以上为"删除"按钮Click中的代码,代码倒数第二行中的DmData.CaptureDatabaseErrorMsg;
就是一个捕获错误的过程,代码如下:
procedure TDmData.CaptureDatabaseErrorMsg();
var
i:integer;
begin
showmessage('Errors Count:'+inttostr(AdoConnection1.Errors.Count));
for i:=0 to AdoConnection1.Errors.Count-1do
begin
showmessage(inttostr(AdoConnection1.Errors.Item.NativeError));
showmessage(inttostr(AdoConnection1.Errors.Item.Number));
showmessage(AdoConnection1.Errors.Item.Source);
showmessage(AdoConnection1.Errors.Item.SQLState);
end;
end;

**** 以下我跟踪得到 AdoConnection1.Errors.Count为0,但明明是有个错误嘛.
**** 另做了一个主键重复的测试,跟踪后得到NativeError=0,ADO连接SQL SERVER中主键重
复的错误号是不是0呀????
兄弟哥们快来讨论讨论吧 [:(][:(][^][^]
 
关注下列问题,一定对你有益:
http://delphibbs.com/delphibbs/dispq.asp?lid=1743719
http://delphibbs.com/delphibbs/dispq.asp?lid=1742072
http://delphibbs.com/delphibbs/dispq.asp?lid=1655569
http://delphibbs.com/delphibbs/dispq.asp?lid=1786356
 
我测试了一下主键错误是可以用你的方法栏住的!
如果你对拦截的要求不高的话!
你可以在application的onexception中写showmessage(e.message)
这样所有的错误都能捕捉到!
其次,本来想多取点信息的!所以这样改》:
在onexception中这样写:
if (e is edatabaseerror) then

begin
showmessage(e.message);
for i:=0 to adoconnection1.errors.count-1do
showmessage(inttostr(AdoConnection1.Errors.Item.NativeError));
end;

我突然发现如果不是缓存更新的话就能正确执行
如果缓存更新的话就不行了! if (e is edatabaseerror) then
进不去e不是edatabaseerror!
很奇怪!但是用你的方法在try..except拦截不管是否缓存更新都是没有问题的啊!
 
一群笨蛋。
 
在application的onexception中写showmessage(e.message),这个都知道,只是它提供的信
息也让用户很不明白的,看上去就是个系统错误!
vmao,还有不知你在作外键引用的主键记录删除时,这个错误在你试验的时候能不能捕获.
我这边好像是不行的.这想依我那样写的错误捕获,应该是没有问题的吧?? 还是哪儿有错误
呢??? [:(]
 
无能为力了!我只知道这么多!
ado的错误机制我也搞不清楚!我一直是用BDE的!
 
数据库编程大致有三种:
1)BDE:错误捕捉用EDBEngineError
2)ADO:错误捕捉用AdoConnection.Errors
3)dbExpress:错误捕捉EDatabaseError/EUpdateError/??????
*-----------------------------------------------------------
BDE,ADO都可以返回服务器端的返回的错误号和错误提示,以MSSQL为例,会返回如下的
错误提示:
---无法将Null值插入列'dqmc',表'xs_02_2003.dbo.a_diqu';该列不允许空值,Insert失败
---违反了Primary Key约束'PK_a_diqu',不能在对象'a_diqu'中插入重复键
---违反了Unique Key约束'IX_a_diqu',不能在对象'a_diqu'中插入重复键
有了错误号#-21.....,和错误提示中的对象名称、表名、约束名、列名....,很容易就可
用一个集中的自定义的数据字典在application的onexception中写出一个通用的错误处理,完
全用不着到处try....except...end;
很爽
当然,BDE更好一些,有数据字典,这是ADO没有的。可惜,Borland已经放弃了BDE,在微软
的屋檐下,ADO能活得似乎长远一些。
*-----------------------------------------------------------
dbexpress的错误提示在E:Edatabase(没有错误号),或者E:EUpdateError(有错误号Errorcode)中,但是
令人气愤的是二者的E.Message返回的都是“sql state:01000, sql error code:3621”,“sql state:23000,
sql error code:2627”,除了这样的数字之外,根本没有服务器端返回的错误提示!!!!
*-----------------------------------------------------------
这些天一直在思考dbexpress + microsoft sql server的错误捕捉,无解,郁闷!
借搂主的这个问题请教高人,dbexpress该如何返回服务器端的错误提示!因为这个问题不解决,
dbexpress就没法用!
只要dbexpress能得到服务器端的错误提示,500分奉送!决不食言。
*-----------------------------------------------------------
另外:
>方法二: 程序设计上,在各种操作提交前通过查询等,自行判断用户操作的合法性,好处是比较
> 灵活,但比较烦(要比较全面的预测出用户的各种操作,少一个软件就有bug),另一个
> 不好就是效率低,都是客户端操作,很多select等语句,会增加服务器的负担
> (一个解决方法是把这些业务逻辑都转移到中间层)
这种方法根本不可取!如同关蚊帐之前,在蚊帐外面检查了没有蚊子,就钻进蚊帐内睡觉,
难保晚上不被蚊子叮成“包公”,因为就在您钻进蚊帐的那一刹那间,蚊子已经先于您飞了
进去!这仅仅是为了给用户一个明确的错误提示而采取的一种不得已而为之的办法!
 
完全同意ctuacc,特别是第二点.
希望对此问题有更高的高手来指点指点....
[:D]
 
做一个编码管理模块呀,
这种模块都是公用的,什么系统都用的着,这个模块就是专门用来解决这种问题的
我师父现在就在做这个模块
 
lyjgs.168,你师父是谁呀? [8D]
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部