三层数据库开发

作者:lvjack 发表于:http://blog.csdn.net/lvjack

春节期间搜了一堆资料看了看终于了解了一些三层数据库程序的开发方法,对我帮助最大的两份资料是猛禽的一篇关于三层数据库开发讨论的文章还有就是大白鲨的三层服务器部署的介绍。
(见http://dev.csdn.net/article/15/15114.shtm

刚开始看了些资料,知道三层是个什么意思,为什么要用三层,但是对于封装业务逻辑这里不大明白,能找到的例子和介绍几乎都是将中间服务器当成了一个不需要驱动的数据源,所以俺就搞不懂这怎么能算封装业务逻辑呢,不还是在客户端。发现了添加接口的方法后又卡在了中间服务器上定义的函数调用的问题,就是调用远程模块上的数据控件报错的问题,还自作聪明的又加了一个DataModule,看了猛禽的文章才恍然大悟,唉,惭愧惭愧。

总算把三层的思路整理清楚了,大部分的设计也完成了。剩下的就是编码工作了:)而且对于三层我想了一个进一步分离业务逻辑的方法,对于MIS系统,大部分的更改都是一些sql的变化,把这部分也放到数据库去,这个数据库可以是业务数据库也可以是单独的数据库,这样对于程序本身代码的修改就更少了,系统的可维护性和扩展性更好一些。

发现文章比较空洞,补充一些网上搜集到的资料:
(以下内容均收集自网络,没有找到原作者,涉及版权问题请与我联系)

   哥们建议你去Delphi Madis版块翻看所有的资料,偶去年仔细研究过(去年交割得客户软件搞得我不得安宁呢,深深得伤痛!^_^),去年两个月趴在Borland CODE CENTER 上啊!几乎看了我能到得MIDAS书,包括研究速达 ERP 源码得部分模块!
  以下是来自Delphi  版块得论述:
  2000下的配置:
DCOM配置

  如果在Windows NT环境下正常运行应用服务器,必须进行DCOM配置。配置方法如下:

  1.运行NT服务器上的dcomcnfg程序,进行DCOM配置。

  2.进入DCOM的总体默认属性页面,将“在这台计算机上启用分布式COM”打上勾,将默认
身份级别改为“无”。

  3.进入DCOM的总体默认安全机制页面,确认默认访问权限和默认启动权限中的默认值无EveryOne,
如果不去掉EveryOne,应用服务器不能正常启动。

  4.在常规页面中,双击你的应用服务器,打开你的应用服务器DCOM属性设置。

  5.将常规页面中的身份验证级别改为“无”。

  6.位置页面中选上“在这台计算机上运行应用程序”。

  7.将安全性页面设置中,均选择“使用自定义访问权限”,编辑每一个权限,将EveryOne加入用
户列表中。

  8.身份标识页面中,选择“交互式用户”。

  9.NT的GUEST用户不能禁用。
注意:关键所在,在控制面板--用户和密码里administrators用户的属性--隶属于里添加power users,其它用户也这样做,guest用户绝对不可以禁用

xp下配置
xp下和上面的一样,不过不用做上面注意里面的东西,只须在dcom配置里对我的电脑属性里的默认com安全性页里默认访问权限和默认启动权限里都加入everyone就可以了
 
 哥们建议你使用InterBase + IBX,速度是巨爽。好用,好用得很呐!I LOVE IBX FULL
    哥们算是从MIDAS中解脱了,哈哈!
---------------------------------------
我去年的软件部分勘误表
1、问题:“类接口服务失败”
   可能原因:
   (1)用户以不同的身份登陆。
   (2)客户机的应用服务器注册表破坏
2、问题:“RPC服务失败“
   可能原因:
   (1)服务器端dcomcnfg设置没有给用户足够的授权。
   (2)客户机联机超时。重试连接时老口令在内存中驻留。
   (3)如果是XP系统,自由IP分配过时改名
   (4)type library中声明函数,客户端调用时,传递的参数类型不一致。
3、问题:千万别用98,95做客户端,即使你的服务器是2000,XP。
    具体出现何问题,就算补了DCOM,你也是”大有收获“。
4、尽量采用socket,DCOM不好搞,如果是Socket引起了安全问题,不要把后端数据库和
应用服务器放在同一台机器。
5、关闭你的防火墙!实在不行,用诺顿配置。
 乌拉,乌拉运行,咔嚓又停,呜呜.....
---------------------------------------
不要用SQL语句增加Blob字段,应该动态创建一个Blob字段,然后进行流操作,最后保存ClientDataSet!
---------------------------------------
Q
服务器端file->new->multiter->remote data module 在datamodule1上放入ADOConnection1,ADOQuery1,DataSetProvider1
DataSetProvider1里设置过Options->poallowcommandtext=true

客户端file->new->data module 在datamodule1上放入DCOMConnection1,ClientDataSet1,Button1
       Button1 点击代码如下: 
          DataModule2->DCOMConnection1->Connected=true;
          DataModule2->ClientDataSetLogin1->Active=false;
          DataModule2->ClientDataSetLogin1->CommandText="select * from employee";

          DataModule2->ClientDataSetLogin1->Active=true;
客户端出现错误信息missing Connection or Connectstring
怎么解决?
A
要先设置ServerName 或 ServerGUID, 如果应用服务器和瘦客户端不在同一台机器上, 还要设置ComputerName
---------------------------------------

DataSnap(MIDAS)三层架构程序中,远程方法调用方式

远程调用方式

一、服务器端接口方法:Remote Data Module 为 rdmAAA

/*执行一个select count(*) from ...*/

STDMETHODIMP TrdmAAAImpl::F_ExecSQL(BSTR asSQL, int* aiCount)

{
       //asSQL是一个in参数,aiCount是一个out参数
    int liCount=0;
    AnsiString lsSQL = AnsiString((WideString)asSQL);
    try
    {
        m_DataModule->qryA2->Close();
        m_DataModule->qryA2->SQL->Clear();
        m_DataModule->qryA2->SQL->Add(lsSQL);
        m_DataModule->qryA2->Prepared = true;
        m_DataModule->qryA2->Open();
        liCount = m_DataModule->qryA2->Fields->Fields[0]->AsInteger;
        m_DataModule->qryA2->Close();
        *aiCount = liCount; //必须把给out参数赋值放在执行的最后
    }
    catch(Exception &E)
    {
        return Error(E.Message.c_str(),IID_IrdmAAA);
    }
    return S_OK;
}
二、客户端调用方式:
注:客户端Project中已加入_TLB.cpp文件,且要调用接口方法的Unit已包含 _TLB.h。客户端连接组件 cntAAA。

方式1、
WideString lsSQL = "select count(*) from Customers";
int liCount;
cntAAA->AppServer.OleFunction("F_ExecSQL ",lsSQL,&liCount);
Label2->Caption = liCount;
注:这种方式对DCOM、Socket都不行
//
方式2、lvjack:AppServer改为GetServer()测试通过
WideString lsSQL = "select count(*) from Customers";
int liCount;
IrdmAAADisp aaa(LPDISPATCH(cntAAA->AppServer));
aaa.F_ExecSQL(lsSQL,&liCount);
Label2->Caption = liCount;
注:这种方式对DCOM可行(但有点问题),对Socket不行

方式3、测试通过
头文件里:类的public变量
    IrdmAAADisp   aaa;
cpp文件里:
    WideString lsSQL = "select count(*) from Customers";
int liCount;
    aaa = (IDispatch*)cntAAA->GetServer();
    aaa->F_ExecSQL(lsSQL,&liCount);
Label2->Caption = liCount;
注:这种方式对DCOM可行,对Socket不行


方式4、lvjack:AppServer改为GetServer()测试通过
       WideString lsSQL = "select count(*) from Customers";
int liCount;
       IrdmAAADisp aaa((IDispatch *)(cntAAA ->AppServer));
       aaa.F_ExecSQL(lsSQL,&liCount);
Label2->Caption = liCount;
注:这种方式对DCOM可行,对Socket不行
//
方式5、lvjack 此法测试通过
WideString lsSQL = "select count(*) from Customers";
int liCount;
IrdmAAADisp aaa;
try
{
       aaa.Bind(cntAAA ->GetServer());
              aaa->F_ExecSQL(lsSQL,&liCount);
Label2->Caption = liCount;
}
__finally
{
       if(aaa.IsBound()) aaa.Unbind();
}
       注:这种方式对DCOM可行,对Socket不行

方式6、
WideString lsSQL = "select count(*) from Customers";
int liCount;
IDispatch* disp = (IDispatch *)cntAAA->AppServer;
IrdmAAADisp aaa((IrdmAAA *)disp);
aaa.F_ExecSQL(lsSQL,&liCount);
Label2->Caption = liCount;
注:(1)这种方式对DCOM、Socket都行

       (2)注意:如果把cntAAA->AppServer 改为cntAAA->GetServer() 会出错“Access Violation”;如果把aaa. F_ExecSQL(lsSQL,&liCount)改为aaa.->F_ExecSQL(lsSQL,&liCount),也会出错”Access Violation”。

/

方式7、
WideString lsSQL = "select count(*) from Customers";
    int liCount;
    cntAAA->AppServer.Exec(Procedure("F_ExecSQL")<<lsSQL<<&liCount);
Label2->Caption = liCount;
注:这种方式对DCOM、Socket都行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值