zoukankan      html  css  js  c++  java
  • 工作单元模式(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
        {
    
        }
    }
    复制代码

         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();
        }
    }
    复制代码

        

        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);
        }
    }
    复制代码

       

        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
        }
    }
    复制代码

      

        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);
        }
    }
    复制代码

       

        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();
            }
        }
    }
  • 相关阅读:
    Codeforces Round 546 (Div. 2)
    Codeforces Round 545 (Div. 2)
    Codeforces Round 544(Div. 3)
    牛客小白月赛12
    Codeforces Round 261(Div. 2)
    Codeforces Round 260(Div. 2)
    Codeforces Round 259(Div. 2)
    Codeforces Round 258(Div. 2)
    Codeforces Round 257 (Div. 2)
    《A First Course in Probability》-chaper5-连续型随机变量-随机变量函数的分布
  • 原文地址:https://www.cnblogs.com/bdbw2012/p/4755319.html
Copyright © 2011-2022 走看看