Thinking in Design Pattern -- unit of work (Work Unit) Model exploration

Source: Internet
Author: User
ArticleDirectory
    • Create an infrastructure
    • Create model
    • Establish repository to persist business entities
What is the unit of work mode?

The unit of work mode is used to maintain a list of business objects that have been modified (added, deleted, or updated) by business transactions. The unit of work mode coordinates the persistence of these changes and the concurrency of all tags. The benefit of using the unit of work mode in the data access layer is to ensure data integrity. If a problem occurs during the persistence of a series of business objects (they belong to the same thing), all modifications should be rolled back to ensure that the data is always in a valid state.

To demonstrate the unit of work mode, a simple banking domain is used to model the transfer between two accounts. The interaction between the service layer (accountservice) and the resource layer (accountrepository) that uses the unit of work mode (to ensure that the transfer is committed as an atomic thing) is provided.

 

Remember this image, because the followingCodeThe logic is implemented according to the definition of this figure.

Create an infrastructure
    • Next, we will write the solution code. First, we will create all the supporting infrastructure code for the unit of work mode.
 Public InterfaceIaggregateroot {}

The iaggregateroot interface actually belongsMark InterfaceThis interface acts as the class and MethodMetadataThe resource library we built only persistently implements the Business Objects of the iaggregateroot interface, so the implementation of unit of workUse the iaggregateroot interface to reference any business entity involved in an atomic transaction.

    • Add another iunitofworkrepository interface, which is used for persistent operations:
 Public InterfaceIunitofworkrepository {VoidPersistcreationof (iaggregateroot entity );VoidPersistupdateof (iaggregateroot entity );VoidPersistdeletionof (iaggregateroot entity );}
    • Then, add the iunitofwork interface to the infrastructure project:
 Public InterfaceIunitofwork {VoidRegisteramended (iaggregateroot entity, iunitofworkrepository unitofworkrepository );VoidRegisternew (iaggregateroot entity, iunitofworkrepository unitofworkrepository );VoidRegisterremoved (iaggregateroot entity, iunitofworkrepository unitofworkrepository );VoidCommit ();}

It is worth noting that the iunitofwork interface requires iunitofworkrepository when registering and modifying/adding/deleting. In this way, the unit of work can delegate the truly persistent work to appropriate implementations during submission.

    • Finally, add unitofwork to the infrastructure project to implement iunitofwork:
  Public   Class  Unitofwork: iunitofwork {  Private Dictionary <iaggregateroot, iunitofworkrepository> Addedentities;  Private Dictionary <iaggregateroot, iunitofworkrepository> Changedentities;  Private Dictionary <iaggregateroot, iunitofworkrepository> Deletedentities;  Public Unitofwork () {addedentities = New Dictionary <iaggregateroot, iunitofworkrepository> (); Changedentities = New Dictionary <iaggregateroot, iunitofworkrepository> (); Deletedentities = New Dictionary <iaggregateroot, iunitofworkrepository> ();}  Public   Void Registeramended (iaggregateroot entity, iunitofworkrepository unitofworkrepository ){  If (! Changedentities. containskey (entity) {changedentities. Add (entity, unitofworkrepository );}}  Public   Void  Registernew (iaggregateroot entity, iunitofworkrepository unitofworkrepository ){  If (! Addedentities. containskey (entity) {addedentities. Add (entity, unitofworkrepository );};}  Public  Void  Registerremoved (iaggregateroot entity, iunitofworkrepository unitofworkrepository ){  If (! Deletedentities. containskey (entity) {deletedentities. Add (entity, unitofworkrepository );}}  Public   Void  Commit (){  Using (Transactionscope scope = New  Transactionscope ()){  Foreach (Iaggregateroot entity In   This  . Addedentities. Keys ){  This  . Addedentities [entity]. persistcreationof (entity );}  Foreach (Iaggregateroot entity In   This  . Changedentities. Keys ){  This  . Changedentities [entity]. persistupdateof (entity );} Foreach (Iaggregateroot entity In   This  . Deletedentities. Keys ){  This  . Deletedentities [entity]. persistdeletionof (entity);} scope. Complete ();}}} 

The unitofwork class uses three dictionary variables to track modifications to the generation of business entities. The first dictionary corresponds to the entity added to the data storage. The first dictionary traces the updated entity, and the third dictionary processes the object deletion, iunitofworkrepository that matches the object key in the dictionary will be saved and usedCommitMethodTo call the repository object. The object contains the code of the truly Persistent Object.. The commit method traverses each dictionary and calls the corresponding iunitofworkrepository method (passing object references ). The work in the commit method isTransactionscopeCode packaging. If an exception occurs when a task is executed in iunitofworkrepository, all work will be rolled back and data storage will remain in the original state.

Create model
    • Add a new class account to the model to indicate a bank account. To facilitate demonstration, the following is a simple process:
 
Public class account: iaggregateroot {public decimal balance {Get; Set ;}}
    • To make accout persistent, add the iaccountrepository interface:
Public InterfaceIaccountrepository {VoidSave (account Account );VoidAdd (account Account );VoidRemove (account Account );}
    • Add the accountservice service class to coordinate the transfer between two accounts.
 Public   Class  Accountservice {  Private  Iaccountrepository _ accountrepository; Private  Iunitofwork _ unitofwork;  ///   <Summary>          ///  Accountservice uses its constructor to implement dependency Injection  ///   </Summary>          ///   <Param name = "accountrepository"> </param>          ///   <Param name = "unitofwork"> </param>          Public Accountservice (iaccountrepository accountrepository, iunitofwork unitofwork) {_ accountrepository = Accountrepository; _ unitofwork = Unitofwork ;}  ///   <Summary>          ///  Transfers funds between two accounts  ///   </Summary>          ///   <Param name = "from"> </param>          ///  <Param name = "to"> </param>          ///   <Param name = "amount"> </param>          Public   Void Transfer (account From , Account, Decimal  Amount ){  If ( From . Balance> = Amount ){  From . Balance-=Amount; To. Balance + = Amount; _ accountrepository. Save (  From  ); _ Accountrepository. Save (to); _ unitofwork. Commit ();}}} 

Next, it calls the account repository to save the two accounts. Finally, it calls the commit method of the unit of work instance to ensure that the transaction is completed as an atomic unit of work.So the next point is how repository interacts with the unit of work.

Establish repository to persist business entities
  Public   Class  Accountrepository: iaccountrepository, iunitofworkrepository {  Private Iunitofwork _ unitofwork;  Public  Accountrepository (iunitofwork unitofwork) {_ unitofwork = Unitofwork ;}  Public   Void  Save (account Account) {_ unitofwork. registeramended (account,  This  );}  Public   Void  Add (account Account) {_ unitofwork. registernew (account, This  );}  Public   Void  Remove (account Account) {_ unitofwork. registerremoved (account,  This  );}  Public   Void  Persistupdateof (iaggregateroot entity ){  //  Ado.net or EF, NH for persistence  }  Public  Void  Persistcreationof (iaggregateroot entity ){  //  Ado.net or EF, NH for persistence  }  Public   Void  Persistdeletionof (iaggregateroot entity ){  //  Ado.net or EF, NH for persistence  }} 

OK, so that the unit of work mode can be set up,AccountrepositoryImplementedIaccountrepositoryAndIunitofworkrepositoryInterface, iaccountrepository method implementation simply delegate workUnit of work(Pass in the object to be persisted and reference of repository), and finally, callUnit of workClassCommitIn fact, the unit of work references repository.IunitofworkrepositoryFor the persistence operation, you can use ado.net, EF, and NH.

Looking back, let's look at this picture. The unit of work is just like this:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.