用Delphi写MIS类程序(七)

 

2.2 连接数据库

       终于到这个标题了,一个MIS系统不可能没有数据库的支持,如果没有了就变成“没本之木,无源之水”。在这个教程中,我选用的数据库是MS SQL Server系列,你可以使用SQL Server 2000或者20052005有一个免费的Express版本,你当然也可以使用它。这个教程并不打算教大家如何使用SQL Server(我也没有这本事,大家可以有空多上CSDN看看邹健大侠的文章),所以怎么安装,设置和建表之类的事情我就不多说了。我在这里为我们的MIS系统准备了一个简单的操作员表,如下图所示:

       当然在实际的应用中这么简单的表结构是不行的,但在这一章里面我们只需要这么多字段就可以说明问题。在这里,OperatorID表示的是操作员号,PSW表示的是该操作员的密码,为了简单,这里使用了明文密码。另外一个问题需要说明,大家最好不要使用password作为字段名,因为有些数据库认为password是一个关键字(例如FireBirdInterbase),不能用来作字段名,因此为了你程序的可移植性,不要使用这种敏感的词。当然如果只是在MSSQL上使用的话,那也可以使用。

       除了建立好对应的表以外,为了能成功使用数据库,我们还需要了解数据库服务器所在的位置等,例如我们这次使用的是建立在本机上的数据库,所以我可以通过127.0.0.1(local)来访问服务器,对应的数据库名是mditut,同时我的SQL Server数据库用户和密码分别是sa/sa

       建立并了解数据库后,我们就可以在我们的MIS程序中使用数据库了。我们选用的数据库控件是Delphi里最通用(不是最好用的)的ADO组件,如下图所示:

 

       在这个组的控件里面,ADOConnection是数据库连接的控件,其它的ADODataSetADOTable等等都是用于返回结果集的控件的,我们会在下面再说明。在这里需要特别说明的是,因为除了ADOConnection能通过一定的配置能连接上数据库外,其它所有的ADO控件都能单独通过配置连接串来连接上数据库,因为它们内部都包含了一个ADOConnection控件。但我认为一个MIS的应用应该由此至终只使用一个数据库的连接(当然如果你的MIS应用需要同时连接两个不同的数据库的话,那么也确实存在多个连接,就像我写的FlexQue一样),这是因为在客户端每增加一个连接,数据库服务器那边都会相应增加一定的资源来为维持这一连接的。所以连接数越多,数据库服务器的资源就耗用得越多。基于上面的理由,所以我们的程序中只使用一个ADOConneciton,其它要的ADO控件都通过这个ADOConnection来获取数据库的连接。

       那么这个ADOConneciton应该放在什么地方比较合适呢?我们现在来看程序:

MDI_Tutorial.dpr

……

begin

  Application.Initialize;

 

  frmLogin := TfrmLogin.Create(Application);

  frmLogin.ShowModal;

  if frmLogin.RetValue then

    begin

      Application.CreateForm(TfrmMain, frmMain);

    end;

  frmLogin.free;

 

  Application.Run;

 

  GFormClassMgr.Free;

end.

       从这里,我们可以看出来,frmLogin是我们的登录窗体,在这个窗体中就需要查找数据库中的tb_operator表的,所以我们的数据库接连接应该放在frmLogin中或者放在frmLogin之前进行初始化。现在我们先来分析第一种的情况,把ADOConneciton放在frmLogin中,这样好办,我们可以在frmLogin中放上一个ADOConnection控件。双击这个控件会弹出一个对话框,如下图所示

 

选择下面的use connection string,然后选择build的,接着会弹出另外的对话框

 

选择Microsoft OLE DB Provider for SQL Server,然后按下一步,

 

然后在弹出的对话框中按要求填定好对应的值,最好点击确定。这个对话框会关闭,同时刚才的对话框中会自动填上组装好的连接串:

 

这个连接串十分有用,我们把它复制下来放到记事本上,我们接下来在别的地方也会用到它的。

接下来的工作就好办了,我们改造一下frmLogin中的代码:

procedure TfrmLogin.btnOKClick(Sender: TObject);

var

  qry : TADOQuery;

  k : integer;

begin

  qry := TADOQuery.Create(nil); //mark A

  qry.Connection := ADOConnection1;

  qry.SQL.Add('select count(*) from tb_operator where operatorid =:opid and psw =:psw');

  qry.Parameters.ParamByName('opid').Value := edtOperatorID.text; //mark B

  qry.Parameters.ParamByName('psw').Value := edtPassword.Text;

  qry.Open;

  k := qry.Fields[0].AsInteger;

  qry.Close;

  qry.Free;

  if k = 1 then

    begin

      FRetValue := true;

      Close;

    end

  else

    begin

      MessageBox(Handle, '错误的用户名或密码!', 'MDI_Tutorial', MB_ICONWARNING or MB_OK);

      edtOperatorID.SetFocus;

    end;

end;

       在上面的代码中,我们使用了一个ADOQuery进行查询数据库,在Delphi的组件面板中我们可以通过拖放在形式来使用ADOQuery,但其实有时候使用代码来完成可能更方便,就像上面Mark A中的代码就可以了。因为我们要把用户输入的操作员号和密码与数据库中tb_operator表的数据进行比较,所以,我们不可避免得要使用sql where子句,很多初用Delphi的朋友都会使用‘拼语句’的方式来完成where子句中的条件编写,其实在delphiADO中支持使用“参数”的方式,就像Mark B中的写法一样,通过使用参数的方式,使得整个语句写起来更加的清爽!

       经过这样的改造,我们来运行一下程序,如果你没拼写错误的话,那么程序应该能正常的运行起来。并且能正确判断用户所输入的操作员号跟密码是否正确。

       所有的东西到目前来看都十分美好,但事实真是这样吗?

2.3 把数据库连接独立出来

我们把frmLogin的代码完成了,同时在frmLogin的数据库连接也完成了,当然这个连接按我们上面的设想,应该是供应给往后的窗体所使用的,要不然这个连接又重新建立一次的话,服务器的资源会相应的增加不少的。那么现在我们来看frmLogin所建立的数据库连接怎样在其它窗体中使用,首先我们来看MDI_Tutorial.dpr中的代码

……

begin

  Application.Initialize;

 

  frmLogin := TfrmLogin.Create(Application); //mark A

  frmLogin.ShowModal;

  if frmLogin.RetValue then

    begin

      Application.CreateForm(TfrmMain, frmMain); //mark B

    end;

  frmLogin.free; //mark C

 

  Application.Run;

 

  GFormClassMgr.Free;

end.

       我们可以知道能过mark A标识的语句,我们的frmLogin建立起来了,同时作为frmLogin中的成员变量的ADOConneciton1也会同时被建立起来的,当程序完成mark B的语句后,我们应该把这个ADOConnection1的值赋予给frmMain中,以便frmMain中能连接上数据库,但当程序来到mark C时,因为要释放掉 frmLogin,所以frmLogin中的ADOConnection1也会被释放掉的,所以当程序进行Windows的消息循环之前,数据库连接就被破坏掉了,frmMain如果调用的话,那么只会产生错误的信息。

       由于这个错误的信息是因为frmLogin被析构引起的,那么我们先不急于把frmLogin析构就可以了,把frmLogin.free放在Application.Run之后就不会产生这样的问题了。但为了保持数据库连接而不释放整个的登录窗体,这样值得吗?

       为了使得整个程序的条理能更清晰,我们引入另一个全局的变量GBaseConf,这个变量存放于BaseConfUnit.pas中,代码如下:

{

MDI Tutorial v2.3

 Written by flexitime.

}

unit BaseConfUnit;

 

interface

uses

  DB, ADODB;

type

  TBaseConf = class (TObject)

  private

    FMainConnection : TADOConnection;

  public

    constructor Create;

    destructor Destroy; override;

    property MainConnection : TADOConnection read FMainConnection;

    procedure BuildConnection;

  end;

 

var

  GBaseConf : TBaseConf;

 

implementation

{ TBaseConf }

 

procedure TBaseConf.BuildConnection;

begin

  FMainConnection.ConnectionString := 'Provider=SQLOLEDB.1;Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=mditut;Data Source=(local)';  //mark A

  FMainConnection.Open;

end;

 

constructor TBaseConf.Create;

begin

  FMainConnection := TADOConnection.Create(nil);

  FMainConnection.LoginPrompt := false;  // mark B

  BuildConnection;

end;

 

destructor TBaseConf.Destroy;

begin

  if FMainConnection <> nil then

    begin

      if FMainConnection.Connected then FMainConnection.Close;

      FMainConnection.Free;

    end;

  inherited;

end;

end.

 

       这个单元的代码其实也比较简单,在MarkA中,就是我刚才说让大家保留到记事本的那个连接串代码了。Mark B的作用是禁止 ADOConnection弹出数据库登录窗口。整个BaseConf的作用其实就是初始化一个数据库连接,并保持它。当然,目前BaseConf中只有这么一点的内容。为了保持一个数据库连接而引入一个全局变量确实有小题大做之嫌,但随着我们程序编写的深入,我们会发现整个MIS中其实还会有很多基本的变量需要一直保存下来的,我们就把这些变量全部都放到BaseConf中来统一管理,这样整个程序就会变得有条理了,而且减少内存泄露的风险。

       接着我们来修改MDI_Tutorial.dpr中的内容:

……

  Application.Initialize;

  GBaseConf := TBaseConf.Create;

 

  frmLogin := TfrmLogin.Create(Application);

  frmLogin.ShowModal;

  if frmLogin.RetValue then

    begin

      Application.CreateForm(TfrmMain, frmMain);

  end;

  frmLogin.free;

 

  Application.Run;

 

  GFormClassMgr.Free;

  GBaseConf.Free;

……

在这个单元中,我们添加了GBaseConf的初始化以及析构的语句。

       接着再来修改frmLogin中的内容,我们首先把刚才放到窗体上的ADOConnection1控件删除掉。然后再来修改以下的代码:

……

implementation

uses

  BaseConfUnit;

……

procedure TfrmLogin.btnOKClick(Sender: TObject);

var

  qry : TADOQuery;

  k : integer;

begin

  qry := TADOQuery.Create(nil);

  qry.Connection := GBaseConf.MainConnection;

  qry.SQL.Add('select count(*) from tb_operator where operatorid =:opid and psw =:psw');

……

       我们引用了BaseConfUnit单元,并把连接串的位置换掉了。

       把上面的代码修改都完成后,现在就让我们来测试一下程序,如果没有其它拼写问题的话,那么程序应该能正常运行起来的。

       经过上面的改造后,其它的窗体,如frmMain需要连接数据库的话,那么它只须像frmLogin一样,引用BaseConfUnit单元,并调用GBaseConf.MainConnection就可以了。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值