关于COM+ 多层分布式应用多表更新的问题(ADO)(100分)

  • 主题发起人 主题发起人 Dephic
  • 开始时间 开始时间
D

Dephic

Unregistered / Unconfirmed
GUEST, unregistred user!
刚才打了一半天,竟出错,又重打了一轮,倒。。。。
具体情况:
机器的软件环境:win2000服务器版+SQLSERVER2000企业版
底层MTS数据模块(TMtsDataModule):TADOConnection + TADODataSet +TDataSetProvider
TDataSetProvider.ResolveToDataSet:= true
TDataSetProvider.OPtions := [poAllowCommandText]
接口过程:
//Delta为从MTS协调层(MTSOBJECT)的ClientDataSet传下来的更新数据封包
//SQLSTR为在 ClientDataSet上执行的SQL语句,执行的是的存储过程
procedure TCreditManageDM.UpdateCreditManage(Delta: OleVariant;
MaxError: Integer;
const SqlStr: WideString;
var ErrorCount: Integer);
begin
adodsCreditManage.CommandText := SqlStr;
dspCreditManage.ApplyUpdates(Delta,MaxError,ErrorCount);
end;

//BeforeUpdateRecord处理事件
procedure TCreditManageDM.dspCreditManageBeforeUpdateRecord(
Sender: TObject;
SourceDS: TDataSet;
DeltaDS: TClientDataSet;
UpdateKind: TUpdateKind;
var Applied: Boolean);
begin
//删除三个字段的可更新数据标记,以防止其更新入数据库
if (pfInUpdate in DeltaDS.FieldByName('SpecialtyName').ProviderFlags) then
DeltaDS.FieldByName('SpecialtyName').ProviderFlags :=
DeltaDS.FieldByName('SpecialtyName').ProviderFlags - [pfInUpdate];
if (pfInUpdate in DeltaDS.FieldByName('SubjectTypeName').ProviderFlags) then
DeltaDS.FieldByName('SubjectTypeName').ProviderFlags :=
DeltaDS.FieldByName('SubjectTypeName').ProviderFlags - [pfInUpdate];
if (pfInUpdate in DeltaDS.FieldByName('TeacherName').ProviderFlags) then
DeltaDS.FieldByName('TeacherName').ProviderFlags :=
DeltaDS.FieldByName('TeacherName').ProviderFlags - [pfInUpdate];
end;

ClientDataset执行的存储过程:
--WDQ
CREATE PROCEDURE GetTermLesson --学期开课表
@GradeInSchool varchar(20), --年级
@SpecialtyNo varchar(5), --专业代码
@SubjectNo varchar(20), --科目代码
@SubjectName varchar(30), --课程名称
@SubjectTypeNo varchar(5), --课程类型 必修,选修等。。
@TeacherNo varchar(20), --教师代码
@TeacherName varchar(20), --教师姓名
@IsOpen1 Bit, --是否开课 0-不开课
@IsOpen2 Bit, --是否开课 1-开课
@Term varchar(9), --学期
@GradeMode1 bit, --评分方法 0-等级评分 1-成绩评分
@GradeMode2 bit --评分方法 0-等级评分 1-成绩评分
AS
begin
SELECT A.ID ,
A.GradeInSchool,
A.SpecialtyNo,
B.Name AS SpecialtyName,
A.SubjectNo,
A.SubjectName,
A.SubjectTypeNo,
D.Name AS SubjectTypeName,
A.TeacherNo,
C.Name AS TeacherName,
A.IsOpen,
A.Term,
A.Credit,
A.Factor,
A.PassScore,
A.MaxNum,
A.MinNum,
A.GradeMode
FROM
TermLesson AS A
LEFT JOIN SpecialtyInfo AS B ON A.SpecialtyNo = B.SpecialtyNo
LEFT JOIN TeacherInfo AS C ON A.TeacherNo = C.TeacherNo
LEFT JOIN SubjectType AS D ON A.SubjectTypeNo = D.SubjectTypeNo
WHERE
A.GradeInSchool LIKE @GradeInSchool AND --年级
A.SpecialtyNo LIKE @SpecialtyNo AND --专业代码
A.SubjectNo LIKE @SubjectNo AND --科目代码
A.SubjectName LIKE @SubjectName AND --课程名称
A.SubjectTypeNo LIKE @SubjectTypeNo AND --课程类型
A.TeacherNo LIKE @TeacherNo AND --教师代码
-- C.Name LIKE @TeacherName AND --教师姓名
(A.IsOpen = @IsOpen1 OR
A.IsOpen = @IsOpen2) AND --是否开课
A.Term LIKE @Term AND --学期
(A.GradeMode = @GradeMode1 OR
A.GradeMode = @GradeMode2)

END
GO
问题:
(各表已经设好主建,如果不设主键会出现错误)
在ClientDataSet端进行添加,修改操作时更新回数据库正常,不会影响到JOIN进来的几个数据字典表
但在执行删除操作时却把JOIN进来的几个表的对应记录全删了!怎么解决?这个问题我已经折腾了一天了!
哪位大虾能帮帮我?谢谢了!
 
应该是你的SQL语句写错了,用查询器分析一下先
 
没错啊,SQL查询错的话我就查不出结果了,更不用说更新回去了
 
不是指查询结果,表的关系定义好后,多表操作就要看SQL语句的了,表之间的各种关系操
作都是靠SQL语句实现,查询分析器可以分析你的SQL语句包括更新、删除等,有不少有用
信息可获取,是非常好用的工具
 
但如果出错,应该是添加修改都不行才对啊,而且我的情况不是删除出错,而是它把我不想删
的表也删了,听说ADO功能正常时就是这样的但我想应该有防止这种情况发生的方法!
 
思考中、、、
 
听人说可以用UPDATEKIND取获更新方式,然后进行删除,但删除的条件如何得来呢?哪位兄台做过?
 
你删除的时候是怎么删的?
 
正是因为“而且我的情况不是删除出错,而是它把我不想删的表也删了”我才猜测是SQL
语句出了逻辑错误,“如果出错,应该是添加修改都不行才对啊”那应该是出了语法错误。
能不能把你的数据库结构和你的意图说一说,让大家分析一下?
BTW:使用存储过程时我一般在数据库端设计,ADO只是简单的调用
 
我的意图很简单:
如有两个表:
表A:
代码 关联表B的代码 字段A
1 B0001 AAA
表B:
代码 名称
B0001 BBB
查询时用存储过程查询得结果:
代码 表B的名称 字段A
1 BBB AAA
然后执行增加,修改,删除操作,
但删除时我不想把B表的记录也删除了!可在操作时它却帮我把B表的字段也删了!
TO forss,
删除操作是由ADO数据集自动产生SQL的!
dspCreditManage.ApplyUpdates(Delta,MaxError,ErrorCount);
Delta参数就是从客户端传来的数据封包,所有的增,删,改都记录在这里!
dspCreditManage是TDataSetProvider控件,用ApplyUpdates提交所有的修改操作!(包括删除)
其SQL是由数据集控件自动产生的!
 
也就是说你根本未写过增、删、改记录的SQL语句,那你就要用Delphi的SQLMonitor检查
一下自动生成的SQL语句了。
我还是以为存储过程还是在数据库端自己写好,ADO只作调用。过多的业务集中在中间层
反而容易在应用程序服务器上造成瓶颈,最好能充分利用现代数据库的强大能力,多层技
术是手段而不是目的,我们的目的是物尽其用,尽量消除系统瓶颈。
 
我的建议也是自己拼装sql,这样可能比较保险。
另外,你如果是在查不出原因,又想用ado的自动提交功能,
我的建议是你可以设置一个删除标志,所有的删除事实上都是
逻辑删除,这样可以起到数据留痕的作用,我们所有的系统都是
这样做的。这样可能数据库文件会越来越大,那可以定期将无效数
据备份后作物理删除。但一般我们不这样做,因为你删除一条记录,那么
跟它关联的所有记录都将失去意义。
也许ado认为既然你要删除你的查询结果,那么就应该删除所有关联的记录吧。
我是这样认为的。
 
OK了,谢谢各位:
adodsCreditManage.Recordset.Properties.Item['Unique Table'].Value := 'TermLesson';
adodsCreditManage是adodataset控件,'TermLesson'是指定要修改的表名!
 
多人接受答案了。
 
好啊,我也同意
 
后退
顶部