一条提高数据库应用程序性能的通用准则就是“80%的应用程序,20%的数据库”。
这意味着就平均情况而言,开发者可以通过调整数据库参数解决软件20%的性能问题,而有80%的问题则需要对应用程序的设计思路和逻辑进行修改。
然而,开发人员面对这样类似问题时,最为直接的冲动就是按照手册上的示例立刻开始编程,将数据库逻辑代码直接放入自己的代码中。这一方法导致了应用程序部署后高昂的维护费用;对数据库逻辑的一点改变或将系统切换到另一种数据库驱动就会需要开发人员花上无数小时来对代码进行修改。而这种做法同样会使得外部源代码调试工程师分析系统性能异常困难。
一种更好的方法就是将数据库服务器看作是真正的服务器――一台能提供整套商业逻辑服务的服务器,而这些商业逻辑服务是完全同代码逻辑相分离的。这种方式将使得对服务的测试和维护在代码外部进行,即无需对代码进行处理。一套应用程序不应该了解是否有一张EMP图表,而只应当明确有某种类型的接口可以为用户访问,从而获取“有多少雇员”的信息和实现“对特定雇员提高薪水”。在32位Windows中,为绝大部分编程语言提供通用接口的主要方式是通过ActiveX或COM服务器。这些DLL或可执行程序能够为多种不同的编程环境提供接口和服务。通常,对ActiveX组件进行编程则是一件让程序员们望而生畏的工作,并且随着数据库接口的改变,这种方式需要开发人员不断对代码进行维护。
对Visual Basic 6.0程序员来说,Oracle Objects for OLE Code Wizard for Visual Basic则可以让这样的工作变得非常简单。通过向导程序,你可以创建一个ActiveX组件将数据库代码包装起来提供给开发人员――这样的方式无需编写太多的Visual Basic代码。
如果你在安装Oracle数据库之前就已经安装了Visual Basic,那么你就可以在Add-Ins菜单选项中找到向导程序。如果你是在之后安装Visual Basic,那么你需要注册Code Wizard DLL以使用此菜单功能。你可以在ORACLE_HOME/bin目录下运行以下命令:
regsvr32.exe oo4ocodewiz.dll
regsvr32.exe odbtreeview.ocx
regsvr32.exe oo4oaddin.dll
在主菜单中选择Add-Ins运行向导,然后就进入了OO4O Code Wizard For Stored Procedures。在第一次运行向导时,程序会要求你登录到一个数据库。一旦登录后,你就可以选择Oracle DB,并从数据库包列表中选择一个数据库包。向导随后将针对这个数据包的功能和处理过程创建OO4O代码。
例如,假设你希望为数据库包创建一个ActiveX DLL服务组件。列表A即显示了如何对数据库包编程以处理相关商业服务。
列表A
REM -- create a package to encapsulate business services for employees
create or replace package empsvc
is
function get_count return integer;
procedure give_raise(empnointeger,amount number);
end empsvc;
/
show errors;
create or replace package body empsvc
is
function get_count return integer
is
l_count integer;
begin
select count(*) into l_count from emp;
end get_count;
--
procedure give_raise(empnointeger,amount number)
is
begin
update emp set sal = sal + amount
where empno = empno;
end give_raise;
end empsvc;
/
show errors;
下一步,进入Visual Basic 6.0并创建一个ActiveX DLL。在创建ActiveX DLL过程中,系统将自动生成ActiveX接口,编译DLL,并将其在Windows操作系统中注册(如果有人希望对我的数据库包进行操作可以简单的从他们喜欢的OLE Browser中进行选择)。
打开项目后,你就可以调用向导程序并登录,向导即会为你的数据库包自动生成Visual Basic代码。代码如列表B所示:
列表B
' local variable(s) to hold property value(s)
Private OraDatabase As OraDatabase 'local copy
Public Property Let database(ByValvData As OraDatabase)
Set OraDatabase = vData
End Property
Public Function GET_COUNT() As Variant
OraDatabase.Parameters.Add "result", 0, ORAPARM_OUTPUT
OraDatabase.Parameters("result").serverType = 2
OraDatabase.ExecuteSQL ("declare result Number; Begin :result :=
EMPSVC.GET_COUNT(); end;")
GET_COUNT = OraDatabase.Parameters("result").Value
OraDatabase.Parameters.Remove "result"
End Function
Public Sub GIVE_RAISE(EMPNO As Variant, AMOUNT As Variant)
OraDatabase.Parameters.Add "EMPNO", EMPNO, ORAPARM_INPUT, 2
OraDatabase.Parameters.Add "AMOUNT", AMOUNT, ORAPARM_INPUT, 2
OraDatabase.ExecuteSQL ("Begin EMPSVC.GIVE_RAISE(:EMPNO, :AMOUNT); end;")
OraDatabase.Parameters.Remove "EMPNO"
OraDatabase.Parameters.Remove "AMOUNT"
End Sub
你可以去掉原始的Class1.cls空文件,对新的EMPSVC.cls设置MultiUse=Yes,然后将项目名设置为你所希望的库类型名称,如EmpSvcLib,然后就可以生成DLL了。如果你启动了一个新的Visual Basic项目,你可以在可见对象列表中看到EmpSvcLib.EMPSVC。如果你对其进行引用(reference),并声明了一个变量,你就可以从变量调用GET_COUNT以及GIVE_RAISE。如果你希望在C++中访问它,你还可以将IDL从Visual Studio所提供的OLE Viewer中提取出来,将其加入的你的项目中,然后通过Visual Studio创建Proxy代码以访问数据库代码。
列表C给出了OLE Viewer所看到的以上IDL代码。
列表C
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: EmpSvcLib.dll
[
uuid(E137CE00-3C0B-497D-976C-C3235FF3C603),
version(1.0),
custom(50867B00-BB69-11D0-A8FF-00A0C9110059, 8169)
]
library EmpSvcLib
{
// TLib : Oracle InProc Server 4.0 Type Library : {F2D4ED20-FFD3-101A-ADF2
-04021C007002}
importlib("oip9.tlb");
// TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface _EMPSVC;
[
odl,
uuid(BEFCB5F1-C9FE-4FCE-B18A-102E51CD8D2A),
version(1.0),
hidden,
dual,
nonextensible,
oleautomation
]
interface _EMPSVC : IDispatch {
[id(0x68030000), propput]
HRESULT database([in] OraDatabase* rhs);
[id(0x60030001)]
HRESULT GET_COUNT([out, retval] VARIANT* );
[id(0x60030002)]
HRESULT GIVE_RAISE(
[in, out] VARIANT* EMPNO,
[in, out] VARIANT* AMOUNT);
};
[
uuid(B1E44C55-EC55-473B-9235-AC7BFA79F30E),
version(1.0)
]
coclass EMPSVC {
[default] interface _EMPSVC;
};
};
如果希望对数据库逻辑进行修改以避免产生不合理请求,诸如请求一个负数薪水值,或是对极大增长的数值设置限制,那么只需要对PL/SQL包进行修改――只要功能和过程签名(procedure signatures)没有改变。如果一旦改变,你也可以重新调用向导程序生成更新版本。
如果你不想使用OO4O,那么可以从USER_ARGUMENTS表格中查询函数和过程定义(procedure definitions),从而生成针对ADO、OLE DB或其他数据库构架的类似Visual Basic代码。这同样是非常简单的方式。