commandtext为select语句没问题,但为insert,delete或update时,灾难性错误!!!(100分)

  • 主题发起人 主题发起人 wmwin
  • 开始时间 开始时间
W

wmwin

Unregistered / Unconfirmed
GUEST, unregistred user!
当commandtext改为insert或delete,update时,我已经把clientDataSet.open改为
clientDataSet.Execute了,执行到这里,出现“灾难性错误”,请问应该如何处理?
另外,我觉得如果在客户端这样来进行Sql语句编写,不太符合三层结构的宗旨:
用户界面+应用逻辑+数据层,实际上中间层没有太大作用,应用逻辑还是停留在用户界面
层,没有分开,不知道诸位大虾如何看待这个问题?
 
将DataSetProvider的Options:poAllowCommandText:=True;
 
我已经将DataSetProvider的Options:poAllowCommandText选定了,否则,怎么可以正确
执行select语句呢?关键是,Select 和Insert、Update等在执行时是否有不同的方法?
 
这样吧
sql:='update xstable set IP='+#39+ips+#39+',tag=0 where xh='+#39+xsno+#39+' and bj='+#39+no+#39;
data2.Close;
data2.Provider.DataRequest(sql);
 
试一下:database1的handleshared设为true
 
同意
hcai
 
顶一下。我今天也遇到这个问题了,不知道怎么解决。。。
有没有前辈解决的?
 
怎么没有人回答呀 。我再加200分。
 
设置 DataSetProvider.ResolveToDataSet := True
再试试。
我这样用一直没有问题。
 
我完全同意你的观点。如果客户端写SQL语句,中间层没发挥什么作用。这也不符合组件化的思想,同时也不符合Midas的设计思想,也不符合面向对象的思想。
我也正在做这方面的探索。我可以提供你一些代码,也许对你又帮助。如果你搞定了也告诉我。(这是李维写的《Delphi5.xADO_MTS_COM+高级程序设计篇》书的第9章)
实现M T S / C O M +更新对象
首先如同前面实现 M T S / C O M +查询对象一样,请先建立一个 ActiveX Library项目,然后在项目中建立一个 M T S / C O M +对象。但是由于这个对象是负责更新数据的,因此设定它的事务模式为“需要事务”,如图9 - 1 5所示:

接着再于项目中建立一个数据模块,并且在数据模块中加入三个 T D C O M C o n -n e c t i o n组件,分别连接到前面实现的三个 M T S / C O M +数据模块。如图9 - 1 6所示。

为什么M T S / C O M +更新对象只使用了T D C O M C o n n e c t i o n组件连接M T S / C O M +数据模块,而不像 M T S / C O M +查询对象也使用 T C l i e n t D a t a S e t组件呢?这是因为这个M T S / C O M +更新对象是从客户端接收更新数据的 M I D A S数据封包。当它收到这个M I D A S封包之后, M T S / C O M +更新对象只要再把 M I D A S数据封包直接传递给M T S / C O M +数据模块更新数据即可。 M T S / C O M +更新对象本身并不再需要使用T C l i e n t D a t a S e t组件暂时储存任何数据,这样可以加快它的执行效率。
由于M T S / C O M +更新对象也使用了数据模块,因此它也和 M T S / C O M +查询对象一样需要在析构函数和 I n i t i a l i z e方法中释放和建立数据模块对象:
d e s t r u c t o r T m t s U p d a t e C o o r O b j . D e s t r o y ;
b e g i n
i n h e r i t e d;
F M y D M . F r e e ;
e n d;
p r o c e d u r e T m t s U p d a t e C o o r O b j . I n i t i a l i z e ;
b e g i n
i n h e r i t e d;
FMyDM := TdmUpdateCoor.Create(Forms.Application);
e n d;
接着激活可视化Type Library编辑器,为这个M T S / C O M +更新对象定义方法以便让客户端调用。图 9 - 1 7显示了 M T S / C O M +更新对象对外界提供的三个方法。此外,每一个更新数据的方法都接受三个参数:第一个参数 v D a t a s是需要更新的数据;第二个参数 i M a x E r r o r是客户端可以接受的更新错误的笔数;最后一个参数是[ i n , o u t ]的参数,这个参数会由 M T S / C O M +数据模块更新数据完毕之后填入在更新数据回数据库的过程中到底发生了多少笔错误。事实上,这三个参数的意义和使用的方法和I A p p S e r v e r接口的A S _ A p p l y U p d a t e s方法是一样的。

下面的程序代码显示了这个M T S / C O M +更新对象如何把数据真正更新回数据库中,你可以看到, M T S / C O M +更新数据通过它的数据模块中的 T D C O M C o n n e c t i o n组件连接到M T S / C O M +数据模块,再调用 M T S / C O M +数据模块的U p d a t e D a t a s方法以更新数据。最后根据状态来调用 S e t C o m p l e t e和S e t A b o r t以便释放M T S / C O M +更新对象占用的资源。
p r o c e d u r e TmtsUpdateCoorObj.UpdateBooks(vDatas: OleVariant;
iMaxError: Integer;
v a r iErrorCount: Integer);
b e g i n
t r y
FMyDM.dcomcBooks.AppServer.UpdateDatas(vDatas, iMaxError,
i E r r o r C o u n t ) ;
S e t C o m p l e t e ;
e x c e p t
S e t A b o r t ;
e n d;
e n d;
p r o c e d u r e TmtsUpdateCoorObj.UpdateCDTitles(vDatas: OleVariant;
iMaxError: Integer;
v a r iErrorCount: Integer);
b e g i n
t r y
FMyDM.dcomcCDs.AppServer.UpdateDatas(vDatas, iMaxError,
i E r r o r C o u n t ) ;
S e t C o m p l e t e ;
e x c e p t
S e t A b o r t ;
e n d;
e n d;
p r o c e d u r e TmtsUpdateCoorObj.UpdatePublishers(vDatas: OleVariant;
iMaxError: Integer;
v a r iErrorCount: Integer);
b e g i n
t r y
FMyDM.dcomcPublishers.AppServer.UpdateDatas(vDatas, iMaxError,
i E r r o r C o u n t ) ;
S e t C o m p l e t e ;
e x c e p t
S e t A b o r t ;
e n d;
e n d;
从上面的程序代码中我们可以知道,在每一个 M T S / C O M +数据模块中必须定义一个方法 U p d a t e D a t a s,让M T S / C O M +更新对象调用,以便更新数据。这是因为M T S / C O M +更新对象不知道如何更新数据,这个工作应该由单个的 M T S / C O M +数据模块来进行,因此 M T S / C O M +更新对象调用了M T S / C O M +数据模块的 U p d a t e D a t a方法来实际地更新数据。这种设计除了前面说明的可以增加 M T S / C O M +应用系统的资源使用率和执行效率之外,也非常符合对象导向的设计。虽然在这个范例中M T S / C O M +更新对象似乎除了调用M T S / C O M +数据模块更新数据之外并没有做其他的工作,因此看起来似乎是多余的。但是你不要忘了,即使是在这个简单的范例中M T S / C O M +更新对象也具备了激活事务管理的功能,因此它能够让更新数据的过程保护在Two-Phase Commit的功能之中。在实际的应用系统中,M T S / C O M +更新对象可以再执行安全管理以及执行状态登录等的工作。
完成这个范例的最后一个步骤是再为每一个 M T S / C O M +数据模块加入一个U p d a t e D a t a s方法,让 M T S / C O M +更新对象调用以便把数据真正更新回每一个M T S / C O M +数据模块代表的数据表中。因此请你在 D e l p h i的集成开发环境中激活前面实现的M T S / C O M +数据模块,再激活可视化 Type Library编辑器,然后加入这个方法。例如,图 9 - 1 8便是在m t s P u b l i s h e r s这个M T S数据模块中加入 U p d a t e D a t a s的画面。

当然,M T S / C O M +数据模块也必须实现 U p d a t e D a t a s方法。由于M T S / C O M +数据模块中已经使用了 T D C O M C o n n e c t i o n、T C l i e n t D a t a S e t和T D a t a S e t P r o v i d e r组件,因此我们只需要简单地调用 T D a t a S e t P r o v i d e r组件的 A p p l y U p d a t e s方法更新即可。
下面就是m t s P u b l i s h e r s实现U p d a t e D a t a s的程序代码:
p r o c e d u r e TmtsPublishers.UpdateDatas(vDatas: OleVariant;
iMaxErrors: Integer;
v a r iErrorCount: Integer);
b e g i n
t r y
// statements to try
dspPublishers.ApplyUpdates(vDatas, iMaxErrors, iErrorCount);
S e t C o m p l e t e ;
e x c e p t
S e t A b o r t ;
e n d;
// try/except
e n d;
从这个范例中可以看到我们如何融合 D e l p h i的M I D A S和M T S / C O M +程序设计为一体。由于 M I D A S的数据封包可以包含新增的数据、更新的数据以及删除的数据,因此上面的范例可以简单地声明一个 U p d a t e D a t a s方法就可以更新各种的数据回数据库中,程序员不再需要像 V B或V C + +一样撰写更新各种类型数据的复杂又无趣的程序代码。 M I D A S不但已经实现了这些功能,还能够更新 M a s t e r-D e t a i l类型的数据,因此我们直接使用 M I D A不但可以提高生产力,而且也不容易出错。
在上面的 M T S / C O M +更新对象中,它使用 T D C O M C o n n e c t i o n对象并且需要M T S / C O M +数据模块定义一个更新数据的方法让 M T S / C O M +更新对象调用。当然你也可以不这样做,可以直接在 M T S / C O M +更新对象中取得 M T S / C O M +数据模块的I A p p S e r v e r接口,再直接调用 I A p p S e r v e r接口的 A S _ A p p l y u p d a t e s方法。例如,我们可以重新撰写M T S / C O M +数据模块的U p d a t e B o o k s如下:
p r o c e d u r e TmtsUpdateCoorObj.UpdateBooks(vDatas: OleVariant;
iMaxError: Integer;
v a r iErrorCount: Integer);
v a r
ServerObj : IAppServer;
OwnerData : OleVariant;
b e g i n
t r y
ServerObj := FMyDM.dcomcBooks.AppServer
a s I A p p S e r v e r ;
IAppServer.AS_Applyupdates('dspBooks', vDatas, iMaxError,
iErrorCount, OnwerData);
S e t C o m p l e t e ;
e x c e p t
S e t A b o r t ;
e n d;
e n d;
使用这种方法就不需要在 M T S / C O M +数据模块中再定义方法让 M T S / C O M +更新对象调用。不过这种方法也有一些问题,那就是 M T S / C O M +更新对象必须在程序代码中写死要使用的 T D a t a S e t P r o v i d e r组件的名称。要解决这个问题,你可以使用I A p p S e r v e r接口中的 A S _ G e t P r o v i d e r N a m e s来弹性地取得 M T S数据模块中的T D a t a S e t P r o v i d e r组件的名称。在稍后的章节中将会讨论更多的实现程序代码。
 
DataSetProvider.ResolveToDataSet := True
通过数据集提交Sql
 
clientdataset.providername := DataSetProvider1;
 
請問一下 MIDAS 的全稱是什么
 
database1的handleshared设为true
在检查一下要delete或update的表是否有外健约束
 
DataSet中的CommandText
Query中的SQL
通常我们要执行插入,修改,操作都 用TQuery
ADOQuery1.sql.add('');
ADOQuery1.ExecSQL
 
不知道你的中间层是不是通过ADO连接的,如果是,试试改用ODBC,我原来是用ADOconnect连接的,出了和你一样的错,后来用ODBC就没问题了
 
不能直接执行修该语句要先查询出结果,再修改,
CLIENT.COMMANDTEXT:='SELECT * FRO MTALBE1';
CLIENT.OPEN;
CLIENT.COMMANDTEXT:='UPDATE TABLE1...'
CLIENT.Execute;
我也遇到过记得是这样一来就可以更改,通过了别望了给我分啊
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
948
import
I
I
回复
0
查看
627
import
I
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部