我使用TADOQuery
组件时遇到了一个奇怪的问题。
我目前在他们使用在Windows XP VM上运行的Borland C ++ Builder应用程序的地方工作。因此,我们希望迁移到Windows 7并将其作为终端服务,以便员工可以使用Windows 10接收新计算机,而无需再次在每台计算机上创建Win XP VM。
目前,该应用程序使用BDE组件,它在XP上运行良好。我们创建了一个用于测试的Win7 64位VM,并安装了必要的驱动程序等,但是BDE不起作用。当我尝试登录Borland附带的SQL Explorer时,它只是挂起。它发送请求但从未得到响应。我花了一个多星期的时间试图调试这个问题,但没有随处可见。
无论如何,我放弃了BDE并想尝试改为ADO。所以我开始只需创建一个TDBGrid
并使用ADO组件填充数据。它在XP和Win7上都很棒!所以现在我正在尝试将应用程序的BDE组件(TDataBase
,TQuery
等)转换为ADO组件。
我在尝试使用参数时遇到了一个有趣的问题。这是一个查询示例:
SELECT t1.SEC_CODE, t1.CODE, t1.CTRL_NUM, t1.CHECK_CODE,
t1.CHECK_NO, t1.CLIENT_ID, t1.AMOUNT, t1.TRANS_NO, decode(t2.prefix,null,t2.name,t2.name||', '||t2.prefix) as fullName,
t1.ENTRY_DATE, t1.DEPOSIT_DATE, t1.ACCT_COMMENT, t2.NAME, t2.PREFIX
FROM ACCOUNTING.ACCT_CHECK_IN t1, OISC.CLIENT t2
WHERE
(:BEN =1 OR (:BEN =0 AND t1.ENTRY_DATE=:DATE)
OR (:BEN =2 AND t1.DEPOSIT_DATE IS NOT NULL)
OR (:BEN =3 AND t1.DEPOSIT_DATE IS NULL)) AND
(:ALEX =1 OR (:ALEX =0 AND t1.ENTRY_DATE>=:DATE1 AND
t1.ENTRY_DATE<=:DATE2) OR (:ALEX =2 AND t1.DEPOSIT_DATE>=:DATE1
AND t1.DEPOSIT_DATE<=:DATE2))
AND T2.CLIENT_ID(+)=T1.CLIENT_ID
ORDER BY t1.SEC_CODE, t1.CHECK_CODE, fullName, t1.check_no
请不要注意参数名称,这对我来说有点好笑,但是你们不能连接。
这里的第一个问题是即使某些参数名称相同,ADO也会将它们视为单独的参数!所以,如果我这样做:
checkload1->Parameters->ParamByName("BEN")->Value=0
ADO不会将每次出现的“BEN”替换为0,我最终会得到0条记录的结果集!相反,我正在使用它:
checkload1->Parameters->Items[0]->Value = 0; // BEN param
checkload1->Parameters->Items[1]->Value = 0;
checkload1->Parameters->Items[3]->Value = 0;
checkload1->Parameters->Items[4]->Value = 0;
基本上,根据参数索引将每个“BEN”参数替换为0。
这给我带来了结果,但不是马上。
以下是它的工作原理:应用程序是基于树的用户界面。有一个节点显示“今天的支票”,它会在展开时显示今天的支票。太棒了,现在这对BDE很有用了,我只分配一次参数值,它会自动替换它看到“BEN”等的地方。
当使用ADO组件时,我展开“今天的检查”节点并运行代码,加载参数,激活查询组件,我没有得到任何结果!因此节点保持折叠状态。如果我再次单击+
符号以展开树,则会加载检查!并且它会在每次加载后加载它们。
因此,在应用程序中有一个日期选项,默认为今天的日期。如果我把它改为昨天的日期,我仍然可以得到今天的支票......就像参数没有得到更新一样。如果我在一开始就尝试以不同的日期开始,我就不会得到任何结果!它将在今天的日期带来结果,但在此之后它将不会接受不同的日期。
我调试了代码,日期也在变化,但由于某种原因,参数没有变化。这是我的代码块:
checkload1->Filter="" ;
checkload1->Filtered=false ;
switch(params)
{
case 0: checkload1->Parameters->Items[0]->Value = 1; // BEN param
checkload1->Parameters->Items[1]->Value = 1;
checkload1->Parameters->Items[3]->Value = 1;
checkload1->Parameters->Items[4]->Value = 1;
// ALEX Param
checkload1->Parameters->Items[5]->Value = 0;
checkload1->Parameters->Items[6]->Value = 0;
checkload1->Parameters->Items[9]->Value = 0;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS NOT IN ('Refunded', 'Posted') ";
break ;
case 1: checkload1->Parameters->Items[0]->Value = 0; // BEN param
checkload1->Parameters->Items[1]->Value = 0;
checkload1->Parameters->Items[3]->Value = 0;
checkload1->Parameters->Items[4]->Value = 0;
checkload1->Parameters->ParamByName("DATE")->Value=FormatDateTime("dd-mmm-yyyy", Date()) ;
checkload1->SQL->Strings[13] = " ";
break ;
case 2: checkload1->Parameters->Items[0]->Value = 2; // BEN param
checkload1->Parameters->Items[1]->Value = 2;
checkload1->Parameters->Items[3]->Value = 2;
checkload1->Parameters->Items[4]->Value = 2;
//ALEX param
checkload1->Parameters->Items[5]->Value = 2;
checkload1->Parameters->Items[6]->Value = 2;
checkload1->Parameters->Items[9]->Value = 2;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS IN ('Deposited') ";
break ;
case 3: checkload1->Parameters->Items[0]->Value = 3; // BEN param
checkload1->Parameters->Items[1]->Value = 3;
checkload1->Parameters->Items[3]->Value = 3;
checkload1->Parameters->Items[4]->Value = 3;
//ALEX param
checkload1->Parameters->Items[5]->Value = 0;
checkload1->Parameters->Items[6]->Value = 0;
checkload1->Parameters->Items[9]->Value = 0;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS IN ('Held') ";
break ;
}
if(!mainform->date1->Checked){
checkload1->Parameters->Items[5]->Value = 1;
checkload1->Parameters->Items[6]->Value = 1;
checkload1->Parameters->Items[9]->Value = 1;
}
checkload1->Parameters->Items[7]->Value = FormatDateTime("dd-mmm-yyyy", fromdate);
checkload1->Parameters->Items[10]->Value = FormatDateTime("dd-mmm-yyyy", fromdate);
checkload1->Parameters->Items[8]->Value = FormatDateTime("dd-mmm-yyyy", todate);
checkload1->Parameters->Items[11]->Value = FormatDateTime("dd-mmm-yyyy", todate);
if(filters != "") checkload1->SQL->Strings[12] = filters;
else checkload1->SQL->Strings[12]=" " ;
checkload1->Prepared = true;
checkload1->Active=true ;
有经验的人可以就此提出建议吗?
我知道这是古老的东西,但这些程序是在15 - 20年前写的,他们正在转向基于网络的用户界面,但这仍在构建中。在此之前,我需要将所需的更改/更新作为我工作的一部分。
答案 0 :(得分:1)
好的,我有这个工作!!
对于那些正在努力使用BDE来处理Windows 7 64位的人来说,这是一个解决方案!请记住,我正在处理的数据库是使用C ++ Builder 6构建的Oracle 8i和Borland C ++应用程序。
按照照片和箭头。我试图把每张照片都有自己的评论,但是这个网站说我不能发布超过2个链接......为了地狱,所以我把所有的照片放在一张照片上。
例如,这个TQuery正在寻找bnetdata作为数据库。很好,在下一张图片中我们添加了一个ADOConnection组件
单击突出显示的连接字符串。
选择使用连接字符串并单击构建。
选择突出显示的提供者,然后单击“下一步”。
检查使用数据源名称,然后单击箭头以选择一个。请注意,稍后您将输入用户名和密码,并选中允许保存密码。
选择BDE组件使用的相同数据源。请注意,这是ODBC管理器中系统DSN下的源之一。如果它不在那里,那就创建一个。
以下是ODBC管理员的一个镜头。请注意,这仍然是XP环境。您需要在Windows 7计算机中创建相同的数据源(在我的情况下为bnetdata)。
现在点击高级并检查列表中的readwrite选项。
在ADOConnection组件上单击“确定”后,正如您在对象检查器中看到的那样。查看突出显示的区域。现在,我们需要将connected属性设置为true。当您这样做时,它会要求您登录数据库。输入用户名和密码,然后单击“确定”。连接属性现在将变为true。之后,您需要将LoginPrompt属性设置为false。现在单击项目上的保存。
所以假设您也有BDE数据库组件,单击它然后清除别名和驱动程序名称,然后将您的数据库名称放在databaseName属性下(在我的例子中是bnetdata)。
保存项目并在XP中编译。复制应用程序并将其粘贴到Windows 7计算机中并双击它,它将工作!我已成功将所有应用程序转换为在Windows 7上运行。最难的部分是安装Borland并让Windows 7在ODBC管理器的“驱动程序”选项卡下识别Oracle ODBC驱动程序。
同样,Borland安装附带的SQL Explorer无法运行。因此,我仍然需要在我的Windows XP VM中进行开发,但用户可以使用Windows 7 VM中的应用程序作为Windows服务器上的终端...为我工作!!
希望这有助于某人!
编辑:
我还在ADOConnection中尝试过Microsoft OLE DB Provider for Oracle,它也有效。没有看到对速度或性能产生可测量的影响。两者似乎都以同样的方式表现。我很惊讶添加ADOConnection组件允许应用程序连接到数据库并像在XP中一样工作!
也只是为了清理,您不需要更改应用程序中的BDE组件。只需添加ADOConnection和所有其他组件保持不变(BDE组件)。我试图转换为使用ADO组件,但不再需要了。