加深昨天的話題,把一些模糊的概念統一一下 日期:2004-05-19。

加深昨天的話題,把一些模糊的概念統一一下 日期:2004-05-19。
 
<Code 1>
unit dmOrderTimeModule;

interface

uses
  SysUtils, Variants, Classes, dmBaseModuleImp, hmStrTools, hmSqlTools, hmDateTools, hmTimeTools;

type
  TdmOrderTime = class(TBaseDataModule)
  private
    { Private declarations }
  protected
    function ActionList(CmdIndex: integer; var Data, Msg: OleVariant): WordBool; override;
    function Action1(var Data, Msg: OleVariant): WordBool;
    function Action2(var Data, Msg: OleVariant): WordBool;
    function Action3(var Data, Msg: OleVariant): WordBool;
    function Action4(var Data, Msg: OleVariant): WordBool;
  end;

  TdmOrderTimeInfo = class(TBaseDataModuleInfo)
  public
    function GetModuleName: WideString; override; stdcall;
    function GetVersion: Widestring; override; stdcall;
    function GetMemo: Widestring; override; stdcall;
    function GetLastUpdate: WideString; override; stdcall;
    function GetModuleIndex: Integer; override; stdcall;
  end;

implementation

uses swModuleIndex;

{ TdmOrderTime }

function TdmOrderTime.ActionList(CmdIndex: integer; var Data, Msg: OleVariant): WordBool;
begin
  case CmdIndex of
    1: Result := Action1(Data, Msg);
    2: Result := Action2(Data, Msg);
    3: Result := Action3(Data, Msg);
    4: Result := Action4(Data, Msg);
  else
    Result := inherited ActionList(CmdIndex, Data, Msg);
  end;
end;

function TdmOrderTime.Action1(var Data, Msg: OleVariant): WordBool;
var
  s: TStringList;
  cnt: integer;
  Option: integer;
begin
  Self.CheckTranstion;
  s := TStringList.Create;
  try
    Service.BeginTrans;
    try
      Option := Ole['Option'];
      if Option = 1 then (* 動作1:加入排班*)
        begin
          Sql.LoadFromStore(2);
          //sql.InLines.Assign(SqlStore.SqlGroup[2].Sql);
          if Ole['chkWorkTime'] = True then
            sql.Params.ParamValue['@mm_WorkKey'] := Ole['edtWorkTime']
          else
            sql.Params.ParamValue['@mm_WorkKey'] := '@F ot.tw_WorkKey';
          sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
          sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
          sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
          Service.Execute(Sql.SqlLanguage);
          Sql.LoadFromStore(3);
          //sql.InLines.Assign(SqlStore.SqlGroup[3].Sql);
          Service.Execute(Sql.SqlLanguage);
          cnt := Service.RecordsAffected;
          Service.DropTable('#ordertimetmp');
          Service.CommitTrans;
          if cnt > 0 then
            Msg := format('排班成功,本次共有%d條記錄加入.', [cnt])
          else
            Msg := '可能已經排過班,本次排班沒有加入任何記錄.';
        end;
      if Option in [2, 3] then
        begin
          Sql.LoadFromStore(4);
          //sql.InLines.Assign(SqlStore.SqlGroup[4].Sql);
          sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
          Service.Execute(Sql.SqlLanguage);
          if Option = 2 then (* 動作2:取消排班,但不刪除*)
            Sql.LoadFromStore(5)
              //sql.InLines.Assign(SqlStore.SqlGroup[5].Sql)
          else (*動作3:刪除排班 *)
            Sql.LoadFromStore(6);
          //sql.InLines.Assign(SqlStore.SqlGroup[6].Sql);

          sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
          sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
          Service.Execute(Sql.SqlLanguage);
          cnt := Service.RecordsAffected;
          Service.DropTable('#Psn');
          Service.CommitTrans;
          if Option = 2 then
            begin
              if cnt > 0 then
                Msg := format('更新排班成功,本次共有%d條記錄被更新.', [cnt])
              else
                Msg := '可能未滿足條件,本次操作沒有更新任何記錄.';
            end
          else
            begin
              if cnt > 0 then
                Msg := format('刪除排班成功,本次共有%d條記錄被刪除.', [cnt])
              else
                Msg := '可能未滿足條件,本次操作沒有刪除任何記錄.';
            end;
        end;
      if Option = 4 then (* 動作4:為員工指定班次*)
        begin
          Sql.LoadFromStore(8);
          Service.Execute(Sql.SqlLanguage);
          Sql.LoadFromStore(9);
          Service.Execute(Sql.SqlLanguage);
          cnt := Service.RecordsAffected;
          Service.DropTable('#Psn');
          Service.CommitTrans;
          if cnt > 0 then
            Msg := format('指定班次成功,本次共有%d條記錄加入.', [cnt])
          else
            Msg := '可能未滿足條件,本次操作沒有任何記錄.';
        end;
      if Option = 5 then (* 動作4:刪除入職之前的排班和數據*)
        begin
          Sql.LoadFromStore(10);
          //sql.InLines.Assign(SqlStore.SqlGroup[10].Sql);
          sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
          Service.Execute(Sql.SqlLanguage);
          s.Add('以下是被刪除的排班記錄清單:');

          Sql.LoadFromStore(11);
          //Sql.InLines.Assign(SqlStore.SqlGroup[11].Sql);
          Sql.Params.ParamValue['@mm_Table'] := '@F tmcDays1';
          Service.Execute(Sql.SqlLanguage);
          s.Add(format('打卡記錄 - %d', [Service.RecordsAffected]));

          //Sql.LoadFromStore(11);
          //Sql.InLines.Assign(SqlStore.SqlGroup[11].Sql);
          Sql.Params.ParamValue['@mm_Table'] := '@F tmcDays2';
          Service.Execute(Sql.SqlLanguage);
          s.Add(format('簽卡記錄 - %d', [Service.RecordsAffected]));

          //Sql.InLines.Assign(SqlStore.SqlGroup[11].Sql);
          Sql.Params.ParamValue['@mm_Table'] := '@F tmcDays3';
          Service.Execute(Sql.SqlLanguage);
          s.Add(format('請假記錄 - %d', [Service.RecordsAffected]));

          //Sql.InLines.Assign(SqlStore.SqlGroup[11].Sql);
          Sql.Params.ParamValue['@mm_Table'] := '@F tmcDays4';
          Service.Execute(Sql.SqlLanguage);

          //Sql.InLines.Assign(SqlStore.SqlGroup[11].Sql);
          Sql.Params.ParamValue['@mm_Table'] := '@F tmcDays4List';
          Service.Execute(Sql.SqlLanguage);
          s.Add(format('額加記錄 - %d', [Service.RecordsAffected]));

          Service.DropTable('#Psn');
          Service.CommitTrans;
          Msg := s.Text;
        end;
      if Option = 6 then (* 動作4:按策略排班*)
        begin
          Sql.LoadFromStore(4);
          //sql.InLines.Assign(SqlStore.SqlGroup[4].Sql);
          sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
          Service.Execute(Sql.SqlLanguage);
          Sql.LoadFromStore(12);
          //sql.InLines.Assign(SqlStore.SqlGroup[12].Sql);
          sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
          sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
          Service.Execute(Sql.SqlLanguage);
          Sql.LoadFromStore(13);
          //sql.InLines.Assign(SqlStore.SqlGroup[13].Sql);
          sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
          sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
          sql.Params.ParamValue['@mm_Policy'] := Ole['Policy'];
          Service.Execute(Sql.SqlLanguage);
          cnt := Service.RecordsAffected;
          Service.DropTable('#Psn');
          Service.CommitTrans;
          if cnt > 0 then
            Msg := format('按策略排班,本次共有%d條記錄加入.', [cnt])
          else
            Msg := '可能未滿足條件,本次操作沒有任何記錄.';
        end;
      Service.ReceiveDataWithNoData;
      Result := True;
    except
      on E: Exception do
        begin
          Msg := '排班操作出現錯誤:' + E.Message;
          Service.RollbackTrans;
          Service.ReceiveDataWithNoData;
          Result := False;
        end;
    end;
  finally
    s.Free;
  end;
end;

function TdmOrderTime.Action2(var Data, Msg: OleVariant): WordBool;
const
  tm_time: array[1..6] of string = ('begin1', 'end1', 'begin2', 'end2', 'begin3', 'end3');
var
  cmdstr: string;
  i: integer;
  cnt: integer;
begin
  Self.CheckTranstion;
  try
    Service.BeginTrans;
    Sql.LoadFromStore(14);
    //Sql.InLines.Assign(SqlStore.SqlGroup[14].Sql);
    sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
    Service.Execute(Sql.SqlLanguage);
    Sql.LoadFromStore(15);
    //sql.InLines.Assign(SqlStore.SqlGroup[15].Sql);
    sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
    sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
    Service.Execute(Sql.SqlLanguage);
    Sql.LoadFromStore(16);
    //sql.InLines.Assign(SqlStore.SqlGroup[16].Sql);
    sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
    sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
    Service.Execute(Sql.SqlLanguage);
    Cmdstr := '';
    for i := 1 to 5 do
      begin
        Sql.LoadFromStore(17);
        //Sql.InLines.Assign(SqlStore.SqlGroup[17].Sql);
        Sql.Params.ParamValue['@mm_Action1'] := '@F td_' + tm_time[i];
        Sql.Params.ParamValue['@mm_Action2'] := '@F tm_' + tm_time[i];
        if i mod 2 = 1 then
          begin
            Sql.Params.ParamValue['@mm_BDelay'] := '@F tm_BDelay';
            Sql.Params.ParamValue['@mm_EDelay'] := '@F 25';
          end
        else
          begin
            sql.Params.ParamValue['@mm_BDelay'] := '@F 25';
            Sql.Params.ParamValue['@mm_EDelay'] := '@F tm_EDelay';
          end;
        CmdStr := CmdStr + Sql.OutLines.Text;
      end;
    Sql.LoadFromStore(18);
    //Sql.InLines.Assign(SqlStore.SqlGroup[18].Sql);
    CmdStr := CmdStr + Sql.OutLines.Text;
    Sql.LoadFromStore(19);
    //Sql.InLines.Assign(SqlStore.SqlGroup[19].Sql);
    Sql.Params.ParamValue['@mm_Fields'] := '@F ' + CmdStr;
    sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
    sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
    Service.Execute(Sql.SqlLanguage);
    cnt := Service.RecordsAffected;

    Service.DropTable('#Psn');
    Service.DropTable('#TS1');
    Service.DropTable('#Card');

    Service.CommitTrans;
    if cnt > 0 then
      Msg := format('分析考勤數據成功,共分析了%d條記錄.', [cnt])
    else
      Msg := '可能未滿足條件,本次操作沒有任何記錄.';
    Service.ReceiveDataWithNoData;
    Result := True;
  except
    on E: Exception do
      begin
        Msg := E.Message;
        Result := False;
        Service.ReceiveDataWithNoData;
        Service.RollbackTrans;
      end;
  end;
end;

(* 本函數的作用是取得沒有排班的員工數據 *)

function TdmOrderTime.Action3(var Data, Msg: OleVariant): WordBool;
var
  s: TStringList;
  i: integer;
begin
  s := TStringList.Create;
  try
    Sql.LoadFromStore(7);
    Service.Query.LoadSqlAndOpen(Sql.SqlLanguage);
    if Service.Query.NotEmpty and (Service.Query.RecordCount > 0) then
      begin
        s.Add('以下是沒有排班的員工名單:');
        for i := 1 to Service.Query.RecordCount do
          begin
            s.Add(Service.Query.SV['td_Number'] + ' - ' +
              Service.Query.SV['td_Name'] + ' - ' +
              Service.Query.SV['td_Card']);
            Service.Query.Next;
          end;
        Service.Query.First;
        s.Add(format('共找到%d條記錄', [Service.Query.RecordCount]));
        Service.ReceiveDataWithNoData;
        Msg := s.Text;
      end
    else
      begin
        Service.ReceiveDataWithNoData;
        Msg := '沒有找到任何記錄';
      end;
    Result := True;
  finally
    s.Free;
  end;
end;

function TdmOrderTime.Action4(var Data, Msg: OleVariant): WordBool;
var
  Option: integer;
begin
  Option := Ole['Option'];
  case Option of
    1: Sql.LoadFromStore(20);
    2: Sql.LoadFromStore(0);
  end;
  Service.Query.LoadSql(Sql.SqlLanguage);
  Service.ReceiveDataWithDefault;
  Result := True;
end;

{ TdmOrderTimeInfo }

function TdmOrderTimeInfo.GetLastUpdate: WideString;
begin
  Result := '2003-10-20';
end;

function TdmOrderTimeInfo.GetMemo: Widestring;
begin
  Result := '';
end;

function TdmOrderTimeInfo.GetModuleIndex: Integer;
begin
  Result := dmOrderTime;
end;

function TdmOrderTimeInfo.GetModuleName: WideString;
begin
  Result := 'OrderTime Module';
end;

function TdmOrderTimeInfo.GetVersion: Widestring;
begin
  Result := '1.0.0.3';
end;

end.

 
 
来自:rester, 时间:2004-5-19 18:12:03, ID:2618442
2004-05-19 14:55:25 烟灰缸(2282902)
重讲一下,今天讨论的内容大概是:
    加深昨天的话题,把一些模糊的概念统一一下。
开课时间:现在开始。

2004-05-19 14:57:25 烟灰缸(2282902)
好,开始,大家先打开PDF。

2004-05-19 14:59:19 烟灰缸(2282902)
昨天有讲到一点,客户端执行RunSQL,算不算违反三层规则,大家说一下。

2004-05-19 15:00:16 风云雨(6614897)
算,但好像又很难避免

2004-05-19 15:01:25 斜阳(249208513)
我觉得不算,如果客户端确实有这个需要的话

2004-05-19 15:02:38 Jackey(15677613)
RunSQL其实是用户自定义了规则.而此规则还是在中间层运行。

2004-05-19 15:02:45 斜阳(249208513)
提供什么接口取决于需求,不能为了三层而三层

2004-05-19 15:03:03 烟灰缸(2282902)
我觉得,比如有一些高级的查询,SQL语句在CLIENT生成比在SERVER生成要快很多,而且效卒要好一点。

2004-05-19 15:03:45 llyygg(13029886)
为什么Client生成会比Server快?

2004-05-19 15:03:46 烟灰缸(2282902)
主要一点是,用户不能自己更改SQL语句就可以了。

2004-05-19 15:04:27 烟灰缸(2282902)
因为是动态生成查询语句,查询条件来自用户自己。

2004-05-19 15:04:38 llyygg(13029886)
不能更改那客户端还要SQL干什么?不理解.

2004-05-19 15:04:43 幽燕游侠(1142610)
其实,将SQL放在中间层
 主要是考虑到维护方便

必要的时候只修改升级中间层,
而不用重新发布客户端

2004-05-19 15:05:08 烟灰缸(2282902)
如果有写过高级动太查询的朋友,应该会理解这一句。

2004-05-19 15:05:12 Jackey(15677613)
to llyygg: 中间层服务器也要占用资源。

2004-05-19 15:05:23 斜阳(249208513)
比如有一种情况,我作了这个软件,我现在要通过客户端调试一些信息,必须直接向数据库中请求信息,而我 只能在客户端工作,那我就要为我提供一个RunSQL的接口来完成我的要求

2004-05-19 15:05:57 幽燕游侠(1142610)
这样的SQL也可以写在中间层饿

2004-05-19 15:06:59 风云雨(6614897)
三层其中一个优点不是比两层安全吗?但如果sql写在客户端,还有什么安全可言?

2004-05-19 15:07:06 llyygg(13029886)
to:斜阳:是啊,其实就是个后门.

2004-05-19 15:07:06 烟灰缸(2282902)
最好的一点是,客户端只生成SQL的WHERE后面的语句或Order by ,Group by 等,不要直接生成整个SQL。

2004-05-19 15:07:07  黑夜(13633497)
这种是意外的,而且只是为我们维护人员服务
可以开例吗?

2004-05-19 15:07:45 斜阳(249208513)
不能算后门,如果我在用客户端,那我就是用户,只不过这个用户特殊了点而已啊。

2004-05-19 15:08:20 llyygg(13029886)
只生成SQL的where后面的语句也很难维护啊,Server端很难解析啊(为了安全的话)

2004-05-19 15:08:52 烟灰缸(2282902)
我的做法是,SQL主句不在客户端生成,也很少在服务层生成,只在“服务器”的SQL管理器中生成。

2004-05-19 15:09:16 风云雨(6614897)
如果是做web的应用,我想大家就不会想到把sql写在Client端了吧

2004-05-19 15:09:33 斜阳(249208513)
其实在这种情况下,中间层只起到了一个存储-转发的功能

2004-05-19 15:09:59 烟灰缸(2282902)
大家看看那个PDF。

2004-05-19 15:09:59 llyygg(13029886)
to:(斜阳)其实我现在的做法和你一样的,不过我自己觉得就是一个后门.

2004-05-19 15:10:57 烟灰缸(2282902)
这个后门应该只让程序员,用户不能用到。

2004-05-19 15:11:16 斜阳(249208513)
是就是吧,反正你得承认,如果没有这个中间层,你根本就不能执行你的 SQL 语句

2004-05-19 15:11:34 llyygg(13029886)
是的,这个模块客户是没有的.

2004-05-19 15:11:54 烟灰缸(2282902)
我不明白你的意思。

2004-05-19 15:12:09 风云雨(6614897)
所以我觉得用delphi做三层很别扭,其实做两层的更好,三层不过是卖点而已

2004-05-19 15:12:18 llyygg(13029886)
我说的是后门哪个模块

2004-05-19 15:12:56 烟灰缸(2282902)
重申:SQL主句在SERVER生成,后句的条件可以由用户生成。

2004-05-19 15:13:21 Jackey(15677613)
关于runsql,其实这个问题可以skip了。 见仁见智.

2004-05-19 15:13:39 风云雨(6614897)
这样两端程序耦合度不是很高了吗?

2004-05-19 15:13:40  黑夜(13633497)
那这样子跟传参数到中间层去由中间层生成sql语句有什么区别呢?

2004-05-19 15:14:39 烟灰缸(2282902)
也一样的,只是跟据要求不同而不同而已。

2004-05-19 15:13:53 烟灰缸(2282902)
好,继续我们的另一个话题。

2004-05-19 15:15:40 斜阳(249208513)
其实我觉得客户端就应该干客户端该干的事情,你要请求一个查询,没必要非要提交一个SQL语句的Where子句 ,这只是一种方法,客户端完全可以把需要请求的数据的条件按照其它的容易解析的方式传给服务器

2004-05-19 15:16:28 烟灰缸(2282902)
谁还记得昨天还有个什么问题没统一意见?

2004-05-19 15:16:44 llyygg(13029886)
是的,但不能是一个SQL语句,可以是一个可以生成SQL语句的文件.

2004-05-19 15:16:55 Jackey(15677613)
关于规则。应该统一了.

2004-05-19 15:17:35 烟灰缸(2282902)
请大家看看PDF,右下角就是我所谓的“规则”,看看和大家是不是一样的。

2004-05-19 15:17:36 斜阳(249208513)
再哪里合成SQL语句不重要,重要的是你的中间层可以负担更多的客户端,中间层维系着业务规则,当业务规则 有变动的时候,你不需要一个一个客户端去跑,去给他们升级软件。我觉得这才是重要的

2004-05-19 15:18:16 llyygg(13029886)
客户端不可能永远不修改吧,客户端做一个自动升级就行了.

2004-05-19 15:18:43 烟灰缸(2282902)
这个问题下一步再深入一些来谈好不好。要不的话又要扯得太远了。

2004-05-19 15:19:10 烟灰缸(2282902)
请大家看看PDF,右下角就是我所谓的"规则",看看和大家是不是一样的。

2004-05-19 15:19:28 烟灰缸(2282902)
每一种规则都是一个DLL。

2004-05-19 15:19:44 Jackey(15677613)
明确一下。

2004-05-19 15:20:16 烟灰缸(2282902)
是你明确了,还是要我明确?

2004-05-19 15:20:36 llyygg(13029886)
我做的比较简单,用COM+做的,每个组建客户端都可以连接,不是通过Action来由服务器调用.

2004-05-19 15:21:11 Jackey(15677613)
比如。erp中进销存,. 出货? 出货的不同类别,你是如何做的

2004-05-19 15:21:59 Jackey(15677613)
是将进销存定义一个dll,还是一个进货类,还是再进一步明细的。

2004-05-19 15:23:10 烟灰缸(2282902)
我的做法是,将进销存中的“进”做成DLL,然后
“进”中的每种单的类型就是Action,类型中再细化的就是Option了。

2004-05-19 15:25:02 llyygg(13029886)
将数据转换成类我觉得很复杂,不知道谁做过.
我现在的都是传递记录.就是定义成一个COM+组建.然后由客户端远程调用.
Jackey是如何做的?

2004-05-19 15:25:25 Jackey(15677613)
也就是说借料. 一般入仓. 检收。等都是作不同的option.

2004-05-19 15:25:50 斜阳(249208513)
还是一个粒度问题,分的越细,越容易被重用,但是太细了就会使使结构变的复杂

2004-05-19 15:25:54 烟灰缸(2282902)
是Action.

2004-05-19 15:27:02 烟灰缸(2282902)
借料里的不同,例如:借主料和借办公用品是不同的,这就是Option.

2004-05-19 15:28:06 烟灰缸(2282902)
喝点水再继续。。。。。。。

2004-05-19 15:28:45 Jackey(15677613)
to llyygg: 但是对于记录你是操作的。

2004-05-19 15:29:23 llyygg(13029886)
但是对于记录你是操作的?不明白-_-!

2004-05-19 15:30:04 烟灰缸(2282902)
好象又要扯得太远了。

2004-05-19 15:31:19 斜阳(249208513)
我觉得在讨论的过程中应该有一个主持人吧,把握住全局

2004-05-19 15:31:34 Jackey(15677613)
比如:入仓。 对应于入仓你有enquire。add update dele. post...

2004-05-19 15:31:45 烟灰缸(2282902)
http://www.delphibbs.com/delphibbs/DispQ.asp?LID=2614850

2004-05-19 15:31:58 llyygg(13029886)
先确定一个主题,然后烟灰缸先说一下,然后大家问问题,然后讨论...如何,一开始就讨论的话很难避免

2004-05-19 15:32:05 烟灰缸(2282902)
大家打开那帖子,看最后的。
如<Code 1>

2004-05-19 15:33:11 llyygg(13029886)
to:Jackey,在Dsp的BeforeUpdateRecord里面写对应的规则.

2004-05-19 15:33:30 烟灰缸(2282902)
我不在那理写规则的。

2004-05-19 15:33:54 llyygg(13029886)
为什么,很方便啊.

2004-05-19 15:34:13 烟灰缸(2282902)
不方便模块化管理。

2004-05-19 15:34:38 烟灰缸(2282902)
我的做法的明细分工。

2004-05-19 15:34:46 Jackey(15677613)
对看烟灰缸的思路往下走。 回头再解释

2004-05-19 15:35:28 烟灰缸(2282902)
大家先看看最后一个回复的前一段,类定义那里。

2004-05-19 15:37:19 烟灰缸(2282902)
看了前段了吗?
    function ActionList(CmdIndex: integer; var Data, Msg: OleVariant): WordBool; override;
    function Action1(var Data, Msg: OleVariant): WordBool;
    function Action2(var Data, Msg: OleVariant): WordBool;
    function Action3(var Data, Msg: OleVariant): WordBool;
    function Action4(var Data, Msg: OleVariant): WordBool;

function TdmOrderTime.ActionList(CmdIndex: integer; var Data, Msg: OleVariant): WordBool;
begin
  case CmdIndex of
    1: Result := Action1(Data, Msg);
    2: Result := Action2(Data, Msg);
    3: Result := Action3(Data, Msg);
    4: Result := Action4(Data, Msg);
  else
    Result := inherited ActionList(CmdIndex, Data, Msg);
  end;
end;

2004-05-19 15:41:08 烟灰缸(2282902)
function ActionList(CmdIndex: integer; var Data, Msg: OleVariant): WordBool; override;
这个函数相当于车间中的主管

2004-05-19 15:42:20 烟灰缸(2282902)
服务层传来包后,由它分配给“本部门”员工去做。

2004-05-19 15:42:29 烟灰缸(2282902)
数据包。

2004-05-19 15:43:09 烟灰缸(2282902)
CmdIndex就是Client中的Ole.Action

2004-05-19 15:43:27 烟灰缸(2282902)
Data有几层意思,迟一点说。

2004-05-19 15:43:44 烟灰缸(2282902)
Msg是指返回客户端的信息。

2004-05-19 15:45:19 烟灰缸(2282902)
按照“办公室管理”的思路,比较好思考一些。

2004-05-19 15:45:40 文(4184443)
什么叫“办公室管理”?

2004-05-19 15:49:23 烟灰缸(2282902)
比如:你是采购部的,你要报销采购的产品,你会如何做?

2004-05-19 15:49:57 文(4184443)
拿发票找领导签字啊!然后再到财务部领钱啊!

2004-05-19 15:49:59  黑夜(13633497)
拿发票去财务部门

2004-05-19 15:50:52 烟灰缸(2282902)
我们都知道, 报销都是支付证明单是不是?


2004-05-19 15:52:19 烟灰缸(2282902)
你填了支付证明单(Client 指定Action)后,

2004-05-19 15:53:33 烟灰缸(2282902)
你要拿到财务室去,你为什么要拿到 尔怚h,这就是“规则”。

2004-05-19 15:54:36 烟灰缸(2282902)
就是这个“规则”让你到人财务室,你肯定不会直接拿给出纳,

2004-05-19 15:56:06 烟灰缸(2282902)
肯定要先有人给你签字,再给会计,这个过程可以说是"ActionList"

2004-05-19 15:56:37 烟灰缸(2282902)
不知有没有说错。。。。

2004-05-19 15:58:55 Jackey(15677613)
是不是可以这样说: 对于财务室,是一个中间层服务器,你提交数据(支付单)。 财务室根据它找相应的 action(报销的规则处理)。 

2004-05-19 15:59:23 烟灰缸(2282902)
会计算完(Action)后,转至出纳(DataIO),再由出纳决定是给钱(Data)给你,还是和你说“没钱”(Msg)

2004-05-19 15:59:32 烟灰缸(2282902)
是。

2004-05-19 16:00:01 烟灰缸(2282902)
但愿我的比喻不会太复杂。。。。。

2004-05-19 16:02:18 烟灰缸(2282902)
function TdmOrderTime.Action1(var Data, Msg: OleVariant): WordBool;
begin
  case CmdIndex of
    1: Result := Action1(Data, Msg);
    2: Result := Action2(Data, Msg);
    3: Result := Action3(Data, Msg);
    4: Result := Action4(Data, Msg);
  else
    Result := inherited ActionList(CmdIndex, Data, Msg);
  end;
end;

2004-05-19 16:02:36 烟灰缸(2282902)
大家看看帖子中这一段的实现部分。
function TdmOrderTime.Action1(var Data, Msg: OleVariant): WordBool;
begin
  case CmdIndex of
    1: Result := Action1(Data, Msg);
    2: Result := Action2(Data, Msg);
    3: Result := Action3(Data, Msg);
    4: Result := Action4(Data, Msg);
  else
    Result := inherited ActionList(CmdIndex, Data, Msg);
  end;
end;


2004-05-19 16:04:13 烟灰缸(2282902)
只看Opton=1部分就可以了。

2004-05-19 16:07:10 风云雨(6614897)
ole是什么来的?

2004-05-19 16:07:37 烟灰缸(2282902)
OLE是数据转换类。

2004-05-19 16:11:03 烟灰缸(2282902)
有一点要说的是,SQL语句我从不放在程序里,而是让SQL管理器来管理。

2004-05-19 16:11:54 烟灰缸(2282902)
我来说好了。OLE的作用是将Client中的数据和参数转成OleVariant.

2004-05-19 16:12:01 llyygg(13029886)
怎么做的?SQL管理器就是Sql这个类吗?

2004-05-19 16:12:03 烟灰缸(2282902)
不是。

2004-05-19 16:12:27 烟灰缸(2282902)
Sql这个类只作读取作用。

2004-05-19 16:12:29 文(4184443)
那是。。。?

2004-05-19 16:12:37 风(68187411)
对了,说到SQL,如果像你那种结构就不能算是三层结构了。
客户端怎么允许写SQL语句呢?

2004-05-19 16:15:12 wind(9186029)
to:烟灰缸
请教你的SQL管理器是放在哪一层?

2004-05-19 16:18:31 烟灰缸(2282902)
数据转换类看昨天的,sql管理器要第5,6课才讲,现在讲Action1好不好。

2004-05-19 16:20:33 烟灰缸(2282902)
          Sql.LoadFromStore(2);
          if Ole['chkWorkTime'] = True then
            sql.Params.ParamValue['@mm_WorkKey'] := Ole['edtWorkTime']
          else
            sql.Params.ParamValue['@mm_WorkKey'] := '@F ot.tw_WorkKey';
          sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];
          sql.Params.ParamValue['@mm_FirstDate'] := Ole['FirstDate'];
          sql.Params.ParamValue['@mm_LastDate'] := Ole['LastDate'];
          Service.Execute(Sql.SqlLanguage);

2004-05-19 16:20:58 烟灰缸(2282902)
我按这一段来讲好不?

2004-05-19 16:24:24 烟灰缸(2282902)
还是继续。
Sql.LoadFromStore(2);

2004-05-19 16:25:38 烟灰缸(2282902)
本意是,从SQL管理中装载本Module的第二条语句。

2004-05-19 16:26:27 Jackey(15677613)
本Module的第二条语句。 ?
是定义在Module中?
 

2004-05-19 16:26:40 Jackey(15677613)
ini?  other?

2004-05-19 16:27:13 烟灰缸(2282902)
不是,SQL语句实际上是存在DATABASE中。

2004-05-19 16:27:41 烟灰缸(2282902)
只是由Sql这个类统一管理读取而已。

2004-05-19 16:27:58 烟灰缸(2282902)
sql.Params.ParamValue['@mm_WorkKey'] := Ole['@mm_WorkTime']
 

2004-05-19 16:28:07 Jackey(15677613)
sql是此规则此action的主要部分。 而所有的sql写在一个表中?

2004-05-19 16:28:54 风云雨(6614897)
这样做有什么好处呢?

2004-05-19 16:29:03 烟灰缸(2282902)
Sql不是单个Action的主要部分,是所有Action读取SQL语句的通道。

2004-05-19 16:29:07 llyygg(13029886)
改SQL不用改程序

2004-05-19 16:29:12 烟灰缸(2282902)

2004-05-19 16:29:45 llyygg(13029886)
但改了SQL的参数,好像还是要改程序?

2004-05-19 16:30:04 Jackey(15677613)
题外: 我的所有sql也都是在一个表中,但是你是用什么加密此数据?

2004-05-19 16:30:09 风云雨(6614897)
就是了

2004-05-19 16:31:01 烟灰缸(2282902)
哪一个加密方法都可以。

2004-05-19 16:31:11 风云雨(6614897)
应该很少机会只修改sql语句就能满足的吧?

2004-05-19 16:31:56 烟灰缸(2282902)
sql.Params.ParamValue['@mm_WorkKey'] := Ole['@mm_WorkTime']

2004-05-19 16:32:47 烟灰缸(2282902)
当SQL需要Param时,它可以在OLE中找(OLE中的参数是Client传来的)。

2004-05-19 16:33:37 烟灰缸(2282902)
sql.Params.ParamValue['@PsnCond'] := '@F ' + Ole['PsnCond'];

2004-05-19 16:33:56 烟灰缸(2282902)
这里的实际上就不是参数这么简单了。

2004-05-19 16:34:45 烟灰缸(2282902)
随然说可以把它当成Param来看待,

2004-05-19 16:35:41 烟灰缸(2282902)
但实际上它是Client中的高级查询生成器生成的(大部分指Where后面的)。

2004-05-19 16:36:15 午秋(345816)
提,提,提个小建议,别见怪呀,能不能讲讲系统的,一味讲语法细节不是教育手法呀!!!!

2004-05-19 16:36:46 烟灰缸(2282902)
加个'@F ' 是让Sql知道它是Func而不普通Param.

2004-05-19 16:37:13 烟灰缸(2282902)
好像不是在讲语法吧。。。。象吗?

2004-05-19 16:37:15 wind(9186029)
如果是多条件查询,而且条件数不一定呢?

2004-05-19 16:37:44 烟灰缸(2282902)
Sql只当它是一个。

2004-05-19 16:38:25 烟灰缸(2282902)
Service.Execute(Sql.SqlLanguage);

2004-05-19 16:39:38 烟灰缸(2282902)
是指,通知服务层执行Sql“解释”后的语句。因为,规则层不能直接执行语句。

2004-05-19 16:40:41 Jackey(15677613)
在以此作例子讲架构。

2004-05-19 16:40:46 烟灰缸(2282902)
对。

2004-05-19 16:41:03 烟灰缸(2282902)
没有例子,讲不成架构了。

2004-05-19 16:41:31 Jackey(15677613)
wait: sqllanguage就是在sql管理器中生成的实际sql?

2004-05-19 16:41:40 烟灰缸(2282902)
是。

2004-05-19 16:42:41 Jackey(15677613)
如何知是哪个账套的?

2004-05-19 16:43:04 烟灰缸(2282902)
因为,我们在写SQL语句时,总会有一些Comment或其它的Params SET,如果让ADO直接执行的话,可能会出错, 而且会加长QueryString.

2004-05-19 16:45:22 Jackey(15677613)
Execute(Sql.SqlLanguage);

2004-05-19 16:45:57 烟灰缸(2282902)
对,执行完后,数据暂时还是服务层,

2004-05-19 16:47:57 烟灰缸(2282902)
所以,就会出现几中可能:
1,无须返回DATA:Service.ReceiveDataWithNoData;
2,要返回DATA:Service.ReceiveDataWithDefault;
3,

2004-05-19 16:48:52 烟灰缸(2282902)
数据由服务层返回Client,规则不谋这个职。

2004-05-19 16:50:12 烟灰缸(2282902)
因为,还要考泸都DLL中返回数据比较麻烦,第二,对应“办公室管理”规则。

2004-05-19 16:50:55 烟灰缸(2282902)
数据返回的技术要点到第8,9课时讲。

2004-05-19 16:52:58 Jackey(15677613)
sql.运行时, 按你的架构, 要动态创建数据联结。如何知是哪个数据联结(账套)

2004-05-19 16:53:51 烟灰缸(2282902)
在服务层创建线程后,用户Login时,就可是确定。

2004-05-19 16:54:54 烟灰缸(2282902)
当你是一个账套一个DATABASE里,比较适知此方法。

2004-05-19 16:55:53 烟灰缸(2282902)
还有不明白的吗?

2004-05-19 16:56:51 文(4184443)
全部都不明白啊!你们说的太高深了!什么线程都来了!

2004-05-19 16:57:28 文(4184443)
我晕!
不好意思,我是菜鸟!

 

2004-05-19 16:58:37 wind(9186029)
我来得晚能不能看看
SQL.LoadFromStore(2) 具体如何实现?

2004-05-19 16:58:47 风云雨(6614897)
还不是很明白你的思路,能否给个完整的例子代码看看(包括客户端服务器)?
hophychow@163.com

2004-05-19 16:59:18 Jackey(15677613)
可能到第8.9课才讲。。。 O

2004-05-19 16:59:30 文(4184443)
好,期待中。。。。

2004-05-19 16:59:31 烟灰缸(2282902)
有些思路可能要在后面讲了,倒回来看时才明白。。。。

2004-05-19 17:00:27 烟灰缸(2282902)
TO风云雨,完整的Source给不了,因为我签了合约了。

2004-05-19 17:01:18 烟灰缸(2282902)
有些技术要点我会直接放在一个地方让大家下载。

2004-05-19 17:01:20 风云雨(6614897)
不一定要商业上的源码,可以是一个小小的demo

2004-05-19 17:01:39 烟灰缸(2282902)
Demo可能没有,都几年前的事了。。。。。。

2004-05-19 17:03:32 烟灰缸(2282902)
可能到了第6课时,我就会放一些Source在另一个网站上,但只留一个星期。


2004-05-19 17:11:59 烟灰缸(2282902)
1,无须返回DATA:Service.ReceiveDataWithNoData;
2,要返回DATA:Service.ReceiveDataWithDefault;

2004-05-19 17:13:05 烟灰缸(2282902)
如果Action是属于Command型的,它无须返回DATA,所以通知服务层Service.ReceiveDataWithNoData;

2004-05-19 17:14:08 烟灰缸(2282902)
如果Action是要返回DATA,而且数据就在服务层的缓冲里,所以就Service.ReceiveDataWithDefault; 

2004-05-19 17:15:43 烟灰缸(2282902)
    if cnt > 0 then
      Msg := format('分析考勤数据成功,共分析了%d条记录.', [cnt])
    else
      Msg := '可能未满足条件,本次操作没有任何记录.';


2004-05-19 17:16:06 烟灰缸(2282902)
这一段比较简单,只是返回信息而已。

2004-05-19 17:16:33 烟灰缸(2282902)
    on E: Exception do
      begin
        Msg := E.Message;
        Result := False;
        Service.ReceiveDataWithNoData;
        Service.RollbackTrans;
      end;

2004-05-19 17:17:18 烟灰缸(2282902)
这一段只是Exception捕捉, 碍藀^给服务层和Client.

2004-05-19 17:19:12 烟灰缸(2282902)
等我忙完这几天,我整理出一个更接近我现在做的架构图出来给大家。

2004-05-19 17:20:10 烟灰缸(2282902)
明天要讲的,大概和服务层有关。

2004-05-19 17:20:10 wind(9186029)
期待ing~~

上一篇:今天還是和大家聊點基本功,就是“如何在DLL中活用Interface” DATE :2004-05-21


下一篇:关于研究 vue-cli3 + electron vue项目打包成桌面客户端 相关文章链接