• 工作单元模式(UnitOfWork)学习总结


          工作单元的目标是维护变化的对象列表。使用IUnitOfWorkRepository负责对象的持久化,使用IUnitOfWork收集变化的对象,并将变化的对象放到各自的增删改列表中,

    最后Commit,Commit时需要循环遍历这些列表,并由Repository来持久化。

    Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

          要实现一个银行卡简单转账的功能,Demo框架如下设计:

         

          代码实现如下:

         

          EntityBase,领域类的基类。

         

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Jack.Gao.UnitOfWork.Infrastructure
    {
        public class EntityBase
        {
    
        }
    }
    View Code

         IUnitOfWork,复杂维护变化的对象列表,并最后Commit,依次遍历变化的列表,并持久化,这就是Commit的事情。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Jack.Gao.UnitOfWork.Infrastructure
    {
        public interface IUnitOfWork
        {
            void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
            void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
            void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
            void Commit();
        }
    }
    View Code

        

        IUnitOfWorkRepository,负责持久化对象。

       

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Jack.Gao.UnitOfWork.Infrastructure
    {
        public interface IUnitOfWorkRepository
        {
            void PersistNewItem(EntityBase entityBase);
            void PersistUpdatedItem(EntityBase entityBase);
            void PersistDeletedItem(EntityBase entityBase);
        }
    }
    View Code

       

        UnitOfWork,IUnitOfWork的具体实现。

       

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Transactions;
     7 
     8 namespace Jack.Gao.UnitOfWork.Infrastructure
     9 {
    10     public class UnitOfWork:IUnitOfWork
    11     {
    12         #region Fields
    13 
    14         private Dictionary<EntityBase, IUnitOfWorkRepository> addedEntities;
    15         private Dictionary<EntityBase, IUnitOfWorkRepository> changededEntities;
    16         private Dictionary<EntityBase, IUnitOfWorkRepository> removedEntities;
    17 
    18         #endregion
    19 
    20         #region Constructor
    21 
    22         public UnitOfWork()
    23         {
    24             addedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
    25             changededEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
    26             removedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
    27         }
    28 
    29         #endregion
    30 
    31         #region Implement IUnitOfWork
    32 
    33         public void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
    34         {
    35             this.addedEntities.Add(entityBase,unitOfWorkRepository);
    36         }
    37 
    38         public void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
    39         {
    40             this.changededEntities.Add(entityBase,unitOfWorkRepository);
    41         }
    42 
    43         public void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
    44         {
    45             this.removedEntities.Add(entityBase,unitOfWorkRepository);
    46         }
    47 
    48         public void Commit()
    49         {
    50             using (TransactionScope transactionScope=new TransactionScope())
    51             {
    52                 foreach (var entity in addedEntities.Keys)
    53                 {
    54                     addedEntities[entity].PersistNewItem(entity);
    55                 }
    56 
    57                 foreach (var entity in changededEntities.Keys)
    58                 {
    59                     changededEntities[entity].PersistUpdatedItem(entity);
    60                 }
    61 
    62                 foreach (var entity in removedEntities.Keys)
    63                 {
    64                     removedEntities[entity].PersistDeletedItem(entity);
    65                 }
    66 
    67                 transactionScope.Complete();
    68             }
    69         }
    70 
    71         #endregion
    72     }
    73 }


       

        BankAccount,继承自领域基类EntityBase。

       

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using Jack.Gao.UnitOfWork.Infrastructure;
    
    namespace Jack.gao.UnitOfWork.Domain
    {
        public class BankAccount:EntityBase
        {
            #region Field
    
            public int Id { get; set; }
    
            public decimal Balance { get; set; }
    
            #endregion
    
            #region operator +
    
            public static BankAccount operator+(BankAccount accountLeft,BankAccount accountRight)
            {
                BankAccount account = new BankAccount();
    
                account.Balance = accountLeft.Balance + accountRight.Balance;
    
                return account;
            }
    
            #endregion
        }
    }
    View Code

      

        IAccountRepository,持久化BankAcount接口

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Jack.gao.UnitOfWork.Domain
    {
        public interface IAccountRepository
        {
            void Save(BankAccount account);
            void Add(BankAccount account);
            void Remove(BankAccount account);
        }
    }
    View Code

       

        BankAccountService,服务类,实现转账服务。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using Jack.Gao.UnitOfWork.Infrastructure;
     7 
     8 namespace Jack.gao.UnitOfWork.Domain
     9 {
    10     public class BankAccountService
    11     {
    12         #region Field
    13 
    14         private IAccountRepository _accountRepository;
    15         private IUnitOfWork _unitOfWork;
    16 
    17         #endregion
    18 
    19         #region Constructor
    20 
    21         public BankAccountService(IAccountRepository accountRepository, IUnitOfWork unitOfWork)
    22         {
    23             this._accountRepository = accountRepository;
    24             this._unitOfWork = unitOfWork;
    25         }
    26 
    27         #endregion
    28 
    29         #region Method
    30 
    31         public void TransferMoney(BankAccount from, BankAccount to, decimal balance)
    32         {
    33             if (from.Balance>=balance)
    34             {
    35                 from.Balance = from.Balance - balance;
    36                 to.Balance = to.Balance + balance;
    37 
    38                 _accountRepository.Save(from);
    39                 _accountRepository.Save(to);
    40                 _unitOfWork.Commit();
    41             }
    42         }
    43 
    44         #endregion
    45     }
    46 }


        AccountRepository,持久化具体实现,使用ADO.NET实现,也可以使用其他的EF,NHbernate

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 using Jack.gao.UnitOfWork.Domain;
      7 using Jack.Gao.UnitOfWork.Infrastructure;
      8 using System.Data.SqlClient;
      9 
     10 namespace Jack.gao.UnitOfWork.Persistence
     11 {
     12     public class AccountRepository:IAccountRepository,IUnitOfWorkRepository
     13     {
     14         #region Field
     15 
     16         private const string _connectionString = @"Data Source=T57649MSSQLSERVER2012;Initial Catalog=DB_Customer;Integrated Security=True";
     17 
     18         private IUnitOfWork _unitOfWork;
     19 
     20         #endregion
     21 
     22         #region Constructor
     23 
     24         public AccountRepository(IUnitOfWork unitOfWork)
     25         {
     26             this._unitOfWork = unitOfWork;
     27         }
     28 
     29         #endregion
     30 
     31         #region Implement interface IAccountRepository,IUnitOfWorkRepository
     32 
     33         public void Save(BankAccount account)
     34         {
     35             _unitOfWork.RegisterChangeded(account,this);
     36         }
     37 
     38         public void Add(BankAccount account)
     39         {
     40             _unitOfWork.RegisterAdded(account,this);
     41         }
     42 
     43         public void Remove(BankAccount account)
     44         {
     45             _unitOfWork.RegisterRemoved(account,this);
     46         }
     47 
     48         public void PersistNewItem(EntityBase entityBase)
     49         {
     50             BankAccount account = (BankAccount)entityBase;
     51 
     52             string insertAccountSql = string.Format("insert into DT_Account(balance,Id) values({0},{1})", account.Balance, account.Id);
     53 
     54             SqlConnection sqlConnection = new SqlConnection(_connectionString);
     55 
     56             try
     57             {
     58                 sqlConnection.Open();
     59 
     60                 SqlCommand sqlCommand = new SqlCommand(insertAccountSql, sqlConnection);
     61 
     62                 sqlCommand.ExecuteNonQuery();
     63             }
     64             catch (Exception ex)
     65             {
     66                 throw ex;
     67             }
     68             finally
     69             {
     70                 sqlConnection.Close();
     71             }
     72         }
     73 
     74         public void PersistUpdatedItem(EntityBase entityBase)
     75         {
     76             BankAccount account = (BankAccount)entityBase;
     77 
     78             string updateAccountSql = string.Format("update DT_Account set balance={0} where Id={1}", account.Balance,account.Id);
     79 
     80             SqlConnection sqlConnection = new SqlConnection(_connectionString);
     81 
     82             try
     83             {
     84                 sqlConnection.Open();
     85 
     86                 SqlCommand sqlCommand = new SqlCommand(updateAccountSql, sqlConnection);
     87 
     88                 sqlCommand.ExecuteNonQuery();
     89             }
     90             catch (Exception ex)
     91             {
     92                 throw ex;
     93             }
     94             finally
     95             {
     96                 sqlConnection.Close();
     97             }
     98         }
     99 
    100         public void PersistDeletedItem(EntityBase entityBase)
    101         {
    102             BankAccount account = (BankAccount)entityBase;
    103 
    104             string deleteAccountSql = string.Format("delete from DT_Account where Id={0}", account.Id);
    105 
    106             SqlConnection sqlConnection = new SqlConnection(_connectionString);
    107 
    108             try
    109             {
    110                 sqlConnection.Open();
    111 
    112                 SqlCommand sqlCommand = new SqlCommand(deleteAccountSql, sqlConnection);
    113 
    114                 sqlCommand.ExecuteNonQuery();
    115             }
    116             catch (Exception ex)
    117             {
    118                 throw ex;
    119             }
    120             finally
    121             {
    122                 sqlConnection.Close();
    123             }
    124         }
    125 
    126         #endregion
    127 
    128         #region Method
    129 
    130         public BankAccount GetAccount(BankAccount account)
    131         {
    132             account.Balance = 100;
    133             return account;
    134         }
    135 
    136         #endregion
    137     }
    138 }

        AccountRepositoryTest,测试AccountRepository中的方法

    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Jack.gao.UnitOfWork.Domain;
    using Jack.Gao.UnitOfWork.Infrastructure;
    using Jack.gao.UnitOfWork.Persistence;
    
    namespace Jack.gao.UnitOfWork.Test
    {
        [TestClass]
        public class AccountRepositoryTest
        {
            private IUnitOfWork unitOfWork;
            private IAccountRepository accountRepository;
            private BankAccountService accountService;
    
            public AccountRepositoryTest()
            {
                unitOfWork = new Jack.Gao.UnitOfWork.Infrastructure.UnitOfWork();
                accountRepository = new AccountRepository(unitOfWork);
                accountService = new BankAccountService(accountRepository, unitOfWork);
            }
    
    
            [TestMethod]
            public void Add()
            {
                var accountLeft = new BankAccount() { Balance = 200, Id = 1 };
                var accountRight = new BankAccount() { Balance = 10, Id = 2 };
    
                accountRepository.Add(accountLeft);
                accountRepository.Add(accountRight);
    
                unitOfWork.Commit();
            }
    
            [TestMethod]
            public void Save()
            {
                var accountLeft = new BankAccount() { Balance = 200, Id = 1 };
                var accountRight = new BankAccount() { Balance = 10, Id = 2 };
    
    
                accountService.TransferMoney(accountLeft, accountRight, 100);
            }
    
            [TestMethod]
            public void Remove()
            {
                var accountLeft = new BankAccount() { Balance = 200, Id = 1 };
    
                accountRepository.Remove(accountLeft);
    
                unitOfWork.Commit();
            }
        }
    }
    View Code
  • 相关阅读:
    PSFTP使用简单教程
    JavaMail应用--通过javamail API实现在代码中发送邮件功能
    java常用数据类型转换
    自己封装的Java excel数据读取方法
    java怎样实现重载一个方法
    怎样做好测试保证交付产品质量
    软件测试之测试用例颗粒度问题
    Python 一句命令启动一个web服务器
    ansible 模块之在学习--lineinfile
    centos 7 安装sql 审核工具 inception + archer
  • 原文地址:https://www.cnblogs.com/GaoHuhu/p/3443145.html
Copyright © 2020-2023  润新知