• 一步一步教你使用AgileEAS.NET基础类库进行应用开发基础篇UDA中处理事务


    前文回顾

            在之前的文章一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-使用UDA操纵SQL语句一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-UDA中的委托与应用两篇文章中详细的介绍了如何使用UDA进行常规的业务进行操作,以及AgileEAS.NET平台中UDA的两种数据处理模式对比,以及基于懒惰模式的代理查询。

    事务处理

           我们知道在应用开发中,使用单SQL语句进行业务处理永远无法满足复杂的应用,一个业务可以需要2-N条SQL语句的配合才能完成,并且要求处理的数据保持一致性,也就是要求2-N语言要么全部执行成功,要么全部失败,不能产品执行一部分另一部分因为某些原因无法执行,造成数据的不一致。

           .NET的Ado.NET为我们提供了事务处理机制,AgileEAS.ENT平台的统一数据访问(UDA)支持基于ADO.NET的事务处理机制,并对其进行了封装。

    处理流程

           标准的事务处理流程是在UDA的数据操作流程的基础上增加事务的打开、提交与回滚三个操作,流程如下:

    image

           AgileEAS.NET平台的UDA也为事务提供了一种懒得的处理模式,即事务托管执行,应用开发人员在这种模式中不用考虑连接的打和关闭,也不用考虑事务的开始、提交与回滚,而只需要关注应用业务就行。

    事务处理的例子

           假定我们需要处理一个商品的入库业务,涉及三个数据表,从商品字典有查出商品字典数据,向商品入库记录表和商品库存表同步写入数据,我们假定实现以单位为采购100单位的商品编码为“1AZ0002094” ,名称为“95%医用酒精”的业务,交易价格为12.5元,处理代码如下: 

    代码
     1     /// <summary>
     2     /// 标准流程的事务处理。
     3     /// </summary>
     4     public void DemoTransaction()
     5     {
     6         IDataAccessor accessor = UdaContext.DataAccessor;
     7         accessor.DataConnection.Open();
     8 
     9         try
    10         {
    11             try
    12             {
    13                 (accessor.DataConnection as IConnection).BeginTransaction();
    14 
    15                 ParameterCollection pc = new ParameterCollection();
    16                 pc.Add("CODE""1AZ0002094");
    17 
    18                 IDictionary<stringobject> dc = accessor.QueryDictionary("SELECT * FROM dbo.PRODUCT where CODE= ?", pc);
    19                 string billCode = DateTime.Now.ToString("yyyyMMddHHmmss");
    20 
    21                 pc = new ParameterCollection();
    22                 pc.Add("BILLCODE", billCode);
    23                 pc.Add("CODE", dc["CODE"]);
    24                 pc.Add("NAME", dc["NAME"]);
    25                 pc.Add("SPEC", dc["SPEC"]);
    26                 pc.Add("UNIT", dc["UNIT"]);
    27                 pc.Add("PRICE"12.5M);
    28                 pc.Add("NUMBER"100);
    29                 pc.Add("OPERATOR""james");
    30                 pc.Add("INTIME", DateTime.Now);
    31 
    32                 //入库记录
    33                 accessor.Execute("INSERT dbo.PIN(IDN,BILLCODE,CODE,NAME,SPEC,UNIT,PRICE,NUMBER,OPERATOR,INTIME) select isnull(max(idn),0)+1,?,?,?,?,?,?,?,?,? from dbo.PIN", pc);
    34 
    35                 //库存
    36                 pc = new ParameterCollection();
    37                 pc.Add("CODE", dc["CODE"]);
    38                 pc.Add("PRICE"12.5M);
    39 
    40                 int storeRecords = (int)accessor.QueryScalar("SELECT count(*) FROM dbo.PSTORE where CODE= ? and PRICE = ?", pc);
    41                 if (storeRecords > 0)
    42                 {
    43                     accessor.QueryScalar("UPDATE dbo.PSTORE Set NUMBER=NUMBER +" + 100 + " where CODE= ? and PRICE = ?", pc);
    44                 }
    45                 else
    46                 {
    47                     pc = new ParameterCollection();
    48                     pc.Add("CODE", dc["CODE"]);
    49                     pc.Add("NAME", dc["NAME"]);
    50                     pc.Add("SPEC", dc["SPEC"]);
    51                     pc.Add("UNIT", dc["UNIT"]);
    52                     pc.Add("PRICE"12.5M);
    53                     pc.Add("NUMBER"100);
    54 
    55                     accessor.Execute("INSERT dbo.PSTORE(IDN,CODE,NAME,SPEC,UNIT,PRICE,NUMBER) select isnull(max(idn),0)+1,?,?,?,?,?,? from dbo.PSTORE", pc);
    56                 }
    57 
    58                 (accessor.DataConnection as IConnection).CommitTransaction();
    59                 System.Console.WriteLine("事务已成功提交。");
    60             }
    61             catch
    62             {
    63                 (accessor.DataConnection as IConnection).RollbackTransaction();
    64                 System.Console.WriteLine("事务已回滚。");
    65                 throw;
    66             }
    67         }
    68         finally
    69         {
    70             accessor.DataConnection.Close();
    71         }
    72     }

    使用事务委托

           上面的单码需要应用开发人管理数据库的打开、关闭,还得处理事务的开始、提交与回滚业务,每个都如些进行处理,容易出错,程序也不是很简洁,在AgileEAS.NET平台的统一数据访问(UDA)中提供了一种更为简洁的事务处理处理方式事务委托,我们定义了TransactionHandler及TransactionHandler2两个事务委托:

        /// <summary>
        /// 定义数据库操作的事务处理委托。该委托将代表客户执行数据库事务,这样使用者不需要考虑事务的开始和结束。
        /// </summary>
        /// <param name="Accessor">数据访问器对象。</param>
        public delegate void TransactionHandler(IDataAccessor Accessor);
    
        /// <summary>
        /// 定义数据库操作的事务处理委托。该委托将代表客户执行数据库事务,这样使用者不需要考虑事务的开始和结束。
        /// </summary>
        /// <param name="Accessor">数据访问器对象。</param>
        /// <param name="parameters">委托参数。</param>
        public delegate void TransactionHandler2(IDataAccessor Accessor, params object[] parameters);

           在IDataAccessor接口中定义了使用这两个委托的事务委托方法TransactionExecute(托管执行),闲话不说了,我们来使用TransactionExecute改造以上代码:

    代码
     1     /// <summary>
     2     /// 委托方式的事务。
     3     /// </summary>
     4     public void DemoTransaction()
     5     {
     6         IDataAccessor accessor = UdaContext.DataAccessor;
     7         try
     8         {
     9             accessor.TransactionExecute(new TransactionHandler(this.InternalSaveData));
    10             System.Console.WriteLine("事务已成功提交。");
    11         }
    12         catch
    13         {
    14             System.Console.WriteLine("事务已回滚。");
    15         }
    16     }
    17 
    18     /// <summary>
    19     /// 事务代理方法。
    20     /// </summary>
    21     /// <param name="accessor"></param>
    22     void InternalSaveData(IDataAccessor accessor)
    23     {
    24         ParameterCollection pc = new ParameterCollection();
    25         pc.Add("CODE""1AZ0002094");
    26 
    27         IDictionary<stringobject> dc = accessor.QueryDictionary("SELECT * FROM dbo.PRODUCT where CODE= ?", pc);
    28         string billCode = DateTime.Now.ToString("yyyyMMddHHmmss" +"_1");
    29 
    30         pc = new ParameterCollection();
    31         pc.Add("BILLCODE", billCode);
    32         pc.Add("CODE", dc["CODE"]);
    33         pc.Add("NAME", dc["NAME"]);
    34         pc.Add("SPEC", dc["SPEC"]);
    35         pc.Add("UNIT", dc["UNIT"]);
    36         pc.Add("PRICE"12.5M);
    37         pc.Add("NUMBER"100);
    38         pc.Add("OPERATOR""james");
    39         pc.Add("INTIME", DateTime.Now);
    40 
    41         //入库记录
    42         accessor.Execute("INSERT dbo.PIN(IDN,BILLCODE,CODE,NAME,SPEC,UNIT,PRICE,NUMBER,OPERATOR,INTIME) select isnull(max(idn),0)+1,?,?,?,?,?,?,?,?,? from dbo.PIN", pc);
    43 
    44         //库存
    45         pc = new ParameterCollection();
    46         pc.Add("CODE", dc["CODE"]);
    47         pc.Add("PRICE"12.5M);
    48 
    49         int storeRecords = (int)accessor.QueryScalar("SELECT count(*) FROM dbo.PSTORE where CODE= ? and PRICE = ?", pc);
    50         if (storeRecords > 0)
    51         {
    52             accessor.QueryScalar("UPDATE dbo.PSTORE Set NUMBER=NUMBER +" + 100 + " where CODE= ? and PRICE = ?", pc);
    53         }
    54         else
    55         {
    56             pc = new ParameterCollection();
    57             pc.Add("CODE", dc["CODE"]);
    58             pc.Add("NAME", dc["NAME"]);
    59             pc.Add("SPEC", dc["SPEC"]);
    60             pc.Add("UNIT", dc["UNIT"]);
    61             pc.Add("PRICE"12.5M);
    62             pc.Add("NUMBER"100);
    63 
    64             accessor.Execute("INSERT dbo.PSTORE(IDN,CODE,NAME,SPEC,UNIT,PRICE,NUMBER) select isnull(max(idn),0)+1,?,?,?,?,?,? from dbo.PSTORE", pc);
    65         }            
    66     }
          是不是发现这种处理方式很简洁呢,本文到此为止,下文我将介绍使用IOC解藕数据库连接对象(数据访问提供者)。

              有关本例子所涉及的数据表结构请参考基于AgileEAS.NET平台基础类库进行应用开发-总体说明及数据定义一文,有关数据对象模型定义文件、文档、DDL脚本请下载:https://files.cnblogs.com/eastjade/demo.db.doc.sql.rar,本文代码下载:UDA.Demo3.rar

    链接

    一步一步教你使用AgileEAS.NET基础类库进行应用开发-系列目录

    AgileEAS.NET平台开发指南-系列目录

    AgileEAS.NET应用开发平台介绍-文章索引

    AgileEAS.NET平台应用开发教程-案例计划

    AgileEAS.NET官方网站

    敏捷软件工程实验室

    QQ群:116773358

  • 相关阅读:
    工具使用:Oracle数据库表转换为Mysql
    使用Spring框架下的完成对事务的操作
    使用Spring框架下的JdbcTemplate 完成对数据库的增删改查操作
    我的历程,从心开始
    验证码
    加载效果
    mybatis逆向工程
    lo4j配置文件
    springmvc拦截器
    如何在标题栏加入图标
  • 原文地址:https://www.cnblogs.com/eastjade/p/1832344.html
Copyright © 2020-2023  润新知