SmartPersistenceLayer3.1讲解(10)---高级事务处理篇

SmartPersistenceLayer 3.1.0.5版本升级了事务处理,实现“实时事务”功能。此前事务处理存在问题,如后续事务对象无法获取前面操作结果、同一对象多次调用更新不及时。新机制在兼容旧方式基础上,通过“实时提交”解决这些问题,且给出使用范例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         SmartPersistenceLayer 3.1(10) --- 高级事务处理篇

SmartPersistenceLayer对事务处理进行了升级了,实现了实时事务功能,这可以解决以往处理的几种事务情况,将在下面详细讲解。
  SmartPersistenceLayer
的新版本 3.1.0 .5才开始支持此实时事务功能,因此对于以前的版本,只要下载新版本后,直接覆盖原先的PersistenceLayer.Dll即可。

提出问题
 
3.1.0 .5之前,SPL 的事务处理是采用“Add<事务操作>后,一次性提交,也即:
 
假设studentdcuc分别为已经实例化的EntityObjectDeleteCriteriaUpdateCriteria  

Transaction t = new  Transaction();
  t.AddSaveObject(student):           
// 要新增或修改的实体 
  t.AddDeleteObject(student);        // 要删除的实体 
  t.AddDeleteCriteria(dc);           // 添加一个DeleteCriteria 
  t.AddUpdateCriteria(uc);            // 添加一个UpdateCriteria 
  t.AddSqlString(sqlString,dbName);        // 添加一个SQL执行语句 
  t.Process();                           // 执行此事务 

  从上面的方式就可以看出,先是把要进行事务处理的<操作>加到事务中,然后使用Process一次性事务提交的。关于原事务处理的方法,请参考:SmartPersistenceLayer 2.0(5) ---事务处理篇 
  这要的事务处理可以满足大部分的情况,但也因此遇到了一些特殊情况:
   1、  后续事务对象要用到前面的<事务操作>
这种情况,最典型的例子是:
订单主档表的ID采用的是自动增长,而订单明细表要引用主档表的ID。在这种情况下,采用上面的事务处理时,由于没能及时提交<事务操作>,而导致订单明细对象无法取到主档添加进数据库时自动生成的ID值。
  PS:其实我对采用自动增长主键是非常不提倡的,具体的原因可以参考我的文章 数据库主键设计之思考 
  
2、  <事务操作>中对同一对象的多次调用
       这种情况,最典型的例子是:
       在入库单进行入库时,入库单的明细里可能会存在同一物料入库,程序员肯定会对明细进行循环:
       For(物料明细条数)
       {
                从数据库中取得物料的库存对象INVEntity; 
            
    INVEntity.Quantity +=
本明细数量;
               
把此库存对象放到事务中;
        }
    因此对于同一物料库存,将会多次被实例化,由于事务没有及时提交,导致后一次取到的同一对象没有包含上一次的数量更新,结果是,同一物料的库存只进行了最后一次数量的累加。
    对于上面两种情况的发生,根源就是没有<事务操作>进行实时的提交,SPL 3.1.0 .5在原有事务机制兼容的情况下,扩展了新的“实时提交”事务处理机制。  

分析问题

     其实上面的问题都是由于没有及时对<事务操作>进行提交,因此,只要在SPL中,当有新的<事务操作>时,让事务及时提交到数据库,这样在下面的事务处理时就可以取到上次事务的处理结果了。有的朋友说:这不就是ADO.NET的事务机制吗?为何还要封装呢,直接把事务公开不就行了吗?

      不是的,因为SPL是考虑多异构数据库的,也就是事务对象可以不是同一数据库的,更者可能是异构数据库的,比如一个是SQL Server的,另一个是Oracle的。因此SPL要完成这些异构数据库的事务提交,不能直接公开ADO.NET的事务实例。

      由于事务是实时提交,那么比如获取(select)实例的操作,也需要添加到事务中,因为当第一个<事务操作>执行后,那表就会被事务立即锁定,后续<事务操作>要进行此表的查询时,此查询也必须在此事务中执行,当事务提交或者回滚后,才可以进行其他的数据操作。因此SPL事务中添加了获取对象的<事务操作>

 

解决问题

SPL 3.0.1 .5版本为此扩展了一种新的事务机制“实时提交”,原来的事务处理方式完全兼容,这不仅方便SPL的升级更新,原来的Process的事务处理也是有它的优点的,因此在对于没有“及时提交”的情况下,完全可以使用旧的处理机制。
新机制的使用范例:

Transaction t = new  Transaction();   // 实例化事务
 t.DoDeleteCriteria(dc) ; // 执行删除标准DeleteCriteria
 t.DoSaveObject(student);   // 执行保存对象操作
 t.Commit();             // 提交或者t.RollBack()回滚

我把原先的”Add”开头都用”Do”来替换了,这体现了Do的实时特性,由于在”Do”操作时会自动打开自己数据库的连接(因为支持多数据库,所以每个被添加的<事务操作>都允许有自己的数据库源),因此事务的提交与回滚必须要通过手动完成,而且必须得完成,比如:t.Commit()t.RollBack()。如果没有提交或回滚,那么很有可能会锁定<事务操作>的表,这就可能会导致其他此表的处理超过。

运用现在的这种机制可以很方便的解决前面提到的两个典型问题:

 1订单主档表的ID采用的是自动增长   

 A:首先我们创建主档对象并赋上属性的值,如SaleOrder1

B:在事务中执行此操作:t.DoSaveObject(SaleOrder1),因此SPL在处理自动增长列时在保存到数据库后立即返回“生成的值”赋给对象的ID,也就是在此操作时,自动生成的ID值已经被自动赋到对象SaleOrder1的ID属性了。

C:用FOR循环New出明细对象OrderDetail1,OrderDetail2….

D:对这些OrderDetail1,OrderDetail2的SOID(对应订单订档ID)属性赋上

    OrderDetail1.SOID
= SaleOrder1.ID;

E:把OrderDetail1等添加到事务中执行t.DoSaveObject(OrderDetail1)…

F:把事务进行提交t.Commit();

这样就一切OK了。

2、  同一物料库存的累加

只介绍物料循环里的操作即可:

FOR(物料明细循环)

{

  A:new一个库存对象Inv1,把物料值赋上,在事务中获取:t.DoRetrieveObject(Inv1);

  B:这样就获取了实时的库存值,Inv1.Quantity 
+= 本次数量;

  C:把此库存对象添加到事务执行:t.DoSaveObject(Inv1);

}

  上面假设的Inv对象的主键就是物料ID,在使用DoRetrieveCrteria时,是通过对象的主键去Retrieve对象的,因此假设库存对象的主键不是物料ID,则需要通过RetrieveCriteria进行多条件查找到对象,然后跟上面的操作一样了。

FOR(物料明细循环)

{

  A:创建一个多条件的RetrieveCriteria对象,在事务中DataTable dt
= t.DoRetrieveCriteria(rc);

  B:new一个库存对象Inv1,把dt中的主键值赋给Inv1,在事务中获取:t.DoRetrieveObject(Inv1);

  C:这样就获取了实时的库存值,Inv1.Quantity 
+= 本次数量;

  D:把此库存对象添加到事务执行:t.DoSaveObject(Inv1);

}

 上面的方法看似复杂,其实道理是很简单,RetrieveCritera是非主键获取的一种手段。

  参考

   上面介绍了几种简单的Do方法,下面总结所有相关的Do方法以供参考,使用的方法是很相似的。 

  public   void  DoDeleteCriteria(DeleteCriteria delete)   // 执行删除标准
    public   void  DoDeleteCriteria(DeleteCriteria delete, bool  isForceCommit)  // 指定是否强制执行删除标准
   对于isForceCommit是否强制执行,默认值为Transaction.IsForceCommit值false:
       
true :强制执行,即就算遇到更新为零的操作,也不会抛出异常
    flase:非强制执行,如果遇到更新为零,则抛出异常PLException,类型为DirthEntity,表示存在并发错误
   
public   void  DoDeleteObject(EntityObject obj)   // 执行实体删除
    public   void  DoDeleteObject(EntityObject obj, bool  isForceCommit)  // 执行实体删除(isForceCommit同前)
    public   void  DoSaveObject(EntityObject obj)  // 执行实体保存
    public   void  DoSaveObject(EntityObject obj, bool  isForceCommit)  // 执行实体保存(isForceCommit同前)
    public   void  DoUpdateCriteria(UpdateCriteria update)  // 执行更新标准
    public   void  DoUpdateCriteria(UpdateCriteria update, bool  isForceCommit)  // 执行更新标准(isForceCommit同前)
    public   void  DoSqlNonQueryString( string  strSql, string  dbName)  // 执行指定SQL语句
    public   void  DoSqlNonQueryString( string  strSql, string  dbName, bool  isForceCommit)  // 同上(isForceCommit同前)
    public  DataTable DoRetrieveCriteria(RetrieveCriteria retrieve)  // 执行获取标准,返加DataTable
    public   void  DoRetrieveObject(EntityObject obj)  // 执行对象获取,对象会自动被赋上值
    public  DataTable DoSqlQueryString( string  strSql, string  dbName)  // 执行查询SQL,返回DataTable

SPL3.1.0.5新版下载,请参考: SPL3.1.0.5升级-加强了事务的“实时提交”功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值