一步一步教你使用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 < string object >  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 < string object >  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脚本请下载:http://files.cnblogs.com/eastjade/demo.db.doc.sql.rar,本文代码下载:UDA.Demo3.rar

 

链接

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

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

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

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

AgileEAS.NET官方网站

敏捷软件工程实验室

QQ群:116773358

你可能感兴趣的:(agile)