• 业务逻辑层的设计(五)——事务脚本模式介绍


    经过了几个月的奋斗,我终于又可以坐下来写点东西了。

        业务逻辑层设计到此为止已经有第五篇了。

    1、学习曲线低,可以说会C#和SQL的程序员就可以上手了,和领域驱动设计相比很少有改各BUG另一边又出问题的情况。

    2、与ASP.NET WebForm完美契合,事件驱动和事务脚本的理解契合,快速开发,是其他开源界没有的,如Java。没错,这就是ASP.NET WebForm下正确的打开方式。

    3、上限很高,在高级的架构师手里一样可以利用AOP切面编程做日志、权限等,目前的MVC结合其他框架,其实已经包含了很多设计模式,在设计师几乎没有什么空间可以用设计模式,而在事务脚本里却可以体现一个设计师的水平,设计师要造很多框架的轮子,这也是上限很高的原因。

    事务脚本模式的思路:

    通俗一点来说,就是你点了一个按钮触发一个事件时,这个事件中将处理一系列的命令,这些命令组合在一起形成一个事务,然后又可以在另一个按钮事件中重新将他们组合起来,形成一个新的事务。

    比如,我的保存事件中执行一个事务,1检查一些状态;2保存一些数据;

    然后我在另一个提交事件中也执行一个事务,1检查一些状态;2保存一些数据;3流程提交;

    伪代码表示

    public void Save(){
    Dao1 dao1=new Dao1(); dao1.IsExists();
    //检查一些东西
    Dao2 dao1=new Dao2(); dao2.Save();
    //保存一些数据 } public void Submit(){ try{ BeginTran(); Dao1 dao1=new Dao1(); dao1.IsExists();//检查一些东西 Dao2 dao1=new Dao2(); dao2.Save();//保存一些数据 Dao3 dao3=new Dao3(); dao3.GoToNextFlow();//流程提交 Commit(); }catch(){ Rollback(); } }

    看完以上伪代码我们发现保存按钮的时候我们没有启用事务,
    而在提交按钮的时候我们开启了事务,需要保证数据的保存和提交在一个事务中。

    事务管理的实现原理:

    将事务管理从数据访问层上提,放到业务层,并且消除ADO.NET的事务参数。

    如何实现?我们需要将一个数据库连接贯穿整个事件(或者是每个WEB请求),在事件中所有DAO都将使用同一个数据库连接。

    我们只要利用CallContext类把数据库连接放到一个请求上下文中,DAO需要操作数据库时从CallContext中取出连接即可。

    WEB应用程序中也可以直接使用HttpContext。

    在老项目中最好是自己对DBHelper作扩展,简单地使用继承就能在不修改原来代码的基础上扩展出新的DBHelper。

    如果你准备新开发一个系统,那么可以选择使用Spring或者Spring.NET,参看事务管理的那部分,将事务托管给Spring来管理。

    事务脚本模式实战:

     public void Appiont(decimal? schemeid,decimal? aogtype)
        {
            try
            {
                BeginTransaction();
                GetCurrToProviderFlowCMD getcurrToProviderCMD = new GetCurrToProviderFlowCMD(schemeid);
                getcurrToProviderCMD.Run();         //验证流程1是否已开始
                if (getcurrToProviderCMD.CurrFlow > 0) throw new Exception("流程1已经开始,无法重新指定!");
                GetCurrToStorageFlowCMD getcurrToStorageCMD = new GetCurrToStorageFlowCMD(schemeid);
                getcurrToStorageCMD.Run();         //验证流程2是否已开始
                if (getcurrToStorageCMD.CurrFlow > 0) throw new Exception("流程2已经开始,无法重新指定!");
                AOGTypeFlowDeleteCMD aogtypeflowdelCMD = new AOGTypeFlowDeleteCMD(schemeid);
                aogtypeflowdelCMD.Run();            //删除流程任务
                AOGTypeAppointCMD aogtypeappointCMD = new AOGTypeAppointCMD(schemeid, aogtype);
                if (aogtypeappointCMD.Run() == 0) throw new DataBaseExecuteInvalidException();      //指定到货方式
                if (aogtype != null)
                {
                    IAOGTypeFlowCreateCMD aogtypeflowcreateCMD = AOGTypeFlowCreate.Init(schemeid, aogtype);
                    if (aogtypeflowcreateCMD.Run() == 0) throw new DataBaseExecuteInvalidException();        //插入新的流程任务
                }
                Commit();
            }
            catch (Exception ex)
            {
                RollBack();
                throw new Exception(ex.Message);
            }
        }
    public class GetCurrToProviderFlowCMD : BaseCommand
    {
        private decimal? _schemeid;
    
        private int _currFlow;
    
        public int CurrFlow
        {
            get { return _currFlow; }
        }
    
        public GetCurrToProviderFlowCMD(decimal? schemeid)
        {
            _schemeid = schemeid;
        }
    
        public int Run()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("select currflow from oproviderflow where schemeid=:schemeid");
            OracleParameter prm = new OracleParameter(":schemeid", OracleDbType.Decimal);
            prm.Value = _schemeid;
            string res = database.ExecuteScalar(builder.ToString(), prm);
            _currFlow = res != "" ? Convert.ToInt32(res) : 0;
            return 1;
        }
    }


    下面是使用微软企业库实现的版本

        public class FirstCommand:BaseCommand
        {
            private DataTable _table;
    
            private int _id;
    
            public DataTable Table
            {
                get { return _table; }
            }
    
            public FirstCommand(int id)
            {
                this._id = id;
            }
    
            public int Run()
            {
                IDbCommand cmd=dbHelper.GetSqlStringCommand("select * from SYS_RESOURCE  where ID=:resid");
                dbHelper.AddInParameter(cmd, ":resid", DbType.Int32, _id);
                _table = dbHelper.ExecuteDataTable(cmd);
                return 1;
            }
        }
  • 相关阅读:
    Spring面试,IoC和AOP的理解
    WEB打印(jsp版)
    Spring事务管理机制的实现原理-动态代理
    spring面试题
    oracle PLSQL基础学习
    oracle创建表空间
    WM_CONCAT字符超过4000的处理办法
    Oracle 数据泵使用详解
    Oracle 数据泵详解
    linux下启动oracle
  • 原文地址:https://www.cnblogs.com/13yan/p/3434341.html
Copyright © 2020-2023  润新知