目录
开发现状
Camstar开发过程中,业务代码通常写在以下位置:
1)Web服务端(C#代码)
基于.NET的B/S框架,代码运行环境是IIS,因为直接使用Visual Studio即可编程,并且方便和UI做代码交互,因此很多业务代码都在此处编写。
2)Designer的CLF中
由Web服务端代码调用Camstar的WCF服务触发,在designer中,CLF代码全部执行完毕后才会调用Commit方法提交事务,写入数据库,如果发生异常则会回滚全部CLF代码,因此对于事务要求较高的业务代码,通常在Designer中编写。
开发问题
但是最近遇到需求,业务代码难以在designer的CLF中编写,并且又需要对事务做把控。于是产生问题:如何在C#代码中控制整个程序的事务。
解决方案
1)自定义UserFunction
该方案的开发过程主要是先编写C#代码自定义userfunction,然后将编译好的dll注入到Camstar中,之后在designer的clf中就可以调用到该userfunction。由于代码实际上是在Camstar Service中运行,因此可以保证事务。但是这种开发方式,目前似乎没有项目这么做过,其中的难度较大,光是可以预料到的问题点就使我不想使用该方案。该方法在西门子官网有教程文档,我也没具体做过,因此本文不具体实现该方案。
2)预调用服务
研究Camstar的Event,如下图所示,Event使用了模板方法模式设计,因此可以清晰地看出整个designer程序中的代码运行生命周期(黄色闪电方法从上往下依次执行)。

执行到AfterCommit的时候,已经提交到数据库了。那么如果能把Commit代码的触发交给C#代码中控制,那么既可做到由C#代码控制整个程序的事务提交。模板方法模式+反向控制,我很自然地就想到了通过钩子方法来实现。(模板方法模式和钩子方法可以参考我以前的博文:模板方法模式学习总结)
预调用服务方案设计与实现
文章中我不方便把具体代码之类的都传上来(我博客中一直是不上传具体产品代码的),设计思路和结果都有了,我相信懂的人自然知道怎么代码该怎么写。
代码设计
关键思路是如何在代码执行提交时停止/中断。由C#代码发出提交命令。
我采用的方法是中断,中断的方法是在Commit代码之前通过异常的方式强行中断(应该还有其他更恰当的方式)。
Service基类定义勾子变量 xxxInterrupt,bool类型,用于反向控制是否中断。
在Commit之前写入CLF代码,if(xxxInterrupt) throw; 。将执行结果一并抛出。
C#代码中,由于bool默认值为false,因此对原有代码无影响。如果需要中断,则传入参数Service.xxxInterrupt = true;
实现结果
自定义一个Lot创建界面,定义俩个按钮PreCommit和RealCommit分别代表预提交(不提交到数据库)和真实提交(提交到数据库)。页面定义一个文本框显示执行结果(方便测试),整体页面如下图1所示。
(图1)

服务端调用Lot创建接口,根据给定的流水号规则创建Lot。由于流水号创建不重复,如果PreCommit和RealCommit都执行完成后,系统只真实往数据库提交一次修改,则说明该方案实现成功。
操作1:点击PreCommit,操作结果中显示未提交一笔数据。
操作截图:
(图2,第一次点击,预提交PEP,执行完后查数据库无新数据)

操作2:点击3次RealCommit,操作结果中显示成功3笔数据,其中第一笔为操作1中的数据。
(图3,第一次点击,提交PEP)

(图4,第二次点击,提交PEP,直接写数据库) 
(第三次点击,提交PEP,直接写数据库)

如果只点击PreCommit,不点击RealCommit,最终数据库未插入任何数据,方案实现成功。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218422.html原文链接:https://javaforall.net
