• c#领域驱动设计


    代码是个程序员都能写,

    怎么的代码才是好的,

     

    --------------------------------------------------------------------------------------------------

    1.设计

      1.可靠性和可得性

        数据库有问题的时候,一般都是系统重启,新系统数据系统应该能够在使用过程中备份,而不应该轻易发生错误。

        2.伸缩性

        系统应该能够处理用户源源不断的需求。

      3.可维护性

        系统代码重复改一个需求到处粘贴复制,这种情况下必须考虑重构,领域逻辑处于核心位置,而且绝对不重复,可复用。

    2.设计架构层

      1.基础设施层

        该层被所有的层所引用,定义所有的基础设施所需的方法。

         2.应用层

        主要维护任务的状态,负责不同领域对象之间的协调动作,该层的方法大多都是静态的

         3.领域层

        该层主要负责业务逻辑

         4.持久层

                该层主要负责数据持久化(与数据库打交到)

         5.UI层

                页面呈现

         6.数据传输层

                数据实体对象(负责数据运输的实体对象)

        

    基础设施层

     1. 定义一个实体接口 IEntity

       定义一个实体接口标识该对象为实体对象(并且标识主键key)

     1     /// <summary>
     2     /// 实体接口
     3     /// </summary>
     4     public interface IEntity
     5     {
     6         /// <summary>
     7         /// key
     8         /// </summary>
     9         object Key { get; }
    10     }
    View Code

     2.抽象一个分层超类型 EntityBase

          抽象一个基类所有的领域模型都将继承它以获得他们的标识

      1     /// <summary>
      2     /// 实体抽象类
      3     /// </summary>
      4     public abstract class EntityBase : IEntity
      5     {
      6         /// <summary>
      7         /// 标识key
      8         /// </summary>
      9         private readonly object key;
     10 
     11         /// <summary>
     12         /// Initializes a new instance of the <see cref="EntityBase"/> class. 
     13         /// 默认构造函数 default constructor
     14         /// </summary>
     15         protected EntityBase()
     16             : this(null)
     17         {
     18         }
     19 
     20         /// <summary>
     21         /// Initializes a new instance of the <see cref="EntityBase"/> class.
     22         /// </summary>
     23         /// <param name="key">key</param>
     24         protected EntityBase(object key)
     25         {
     26             this.key = key;
     27         }
     28 
     29         /// <summary>
     30         /// Gets the key.
     31         /// </summary>
     32         public object Key
     33         {
     34             get
     35             {
     36                 return this.key;
     37             }
     38         }
     39 
     40         /// <summary>
     41         /// The equals.
     42         /// </summary>
     43         /// <param name="other">
     44         /// The other.
     45         /// </param>
     46         /// <returns>
     47         /// The <see cref="bool"/>.
     48         /// </returns>
     49         protected bool Equals(EntityBase other)
     50         {
     51             return Equals(this.Key, other.Key);
     52         }
     53 
     54         /// <summary>
     55         /// The equals.
     56         /// </summary>
     57         /// <param name="entity">
     58         /// The entity.
     59         /// </param>
     60         /// <returns>
     61         /// The <see cref="bool"/>.
     62         /// </returns>
     63         public override bool Equals(object entity)
     64         {
     65             if (entity == null || !(entity is EntityBase))
     66             {
     67                 return false;
     68             }
     69 
     70             return this == (EntityBase)entity;
     71         }
     72 
     73         /// <summary>
     74         /// The get hash code.
     75         /// </summary>
     76         /// <returns>
     77         /// The <see cref="int"/>.
     78         /// </returns>
     79         public override int GetHashCode()
     80         {
     81             return this.Key != null ? this.Key.GetHashCode() : 0;
     82         }
     83 
     84         /// <summary>
     85         /// The ==.
     86         /// </summary>
     87         /// <param name="left">
     88         /// The base 1.
     89         /// </param>
     90         /// <param name="right">
     91         /// The base 2.
     92         /// </param>
     93         /// <returns>
     94         /// </returns>
     95         public static bool operator ==(EntityBase left, EntityBase right)
     96         {
     97             if ((object)left == null && (object)right == null)
     98             {
     99                 return true;
    100             }
    101 
    102             if ((object)left == null || (object)right == null)
    103             {
    104                 return false;
    105             }
    106 
    107             return left.Key == right.Key;
    108         }
    109 
    110         /// <summary>
    111         /// The !=.
    112         /// </summary>
    113         /// <param name="left">
    114         /// The base 1.
    115         /// </param>
    116         /// <param name="right">
    117         /// The base 2.
    118         /// </param>
    119         /// <returns>
    120         /// </returns>
    121         public static bool operator !=(EntityBase left, EntityBase right)
    122         {
    123             return !(left == right);
    124         }
    125     }
    View Code

         做一个泛型的标识继承EntityBase

     1     /// <summary>
     2     /// The entity.
     3     /// </summary>
     4     /// <typeparam name="T">
     5     /// </typeparam>
     6     public abstract class EntityBase<T> : EntityBase
     7     {
     8         /// <summary>
     9         /// Initializes a new instance of the <see cref="EntityBase{T}"/> class. 
    10         /// Initializes a new instance of the <see cref="EntityBase"/> class. 
    11         /// 默认构造函数 default constructor
    12         /// </summary>
    13         protected EntityBase()
    14             : base(null)
    15         {
    16         }
    17 
    18         /// <summary>
    19         /// Initializes a new instance of the <see cref="EntityBase{T}"/> class. 
    20         /// Initializes a new instance of the <see cref="EntityBase"/> class.
    21         /// </summary>
    22         /// <param name="key">
    23         /// key
    24         /// </param>
    25         protected EntityBase(T key)
    26             : base(key)
    27         {
    28         }
    29 
    30         /// <summary>
    31         /// Gets the key.
    32         /// </summary>
    33         public new T Key
    34         {
    35             get
    36             {
    37                 T @default = default(T);
    38                 if (base.Key == null)
    39                 {
    40                     return @default;
    41                 }
    42 
    43                 return (T)base.Key;
    44             }
    45         }
    46     }
    View Code

    3. 仓储接口 IRepository<in TKey, TValue>

     仓储接口提供增删查改的方法签名,并且多了一个索引 TValue类型并且标识为IEntity

     1     /// <summary>
     2     /// 仓储接口
     3     /// </summary>
     4     /// <typeparam name="TKey">TKey</typeparam>
     5     /// <typeparam name="TValue">TValue</typeparam>
     6     public interface IRepository<in TKey, TValue>
     7         where TValue : EntityBase<TKey>
     8     {
     9         /// <summary>
    10         /// 根据key查询
    11         /// </summary>
    12         /// <param name="key">key</param>
    13         /// <returns>TValue</returns>
    14         TValue FindBy(TKey key);
    15 
    16         /// <summary>
    17         /// 添加
    18         /// </summary>
    19         /// <param name="item">item</param>
    20         void Add(TValue item);
    21 
    22         /// <summary>
    23         /// 索引查询
    24         /// </summary>
    25         /// <param name="key">key</param>
    26         /// <returns>TValue</returns>
    27         TValue this[TKey key] { get; set; }
    28 
    29         /// <summary>
    30         /// 删除
    31         /// </summary>
    32         /// <param name="item">item</param>
    33         void Remove(TValue item);
    34 
    35         /// <summary>
    36         /// 更新
    37         /// </summary>
    38         /// <param name="item">item</param>
    39         void Update(TValue item);
    40     }
    View Code

     4.仓储工厂

      通过配置文件创建仓储(配置类就不多说,稍后附上源码),为了决定创建哪一种仓储,RespositoryFactory类使用泛型类型参数。

     1     /// <summary>
     2     /// 仓储工厂
     3     /// </summary>
     4     public static class RepositoryFactory
     5     {
     6         /// <summary>
     7         /// Dictionary to enforce the singleton pattern
     8         /// </summary>
     9         private static readonly Dictionary<string, object> m_respository = new Dictionary<string, object>();
    10 
    11         /// <summary>
    12         /// The get repository.
    13         /// </summary>
    14         /// <typeparam name="TRepository">
    15         /// </typeparam>
    16         /// <typeparam name="TEntity">
    17         /// </typeparam>
    18         /// <returns>
    19         /// The <see cref="TRepository"/>.
    20         /// </returns>
    21         public static TRepository GetRepository<TRepository, TEntity>()
    22             where TRepository : class, IRepository<TEntity>
    23             where TEntity : EntityBase
    24         {
    25             TRepository respository = default(TRepository);
    26             string interfaceShortName = typeof(TRepository).Name;
    27             if (!m_respository.ContainsKey(interfaceShortName))
    28             {
    29                 RepositorySettings settings = (RepositorySettings)ConfigurationManager.GetSection(RepositoryMappingConstants.RepositoryMappingsConfigurationSectionName);
    30                 string repositoryFullTypeName = settings.RepositoryMappings[interfaceShortName].RepositoryFullTypeName;
    31                 Type type = Type.GetType(repositoryFullTypeName);
    32                 if (type != null)
    33                 {
    34                     respository = Activator.CreateInstance(type) as TRepository;
    35                     m_respository.Add(interfaceShortName, respository);
    36                 }
    37             }
    38             else
    39             {
    40                 respository = (TRepository)m_respository[interfaceShortName];
    41             }
    42 
    43             return respository;
    44         }
    45     }
    View Code

     5.工作单元

      由于需要同时操作几个仓储(同时更新订单状态,订单详细信息)要求操作结果一致。

          调用折注册---对象的用户必须记得注册到工作单元

          对象注册-----对象把自身注册到工作单元

          工作单元仓储接口

      主要定义仓储的3个基本操作签名

     1     /// <summary>
     2     /// 工作单元仓储接口
     3     /// </summary>
     4     public interface IUnitOfWorkRepository
     5     {
     6         /// <summary>
     7         /// 持久化新增实体
     8         /// </summary>
     9         /// <param name="item">待新增实体接口</param>
    10         void PersistNewItem(IEntity item);
    11 
    12         /// <summary>
    13         /// 持久化更新实体
    14         /// </summary>
    15         /// <param name="item">待更新实体接口</param>
    16         void PersistUpdatedItem(IEntity item);
    17 
    18         /// <summary>
    19         /// 持久化删除实体
    20         /// </summary>
    21         /// <param name="item">待删除实体接口</param>
    22         void PersistDeletedItem(IEntity item);
    23     }
    View Code

          工作单元接口

     1     /// <summary>
     2     /// InvokeMethod
     3     /// </summary>
     4     /// <param name="entity">
     5     /// The entity.
     6     /// </param>
     7     public delegate void InvokeMethod(IEntity entity);
     8 
     9     /// <summary>
    10     /// 工作单元接口
    11     /// </summary>
    12     public interface IUnitOfWork : IDisposable
    13     {
    14         /// <summary>
    15         ///  .NET Framework 数据提供程序
    16         /// </summary>
    17         IDbCommand Command { get; }
    18 
    19         /// <summary>
    20         /// 提交工作单元
    21         /// </summary>
    22         void Complete();
    23 
    24         /// <summary>
    25         /// 回滚工作单元
    26         /// </summary>
    27         void Rollback();
    28 
    29         /// <summary>
    30         /// 注册新增实体工作单元仓储接口
    31         /// </summary>
    32         /// <param name="entity">待新增实体接口</param>
    33         /// <param name="repository">工作单元仓储接口</param>
    34         void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository);
    35 
    36         /// <summary>
    37         /// 注册修改实体工作单元仓储接口
    38         /// </summary>
    39         /// <param name="entity">待修改实体接口</param>
    40         /// <param name="repository">工作单元仓储接口</param>
    41         void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository);
    42 
    43         /// <summary>
    44         /// 注册删除实体工作单元仓储接口
    45         /// </summary>
    46         /// <param name="entity">待删除实体接口</param>
    47         /// <param name="repository">工作单元仓储接口</param>
    48         void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository);
    49 
    50         /// <summary>
    51         /// 注册一个其他非基础的增删改工作单元仓储接口
    52         /// </summary>
    53         /// <param name="entity">待操作实体接口</param>
    54         /// <param name="methodName">自定义委托</param>
    55         void RegisterInvokeMethod(IEntity entity, InvokeMethod methodName);
    56 
    57         /// <summary>
    58         /// 注册一个非继承聚合根的其他非基础的增删改工作单元仓储接口 
    59         /// </summary>
    60         /// <param name="entity">待操作实体接口</param>
    61         /// <param name="methodName">Func委托</param>
    62         void RegisterInvokeMethod(object entity, Func<object, object> methodName);
    63     }
    View Code

          工作单元

      1     /// <summary>
      2     ///  工作单元
      3     /// </summary>
      4     public class UnitOfWork : IUnitOfWork
      5     {
      6         /// <summary>
      7         /// 新增实体工作单元
      8         /// </summary>
      9         private readonly Dictionary<IEntity, IUnitOfWorkRepository> m_addedEntities;
     10 
     11         /// <summary>
     12         /// 修改实体工作单元
     13         /// </summary>
     14         private readonly Dictionary<IEntity, IUnitOfWorkRepository> m_changedEntities;
     15 
     16         /// <summary>
     17         /// 删除实体工作单元
     18         /// </summary>
     19         private readonly Dictionary<IEntity, IUnitOfWorkRepository> m_deletedEntities;
     20 
     21         /// <summary>
     22         /// 其他非基础的增删改
     23         /// </summary>
     24         private readonly Dictionary<IEntity, InvokeMethod> m_invokeEntities;
     25 
     26         /// <summary>
     27         /// 非继承聚合根的其他非基础的增删改工作单元
     28         /// </summary>
     29         private readonly Dictionary<object, Func<object, object>> m_func;
     30 
     31         /// <summary>
     32         /// IDbConnection
     33         /// </summary>
     34         private IDbConnection m_connection;
     35 
     36         /// <summary>
     37         /// IDbCommand
     38         /// </summary>
     39         private IDbCommand m_command;
     40 
     41         /// <summary>
     42         /// IDbTransaction
     43         /// </summary>
     44         private IDbTransaction m_trans;
     45 
     46         /// <summary>
     47         /// Initializes a new instance of the <see cref="UnitOfWork"/> class.
     48         /// </summary>
     49         /// <param name="connectionSetting">
     50         /// The connection setting.
     51         /// </param>
     52         public UnitOfWork(string connectionSetting)
     53         {
     54             this.m_connection = DbFactories.GetConnection(connectionSetting);
     55             this.m_command = this.m_connection.CreateCommand();
     56             this.m_trans = this.m_connection.BeginTransaction();
     57             this.m_command.Transaction = this.m_trans;
     58             this.m_addedEntities = new Dictionary<IEntity, IUnitOfWorkRepository>();
     59             this.m_changedEntities = new Dictionary<IEntity, IUnitOfWorkRepository>();
     60             this.m_deletedEntities = new Dictionary<IEntity, IUnitOfWorkRepository>();
     61             this.m_invokeEntities = new Dictionary<IEntity, InvokeMethod>();
     62             this.m_func = new Dictionary<object, Func<object, object>>();
     63         }
     64 
     65         /// <summary>
     66         ///  .NET Framework 数据提供程序
     67         /// </summary>
     68         public IDbCommand Command
     69         {
     70             get
     71             {
     72                 return this.m_command;
     73             }
     74         }
     75 
     76         /// <summary>
     77         /// 提交工作单元
     78         /// </summary>
     79         public void Complete()
     80         {
     81             try
     82             {
     83                 foreach (IEntity entity in this.m_deletedEntities.Keys)
     84                 {
     85                     this.m_deletedEntities[entity].PersistDeletedItem(entity);
     86                 }
     87 
     88                 foreach (IEntity entity in this.m_addedEntities.Keys)
     89                 {
     90                     this.m_addedEntities[entity].PersistNewItem(entity);
     91                 }
     92 
     93                 foreach (IEntity entity in this.m_changedEntities.Keys)
     94                 {
     95                     this.m_changedEntities[entity].PersistUpdatedItem(entity);
     96                 }
     97 
     98                 foreach (IEntity entity in this.m_invokeEntities.Keys)
     99                 {
    100                     this.m_invokeEntities[entity](entity);
    101                 }
    102 
    103                 foreach (var entity in this.m_func)
    104                 {
    105                     entity.Value(entity.Key);
    106                 }
    107 
    108                 this.m_trans.Commit();
    109             }
    110             catch (Exception)
    111             {
    112                 this.Rollback();
    113             }
    114             finally
    115             {
    116                 this.Dispose();
    117                 this.Clear();
    118             }
    119         }
    120 
    121         /// <summary>
    122         /// 回滚工作单元
    123         /// </summary>
    124         public void Rollback()
    125         {
    126             this.m_trans.Rollback();
    127         }
    128 
    129         /// <summary>
    130         /// 注册新增实体工作单元仓储接口
    131         /// </summary>
    132         /// <param name="entity">待新增实体接口</param>
    133         /// <param name="repository">工作单元仓储接口</param>
    134         public void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository)
    135         {
    136             this.m_addedEntities.Add(entity, repository);
    137         }
    138 
    139         /// <summary>
    140         /// 注册修改实体工作单元仓储接口
    141         /// </summary>
    142         /// <param name="entity">待修改实体接口</param>
    143         /// <param name="repository">工作单元仓储接口</param>
    144         public void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository)
    145         {
    146             this.m_changedEntities.Add(entity, repository);
    147         }
    148 
    149         /// <summary>
    150         /// 注册删除实体工作单元仓储接口
    151         /// </summary>
    152         /// <param name="entity">待删除实体接口</param>
    153         /// <param name="repository">工作单元仓储接口</param>
    154         public void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository)
    155         {
    156             this.m_deletedEntities.Add(entity, repository);
    157         }
    158 
    159         /// <summary>
    160         /// 注册一个其他非基础的增删改工作单元仓储接口
    161         /// </summary>
    162         /// <param name="entity">待操作实体接口</param>
    163         /// <param name="methodName">自定义委托</param>
    164         public void RegisterInvokeMethod(IEntity entity, InvokeMethod methodName)
    165         {
    166             this.m_invokeEntities.Add(entity, methodName);
    167         }
    168 
    169         /// <summary>
    170         /// 注册一个非继承聚合根的其他非基础的增删改工作单元仓储接口 
    171         /// </summary>
    172         /// <param name="entity">待操作实体接口</param>
    173         /// <param name="methodName">Func委托</param>
    174         public void RegisterInvokeMethod(object entity, Func<object, object> methodName)
    175         {
    176             this.m_func.Add(entity, methodName);
    177         }
    178 
    179         /// <summary>
    180         /// 释放资源
    181         /// </summary>
    182         public void Dispose()
    183         {
    184             if (this.m_trans != null)
    185             {
    186                 this.m_trans.Dispose();
    187                 this.m_trans = null;
    188             }
    189 
    190             if (this.m_command != null)
    191             {
    192                 this.m_command.Dispose();
    193                 this.m_command = null;
    194             }
    195 
    196             if (this.m_connection != null)
    197             {
    198                 this.m_connection.Dispose();
    199                 this.m_connection.Close();
    200                 this.m_connection = null;
    201             }
    202         }
    203 
    204         /// <summary>
    205         /// 清除
    206         /// </summary>
    207         private void Clear()
    208         {
    209             this.m_addedEntities.Clear();
    210             this.m_changedEntities.Clear();
    211             this.m_deletedEntities.Clear();
    212             this.m_invokeEntities.Clear();
    213             this.m_func.Clear();
    214         }
    215     }
    View Code

     6.仓储基类

        主要是为了消除大量重复代码,仓储将从基类继承共同的代码,仓储基类会实现仓储接口IRepository<in TKey, TValue> 并且实现IUnitOfWorkRepository工作单元仓储接口

      1     /// <summary>
      2     /// The repository base.
      3     /// </summary>
      4     /// <typeparam name="TKey">
      5     /// </typeparam>
      6     /// <typeparam name="TValue">
      7     /// </typeparam>
      8     public abstract class RepositoryBase<TKey, TValue> : IRepository<TKey, TValue>, IUnitOfWorkRepository
      9         where TValue : EntityBase<TKey>
     10     {
     11         /// <summary>
     12         /// IUnitOfWork
     13         /// </summary>
     14         public IUnitOfWork UnitOfWork { get; private set; }
     15 
     16         /// <summary>
     17         /// Initializes a new instance of the <see cref="RepositoryBase{TKey,TValue}"/> class.
     18         /// </summary>
     19         protected RepositoryBase()
     20             : this(null)
     21         {
     22         }
     23 
     24         /// <summary>
     25         /// Initializes a new instance of the <see cref="RepositoryBase{TKey,TValue}"/> class.
     26         /// </summary>
     27         /// <param name="unitOfWork">
     28         /// The unit of work.
     29         /// </param>
     30         protected RepositoryBase(IUnitOfWork unitOfWork)
     31         {
     32             this.UnitOfWork = unitOfWork;
     33         }
     34 
     35         /// <summary>
     36         /// The find by.
     37         /// </summary>
     38         /// <param name="key">
     39         /// The key.
     40         /// </param>
     41         /// <returns>
     42         /// The <see cref="TValue"/>.
     43         /// </returns>
     44         public abstract TValue FindBy(TKey key);
     45 
     46         /// <summary>
     47         /// The add.
     48         /// </summary>
     49         /// <param name="item">
     50         /// The item.
     51         /// </param>
     52         public void Add(TValue item)
     53         {
     54             if (this.UnitOfWork != null)
     55             {
     56                 this.UnitOfWork.RegisterAdded(item, this);
     57             }
     58         }
     59 
     60         /// <summary>
     61         /// The this.
     62         /// </summary>
     63         /// <param name="key">
     64         /// The key.
     65         /// </param>
     66         /// <returns>
     67         /// The <see cref="TValue"/>.
     68         /// </returns>
     69         public TValue this[TKey key]
     70         {
     71             get
     72             {
     73                 return this.FindBy(key);
     74             }
     75 
     76             set
     77             {
     78                 if (this.FindBy(key) == null)
     79                 {
     80                     this.Add(value);
     81                 }
     82                 else
     83                 {
     84                     this.Update(value);
     85                 }
     86             }
     87         }
     88 
     89         /// <summary>
     90         /// The remove.
     91         /// </summary>
     92         /// <param name="item">
     93         /// The item.
     94         /// </param>
     95         public void Remove(TValue item)
     96         {
     97             if (this.UnitOfWork != null)
     98             {
     99                 this.UnitOfWork.RegisterRemoved(item, this);
    100             }
    101         }
    102 
    103         /// <summary>
    104         /// The update.
    105         /// </summary>
    106         /// <param name="item">
    107         /// The item.
    108         /// </param>
    109         public void Update(TValue item)
    110         {
    111             if (this.UnitOfWork != null)
    112             {
    113                 this.UnitOfWork.RegisterChanged(item, this);
    114             }
    115         }
    116 
    117         /// <summary>
    118         /// The persist new item.
    119         /// </summary>
    120         /// <param name="item">
    121         /// The item.
    122         /// </param>
    123         public abstract void PersistNewItem(IEntity item);
    124 
    125         /// <summary>
    126         /// The persist updated item.
    127         /// </summary>
    128         /// <param name="item">
    129         /// The item.
    130         /// </param>
    131         public abstract void PersistUpdatedItem(IEntity item);
    132 
    133         /// <summary>
    134         /// The persist deleted item.
    135         /// </summary>
    136         /// <param name="item">
    137         /// The item.
    138         /// </param>
    139         public abstract void PersistDeletedItem(IEntity item);
    140     }
    View Code

    7.SqlCe仓储基类

      主要是一些操作数据库的方法,这样避免了使用DBHelper类 

      1     /// <summary>
      2     /// The sql ce repository base.
      3     /// </summary>
      4     /// <typeparam name="TKey">
      5     /// </typeparam>
      6     /// <typeparam name="TValue">
      7     /// </typeparam>
      8     public abstract class SqlCeRepositoryBase<TKey, TValue> : RepositoryBase<TKey, TValue>, IDisposable
      9         where TValue : EntityBase<TKey>
     10     {
     11         /// <summary>
     12         /// The connection.
     13         /// </summary>
     14         protected IDbConnection Connection { get; private set; }
     15 
     16         /// <summary>
     17         /// The cmd.
     18         /// </summary>
     19         protected IDbCommand Command { get; private set; }
     20 
     21         /// <summary>
     22         /// Initializes a new instance of the <see cref="SqlCeRepositoryBase{TKey,TValue}"/> class.
     23         /// </summary>
     24         /// <param name="connectionSetting">
     25         /// The connection setting.
     26         /// </param>
     27         protected SqlCeRepositoryBase(string connectionSetting)
     28             : this(null, connectionSetting)
     29         {
     30         }
     31 
     32         /// <summary>
     33         /// Initializes a new instance of the <see cref="SqlCeRepositoryBase{TKey,TValue}"/> class.
     34         /// </summary>
     35         /// <param name="unitOfWork">
     36         /// The unit of work.
     37         /// </param>
     38         /// <param name="connectionSetting">
     39         /// The connection setting.
     40         /// </param>
     41         protected SqlCeRepositoryBase(IUnitOfWork unitOfWork, string connectionSetting)
     42             : base(unitOfWork)
     43         {
     44             if (UnitOfWork != null)
     45             {
     46                 this.Command = UnitOfWork.Command;
     47             }
     48             else
     49             {
     50                 if (this.Connection == null)
     51                 {
     52                     this.Connection = DbFactories.GetConnection(connectionSetting);
     53                 }
     54                 if (this.Connection.State != ConnectionState.Open)
     55                 {
     56                     this.Connection.Open();
     57                 }
     58                 this.Command = Connection.CreateCommand();
     59             }
     60         }
     61 
     62         #region Parameter
     63 
     64         /// <summary>
     65         /// The create parameter.
     66         /// </summary>
     67         /// <param name="name">
     68         /// The name.
     69         /// </param>
     70         /// <returns>
     71         /// The <see cref="IDbDataParameter"/>.
     72         /// </returns>
     73         private IDbDataParameter CreateParameter(string name)
     74         {
     75             IDbDataParameter param = this.Command.CreateParameter();
     76             param.ParameterName = name;
     77             return param;
     78         }
     79 
     80         /// <summary>
     81         /// The create parameter.
     82         /// </summary>
     83         /// <param name="name">
     84         /// The name.
     85         /// </param>
     86         /// <param name="value">
     87         /// The value.
     88         /// </param>
     89         /// <returns>
     90         /// The <see cref="IDbDataParameter"/>.
     91         /// </returns>
     92         private IDbDataParameter CreateParameter(string name, object value)
     93         {
     94             IDbDataParameter param = CreateParameter(name);
     95             param.Value = value ?? DBNull.Value;
     96             return param;
     97         }
     98 
     99         /// <summary>
    100         /// The create parameter.
    101         /// </summary>
    102         /// <param name="name">
    103         /// The name.
    104         /// </param>
    105         /// <param name="value">
    106         /// The value.
    107         /// </param>
    108         /// <param name="type">
    109         /// The type.
    110         /// </param>
    111         /// <returns>
    112         /// The <see cref="IDbDataParameter"/>.
    113         /// </returns>
    114         private IDbDataParameter CreateParameter(string name, object value, DbType type)
    115         {
    116             IDbDataParameter param = CreateParameter(name, value);
    117             param.DbType = type;
    118             return param;
    119         }
    120 
    121         /// <summary>
    122         /// The create parameter.
    123         /// </summary>
    124         /// <param name="name">
    125         /// The name.
    126         /// </param>
    127         /// <param name="value">
    128         /// The value.
    129         /// </param>
    130         /// <param name="type">
    131         /// The type.
    132         /// </param>
    133         /// <param name="direction">
    134         /// The direction.
    135         /// </param>
    136         /// <returns>
    137         /// The <see cref="IDbDataParameter"/>.
    138         /// </returns>
    139         private IDbDataParameter CreateParameter(string name, object value, DbType type, ParameterDirection direction)
    140         {
    141             IDbDataParameter param = CreateParameter(name, value, type);
    142             param.Direction = direction;
    143             return param;
    144         }
    145 
    146         /// <summary>
    147         /// The create parameter.
    148         /// </summary>
    149         /// <param name="name">
    150         /// The name.
    151         /// </param>
    152         /// <param name="value">
    153         /// The value.
    154         /// </param>
    155         /// <param name="type">
    156         /// The type.
    157         /// </param>
    158         /// <param name="direction">
    159         /// The direction.
    160         /// </param>
    161         /// <param name="size">
    162         /// The size.
    163         /// </param>
    164         /// <returns>
    165         /// The <see cref="IDbDataParameter"/>.
    166         /// </returns>
    167         private IDbDataParameter CreateParameter(string name, object value, DbType type, ParameterDirection direction, int size)
    168         {
    169             IDbDataParameter param = CreateParameter(name, value, type, direction);
    170             param.Size = size;
    171             return param;
    172         }
    173 
    174         /// <summary>
    175         /// The create parameter.
    176         /// </summary>
    177         /// <param name="name">
    178         /// The name.
    179         /// </param>
    180         /// <param name="value">
    181         /// The value.
    182         /// </param>
    183         /// <param name="type">
    184         /// The type.
    185         /// </param>
    186         /// <param name="direction">
    187         /// The direction.
    188         /// </param>
    189         /// <param name="size">
    190         /// The size.
    191         /// </param>
    192         /// <param name="scale">
    193         /// The scale.
    194         /// </param>
    195         /// <returns>
    196         /// The <see cref="IDbDataParameter"/>.
    197         /// </returns>
    198         private IDbDataParameter CreateParameter(string name, object value, DbType type, ParameterDirection direction, int size, byte scale)
    199         {
    200             IDbDataParameter param = CreateParameter(name, value, type, direction, size);
    201             param.Scale = scale;
    202             return param;
    203         }
    204 
    205         /// <summary>
    206         /// The add parameter.
    207         /// </summary>
    208         /// <param name="name">
    209         /// The name.
    210         /// </param>
    211         /// <returns>
    212         /// The <see cref="IDbDataParameter"/>.
    213         /// </returns>
    214         protected IDbDataParameter AddParameter(string name)
    215         {
    216             IDbDataParameter param = CreateParameter(name);
    217             this.Command.Parameters.Add(param);
    218             return param;
    219         }
    220 
    221         /// <summary>
    222         /// The add parameter.
    223         /// </summary>
    224         /// <param name="name">
    225         /// The name.
    226         /// </param>
    227         /// <param name="value">
    228         /// The value.
    229         /// </param>
    230         /// <returns>
    231         /// The <see cref="IDbDataParameter"/>.
    232         /// </returns>
    233         protected IDbDataParameter AddParameter(string name, object value)
    234         {
    235             IDbDataParameter param = CreateParameter(name, value);
    236             this.Command.Parameters.Add(param);
    237             return param;
    238         }
    239 
    240         /// <summary>
    241         /// The add parameter.
    242         /// </summary>
    243         /// <param name="name">
    244         /// The name.
    245         /// </param>
    246         /// <param name="value">
    247         /// The value.
    248         /// </param>
    249         /// <param name="type">
    250         /// The type.
    251         /// </param>
    252         /// <returns>
    253         /// The <see cref="IDbDataParameter"/>.
    254         /// </returns>
    255         protected IDbDataParameter AddParameter(string name, object value, DbType type)
    256         {
    257             IDbDataParameter param = CreateParameter(name, value, type);
    258             this.Command.Parameters.Add(param);
    259             return param;
    260         }
    261 
    262         /// <summary>
    263         /// The add parameter.
    264         /// </summary>
    265         /// <param name="name">
    266         /// The name.
    267         /// </param>
    268         /// <param name="value">
    269         /// The value.
    270         /// </param>
    271         /// <param name="type">
    272         /// The type.
    273         /// </param>
    274         /// <param name="direction">
    275         /// The direction.
    276         /// </param>
    277         /// <returns>
    278         /// The <see cref="IDbDataParameter"/>.
    279         /// </returns>
    280         protected IDbDataParameter AddParameter(string name, object value, DbType type, ParameterDirection direction)
    281         {
    282             IDbDataParameter param = CreateParameter(name, value, type, direction);
    283             this.Command.Parameters.Add(param);
    284             return param;
    285         }
    286 
    287         /// <summary>
    288         /// The add parameter.
    289         /// </summary>
    290         /// <param name="name">
    291         /// The name.
    292         /// </param>
    293         /// <param name="value">
    294         /// The value.
    295         /// </param>
    296         /// <param name="type">
    297         /// The type.
    298         /// </param>
    299         /// <param name="direction">
    300         /// The direction.
    301         /// </param>
    302         /// <param name="size">
    303         /// The size.
    304         /// </param>
    305         /// <returns>
    306         /// The <see cref="IDbDataParameter"/>.
    307         /// </returns>
    308         protected IDbDataParameter AddParameter(string name, object value, DbType type, ParameterDirection direction, int size)
    309         {
    310             IDbDataParameter param = CreateParameter(name, value, type, direction, size);
    311             this.Command.Parameters.Add(param);
    312             return param;
    313         }
    314 
    315         /// <summary>
    316         /// The add parameter.
    317         /// </summary>
    318         /// <param name="name">
    319         /// The name.
    320         /// </param>
    321         /// <param name="value">
    322         /// The value.
    323         /// </param>
    324         /// <param name="type">
    325         /// The type.
    326         /// </param>
    327         /// <param name="direction">
    328         /// The direction.
    329         /// </param>
    330         /// <param name="size">
    331         /// The size.
    332         /// </param>
    333         /// <param name="scale">
    334         /// The scale.
    335         /// </param>
    336         /// <returns>
    337         /// The <see cref="IDbDataParameter"/>.
    338         /// </returns>
    339         protected IDbDataParameter AddParameter(string name, object value, DbType type, ParameterDirection direction, int size, byte scale)
    340         {
    341             IDbDataParameter param = CreateParameter(name, value, type, direction, size, scale);
    342             this.Command.Parameters.Add(param);
    343             return param;
    344         }
    345 
    346         /// <summary>
    347         /// The clear parameters.
    348         /// </summary>
    349         protected void ClearParameters()
    350         {
    351             this.Command.Parameters.Clear();
    352         }
    353 
    354         #endregion
    355 
    356         #region  ExecuteReader
    357 
    358         /// <summary>
    359         /// The execute reader.
    360         /// </summary>
    361         /// <param name="sql">
    362         /// The sql.
    363         /// </param>
    364         /// <param name="type">
    365         /// The type.
    366         /// </param>
    367         /// <param name="behavior">
    368         /// The behavior.
    369         /// </param>
    370         /// <param name="timeout">
    371         /// The timeout.
    372         /// </param>
    373         /// <returns>
    374         /// The <see cref="IDataReader"/>.
    375         /// </returns>
    376         protected virtual IDataReader ExecuteReader(string sql, CommandType type, CommandBehavior behavior, int timeout)
    377         {
    378             if (string.IsNullOrWhiteSpace(sql))
    379             {
    380                 throw new ArgumentNullException("sql");
    381             }
    382             this.Command.CommandText = sql;
    383             this.Command.CommandType = type;
    384             this.Command.CommandTimeout = timeout;
    385             return this.Command.ExecuteReader(behavior);
    386         }
    387 
    388         /// <summary>
    389         /// The execute reader.
    390         /// </summary>
    391         /// <param name="sql">
    392         /// The sql.
    393         /// </param>
    394         /// <param name="type">
    395         /// The type.
    396         /// </param>
    397         /// <param name="behavior">
    398         /// The behavior.
    399         /// </param>
    400         /// <returns>
    401         /// The <see cref="IDataReader"/>.
    402         /// </returns>
    403         protected IDataReader ExecuteReader(string sql, CommandType type, CommandBehavior behavior)
    404         {
    405             return this.ExecuteReader(sql, type, behavior, 0);
    406         }
    407 
    408         /// <summary>
    409         /// The execute reader.
    410         /// </summary>
    411         /// <param name="sql">
    412         /// The sql.
    413         /// </param>
    414         /// <param name="type">
    415         /// The type.
    416         /// </param>
    417         /// <param name="timeout">
    418         /// The timeout.
    419         /// </param>
    420         /// <returns>
    421         /// The <see cref="IDataReader"/>.
    422         /// </returns>
    423         protected IDataReader ExecuteReader(string sql, CommandType type, int timeout)
    424         {
    425             return this.ExecuteReader(sql, type, CommandBehavior.Default, timeout);
    426         }
    427 
    428         /// <summary>
    429         /// The execute reader.
    430         /// </summary>
    431         /// <param name="sql">
    432         /// The sql.
    433         /// </param>
    434         /// <param name="type">
    435         /// The type.
    436         /// </param>
    437         /// <returns>
    438         /// The <see cref="IDataReader"/>.
    439         /// </returns>
    440         protected IDataReader ExecuteReader(string sql, CommandType type)
    441         {
    442             return this.ExecuteReader(sql, type, CommandBehavior.Default, 0);
    443         }
    444 
    445         /// <summary>
    446         /// The execute reader.
    447         /// </summary>
    448         /// <param name="sql">
    449         /// The sql.
    450         /// </param>
    451         /// <param name="behavior">
    452         /// The behavior.
    453         /// </param>
    454         /// <param name="timeout">
    455         /// The timeout.
    456         /// </param>
    457         /// <returns>
    458         /// The <see cref="IDataReader"/>.
    459         /// </returns>
    460         protected IDataReader ExecuteReader(string sql, CommandBehavior behavior, int timeout)
    461         {
    462             return this.ExecuteReader(sql, CommandType.Text, behavior, timeout);
    463         }
    464 
    465         /// <summary>
    466         /// The execute reader.
    467         /// </summary>
    468         /// <param name="sql">
    469         /// The sql.
    470         /// </param>
    471         /// <param name="behavior">
    472         /// The behavior.
    473         /// </param>
    474         /// <returns>
    475         /// The <see cref="IDataReader"/>.
    476         /// </returns>
    477         protected IDataReader ExecuteReader(string sql, CommandBehavior behavior)
    478         {
    479             return this.ExecuteReader(sql, CommandType.Text, behavior, 0);
    480         }
    481 
    482         /// <summary>
    483         /// The execute reader.
    484         /// </summary>
    485         /// <param name="sql">
    486         /// The sql.
    487         /// </param>
    488         /// <param name="timeout">
    489         /// The timeout.
    490         /// </param>
    491         /// <returns>
    492         /// The <see cref="IDataReader"/>.
    493         /// </returns>
    494         protected IDataReader ExecuteReader(string sql, int timeout)
    495         {
    496             return this.ExecuteReader(sql, CommandType.Text, CommandBehavior.Default, timeout);
    497         }
    498 
    499         /// <summary>
    500         /// The execute reader.
    501         /// </summary>
    502         /// <param name="sql">
    503         /// The sql.
    504         /// </param>
    505         /// <returns>
    506         /// The <see cref="IDataReader"/>.
    507         /// </returns>
    508         protected IDataReader ExecuteReader(string sql)
    509         {
    510             return this.ExecuteReader(sql, CommandType.Text, CommandBehavior.Default, 0);
    511         }
    512 
    513         #endregion
    514 
    515         #region ExecuteTable
    516 
    517         /// <summary>
    518         /// The execute table.
    519         /// </summary>
    520         /// <param name="sql">
    521         /// The sql.
    522         /// </param>
    523         /// <param name="type">
    524         /// The type.
    525         /// </param>
    526         /// <param name="behavior">
    527         /// The behavior.
    528         /// </param>
    529         /// <param name="timeout">
    530         /// The timeout.
    531         /// </param>
    532         /// <returns>
    533         /// The <see cref="DataTable"/>.
    534         /// </returns>
    535         protected virtual DataTable ExecuteTable(string sql, CommandType type, CommandBehavior behavior, int timeout)
    536         {
    537             using (IDataReader dr = ExecuteReader(sql, type, behavior, timeout))
    538             {
    539                 DataTable dt = new DataTable();
    540                 dt.Load(dr);
    541                 return dt;
    542             }
    543         }
    544 
    545         /// <summary>
    546         /// The execute table.
    547         /// </summary>
    548         /// <param name="sql">
    549         /// The sql.
    550         /// </param>
    551         /// <param name="type">
    552         /// The type.
    553         /// </param>
    554         /// <param name="behavior">
    555         /// The behavior.
    556         /// </param>
    557         /// <returns>
    558         /// The <see cref="DataTable"/>.
    559         /// </returns>
    560         protected DataTable ExecuteTable(string sql, CommandType type, CommandBehavior behavior)
    561         {
    562             return this.ExecuteTable(sql, type, behavior, 0);
    563         }
    564 
    565         /// <summary>
    566         /// The execute table.
    567         /// </summary>
    568         /// <param name="sql">
    569         /// The sql.
    570         /// </param>
    571         /// <param name="type">
    572         /// The type.
    573         /// </param>
    574         /// <param name="timeout">
    575         /// The timeout.
    576         /// </param>
    577         /// <returns>
    578         /// The <see cref="DataTable"/>.
    579         /// </returns>
    580         protected DataTable ExecuteTable(string sql, CommandType type, int timeout)
    581         {
    582             return this.ExecuteTable(sql, type, CommandBehavior.Default, timeout);
    583         }
    584 
    585         /// <summary>
    586         /// The execute table.
    587         /// </summary>
    588         /// <param name="sql">
    589         /// The sql.
    590         /// </param>
    591         /// <param name="type">
    592         /// The type.
    593         /// </param>
    594         /// <returns>
    595         /// The <see cref="DataTable"/>.
    596         /// </returns>
    597         protected DataTable ExecuteTable(string sql, CommandType type)
    598         {
    599             return this.ExecuteTable(sql, type, CommandBehavior.Default, 0);
    600         }
    601 
    602         /// <summary>
    603         /// The execute table.
    604         /// </summary>
    605         /// <param name="sql">
    606         /// The sql.
    607         /// </param>
    608         /// <param name="behavior">
    609         /// The behavior.
    610         /// </param>
    611         /// <param name="timeout">
    612         /// The timeout.
    613         /// </param>
    614         /// <returns>
    615         /// The <see cref="DataTable"/>.
    616         /// </returns>
    617         protected DataTable ExecuteTable(string sql, CommandBehavior behavior, int timeout)
    618         {
    619             return this.ExecuteTable(sql, CommandType.Text, behavior, timeout);
    620         }
    621 
    622         /// <summary>
    623         /// The execute table.
    624         /// </summary>
    625         /// <param name="sql">
    626         /// The sql.
    627         /// </param>
    628         /// <param name="behavior">
    629         /// The behavior.
    630         /// </param>
    631         /// <returns>
    632         /// The <see cref="DataTable"/>.
    633         /// </returns>
    634         protected DataTable ExecuteTable(string sql, CommandBehavior behavior)
    635         {
    636             return this.ExecuteTable(sql, CommandType.Text, behavior, 0);
    637         }
    638 
    639         /// <summary>
    640         /// The execute table.
    641         /// </summary>
    642         /// <param name="sql">
    643         /// The sql.
    644         /// </param>
    645         /// <param name="timeout">
    646         /// The timeout.
    647         /// </param>
    648         /// <returns>
    649         /// The <see cref="DataTable"/>.
    650         /// </returns>
    651         protected DataTable ExecuteTable(string sql, int timeout)
    652         {
    653             return this.ExecuteTable(sql, CommandType.Text, CommandBehavior.Default, timeout);
    654         }
    655 
    656         /// <summary>
    657         /// The execute table.
    658         /// </summary>
    659         /// <param name="sql">
    660         /// The sql.
    661         /// </param>
    662         /// <returns>
    663         /// The <see cref="DataTable"/>.
    664         /// </returns>
    665         protected DataTable ExecuteTable(string sql)
    666         {
    667             return this.ExecuteTable(sql, CommandType.Text, CommandBehavior.Default, 0);
    668         }
    669 
    670         #endregion
    671 
    672         #region ExecuteDataSet
    673 
    674         /// <summary>
    675         /// The execute data set.
    676         /// </summary>
    677         /// <param name="sql">
    678         /// The sql.
    679         /// </param>
    680         /// <param name="tableName">
    681         /// The table name.
    682         /// </param>
    683         /// <returns>
    684         /// The <see cref="DataSet"/>.
    685         /// </returns>
    686         public DataSet ExecuteDataSet(string sql, params string[] tableName)
    687         {
    688             return this.ExecuteDataSet(sql, CommandType.Text, tableName);
    689         }
    690 
    691         /// <summary>
    692         /// The execute data set.
    693         /// </summary>
    694         /// <param name="sql">
    695         /// The sql.
    696         /// </param>
    697         /// <param name="type">
    698         /// The type.
    699         /// </param>
    700         /// <param name="tableName">
    701         /// The table name.
    702         /// </param>
    703         /// <returns>
    704         /// The <see cref="DataSet"/>.
    705         /// </returns>
    706         public virtual DataSet ExecuteDataSet(string sql, CommandType type, params string[] tableName)
    707         {
    708             using (IDataReader dr = this.ExecuteReader(sql, type, CommandBehavior.Default, 0))
    709             {
    710                 DataSet ds = new DataSet();
    711                 ds.Load(dr, LoadOption.Upsert, tableName);
    712                 return ds;
    713             }
    714         }
    715 
    716         #endregion
    717 
    718         #region ExecuteScalar
    719 
    720         /// <summary>
    721         /// The execute scalar.
    722         /// </summary>
    723         /// <param name="sql">
    724         /// The sql.
    725         /// </param>
    726         /// <param name="type">
    727         /// The type.
    728         /// </param>
    729         /// <param name="timeout">
    730         /// The timeout.
    731         /// </param>
    732         /// <returns>
    733         /// The <see cref="object"/>.
    734         /// </returns>
    735         public virtual object ExecuteScalar(string sql, CommandType type, int timeout)
    736         {
    737             if (string.IsNullOrWhiteSpace(sql))
    738             {
    739                 throw new ArgumentNullException("sql");
    740             }
    741             this.Command.CommandText = sql;
    742             this.Command.CommandType = type;
    743             this.Command.CommandTimeout = timeout;
    744             return this.Command.ExecuteScalar();
    745         }
    746 
    747         /// <summary>
    748         /// The execute scalar.
    749         /// </summary>
    750         /// <param name="sql">
    751         /// The sql.
    752         /// </param>
    753         /// <param name="type">
    754         /// The type.
    755         /// </param>
    756         /// <returns>
    757         /// The <see cref="object"/>.
    758         /// </returns>
    759         public object ExecuteScalar(string sql, CommandType type)
    760         {
    761             return this.ExecuteScalar(sql, type, 0);
    762         }
    763 
    764         /// <summary>
    765         /// The execute scalar.
    766         /// </summary>
    767         /// <param name="sql">
    768         /// The sql.
    769         /// </param>
    770         /// <param name="timeout">
    771         /// The timeout.
    772         /// </param>
    773         /// <returns>
    774         /// The <see cref="object"/>.
    775         /// </returns>
    776         public object ExecuteScalar(string sql, int timeout)
    777         {
    778             return this.ExecuteScalar(sql, CommandType.Text, timeout);
    779         }
    780 
    781         /// <summary>
    782         /// The execute scalar.
    783         /// </summary>
    784         /// <param name="sql">
    785         /// The sql.
    786         /// </param>
    787         /// <returns>
    788         /// The <see cref="object"/>.
    789         /// </returns>
    790         public object ExecuteScalar(string sql)
    791         {
    792             return this.ExecuteScalar(sql, CommandType.Text, 0);
    793         }
    794 
    795         #endregion
    796 
    797         #region ExecuteNonQuery
    798 
    799         /// <summary>
    800         /// The execute non query.
    801         /// </summary>
    802         /// <param name="sql">
    803         /// The sql.
    804         /// </param>
    805         /// <param name="type">
    806         /// The type.
    807         /// </param>
    808         /// <param name="timeout">
    809         /// The timeout.
    810         /// </param>
    811         /// <returns>
    812         /// The <see cref="int"/>.
    813         /// </returns>
    814         public virtual int ExecuteNonQuery(string sql, CommandType type, int timeout)
    815         {
    816             if (string.IsNullOrWhiteSpace(sql))
    817             {
    818                 throw new ArgumentNullException("sql");
    819             }
    820             this.Command.CommandText = sql;
    821             this.Command.CommandType = type;
    822             this.Command.CommandTimeout = timeout;
    823             return this.Command.ExecuteNonQuery();
    824         }
    825 
    826         /// <summary>
    827         /// The execute non query.
    828         /// </summary>
    829         /// <param name="sql">
    830         /// The sql.
    831         /// </param>
    832         /// <param name="type">
    833         /// The type.
    834         /// </param>
    835         /// <returns>
    836         /// The <see cref="int"/>.
    837         /// </returns>
    838         public int ExecuteNonQuery(string sql, CommandType type)
    839         {
    840             return this.ExecuteNonQuery(sql, type, 0);
    841         }
    842 
    843         /// <summary>
    844         /// The execute non query.
    845         /// </summary>
    846         /// <param name="sql">
    847         /// The sql.
    848         /// </param>
    849         /// <param name="timeout">
    850         /// The timeout.
    851         /// </param>
    852         /// <returns>
    853         /// The <see cref="int"/>.
    854         /// </returns>
    855         public int ExecuteNonQuery(string sql, int timeout)
    856         {
    857             return this.ExecuteNonQuery(sql, CommandType.Text, timeout);
    858         }
    859 
    860         /// <summary>
    861         /// The execute non query.
    862         /// </summary>
    863         /// <param name="sql">
    864         /// The sql.
    865         /// </param>
    866         /// <returns>
    867         /// The <see cref="int"/>.
    868         /// </returns>
    869         public int ExecuteNonQuery(string sql)
    870         {
    871             return this.ExecuteNonQuery(sql, CommandType.Text, 0);
    872         }
    873 
    874         #endregion
    875 
    876         /// <summary>
    877         /// The dispose.
    878         /// </summary>
    879         public void Dispose()
    880         {
    881             if (this.Command != null)
    882             {
    883                 this.Command.Dispose();
    884                 this.Command = null;
    885             }
    886 
    887             if (this.Connection == null)
    888             {
    889                 return;
    890             }
    891 
    892             if (this.Connection.State == ConnectionState.Open)
    893             {
    894                 this.Connection.Close();
    895             }
    896 
    897             this.Connection.Dispose();
    898             this.Connection = null;
    899         }
    900     }
    View Code

    8.Sql仓储基类

        主要是加载有子对象的跟定义实体对象接口

      1     /// <summary>
      2     /// The sql repository base.
      3     /// </summary>
      4     /// <typeparam name="TKey">
      5     /// </typeparam>
      6     /// <typeparam name="TValue">
      7     /// </typeparam>
      8     public abstract class SqlRepositoryBase<TKey, TValue> : SqlCeRepositoryBase<TKey, TValue>
      9         where TValue : EntityBase<TKey>
     10     {
     11         /// <summary>
     12         /// 有子对象的回调委托
     13         /// </summary>
     14         /// <param name="entityAggregate">实体聚合根</param>
     15         /// <param name="childEntityKeyValue">子实体键</param>
     16         public delegate void AppendChildData(TValue entityAggregate, object childEntityKeyValue);
     17 
     18         /// <summary>
     19         /// 实体工厂
     20         /// </summary>
     21         private readonly IEntityFactory<TValue> m_entityFactory;
     22 
     23         /// <summary>
     24         /// 子对象集
     25         /// </summary>
     26         private readonly Dictionary<string, AppendChildData> m_childCallbacks;
     27 
     28         /// <summary>
     29         /// The m_child key datas.
     30         /// </summary>
     31         private readonly Dictionary<string, object> m_childKeyDatas;
     32 
     33         /// <summary>
     34         /// Initializes a new instance of the <see cref="SqlRepositoryBase{TKey,TValue}"/> class.
     35         /// </summary>
     36         /// <param name="connectionSetting">
     37         /// The connection setting.
     38         /// </param>
     39         protected SqlRepositoryBase(string connectionSetting)
     40             : base(connectionSetting)
     41         {
     42         }
     43 
     44         /// <summary>
     45         /// Initializes a new instance of the <see cref="SqlRepositoryBase{TKey,TValue}"/> class.
     46         /// </summary>
     47         /// <param name="unitOfWork">
     48         /// The unit of work.
     49         /// </param>
     50         /// <param name="connectionSetting">
     51         /// The connection setting.
     52         /// </param>
     53         protected SqlRepositoryBase(IUnitOfWork unitOfWork, string connectionSetting)
     54             : base(unitOfWork, connectionSetting)
     55         {
     56             this.m_entityFactory = this.BuildEntityFactory();
     57             this.m_childCallbacks = new Dictionary<string, AppendChildData>();
     58             this.m_childKeyDatas = new Dictionary<string, object>();
     59             this.BuildChildCallbacks(this.m_childCallbacks);
     60         }
     61 
     62         /// <summary>
     63         /// 改为由子类创建实体,不使用工厂
     64         /// </summary>
     65         /// <returns>TValue</returns>
     66         protected abstract IEntityFactory<TValue> BuildEntityFactory();
     67 
     68         /// <summary>
     69         /// 创建子对象回调
     70         /// </summary>
     71         /// <param name="childCallbacks">子对象集</param>
     72         protected abstract void BuildChildCallbacks(Dictionary<string, AppendChildData> childCallbacks);
     73 
     74         /// <summary>
     75         /// 子对象回调集
     76         /// </summary>
     77         protected Dictionary<string, AppendChildData> ChildCallbacks
     78         {
     79             get
     80             {
     81                 return this.m_childCallbacks;
     82             }
     83         }
     84 
     85         /// <summary>
     86         /// The build entity from reader.
     87         /// </summary>
     88         /// <param name="reader">
     89         /// The reader.
     90         /// </param>
     91         /// <returns>
     92         /// The <see cref="TValue"/>.
     93         /// </returns>
     94         protected virtual TValue BuildEntityFromReader(IDataReader reader)
     95         {
     96             TValue entity = this.m_entityFactory.BuildEntity(reader);
     97             if (this.m_childCallbacks != null && this.m_childCallbacks.Count > 0)
     98             {
     99                 DataTable columnData = reader.GetSchemaTable();
    100                 foreach (string childKeyName in this.m_childCallbacks.Keys)
    101                 {
    102                     object childKeyValue;
    103                     ////判断 DataReader 的数据集合中是否存在一个特定的列名(或字段名)
    104                     if (columnData != null && columnData.Rows.Cast<DataRow>().Any(row => row["ColumnName"].ToString() == childKeyName))
    105                     {
    106                         childKeyValue = reader[childKeyName];
    107                     }
    108                     else
    109                     {
    110                         childKeyValue = null;
    111                     }
    112                     if (m_childKeyDatas.ContainsKey(childKeyName))
    113                     {
    114                         m_childKeyDatas[childKeyName] = childKeyValue;
    115                     }
    116                     else
    117                     {
    118                         m_childKeyDatas.Add(childKeyName, childKeyValue);
    119                     }
    120                 }
    121             }
    122             return entity;
    123         }
    124 
    125         /// <summary>
    126         /// The build entity from sql.
    127         /// </summary>
    128         /// <param name="sql">
    129         /// The sql.
    130         /// </param>
    131         /// <returns>
    132         /// The <see cref="TValue"/>.
    133         /// </returns>
    134         protected virtual TValue BuildEntityFromSql(string sql)
    135         {
    136             TValue entity = default(TValue);
    137             using (IDataReader reader = this.ExecuteReader(sql))
    138             {
    139                 if (reader.Read())
    140                 {
    141                     entity = this.BuildEntityFromReader(reader);
    142                 }
    143             }
    144             if (entity != null)
    145             {
    146                 this.InvokeChildCallbacks(entity);
    147             }
    148             return entity;
    149         }
    150 
    151         /// <summary>
    152         /// The build entities from sql.
    153         /// </summary>
    154         /// <param name="sql">
    155         /// The sql.
    156         /// </param>
    157         /// <returns>
    158         /// The 
    159         /// </returns>
    160         protected virtual List<TValue> BuildEntitiesFromSql(string sql)
    161         {
    162             List<TValue> entities = new List<TValue>();
    163             using (IDataReader reader = this.ExecuteReader(sql))
    164             {
    165                 while (reader.Read())
    166                 {
    167                     entities.Add(this.BuildEntityFromReader(reader));
    168                 }
    169             }
    170             return entities;
    171         }
    172 
    173         /// <summary>
    174         /// The invoke child callbacks.
    175         /// </summary>
    176         /// <param name="entity">
    177         /// The entity.
    178         /// </param>
    179         private void InvokeChildCallbacks(TValue entity)
    180         {
    181             if (this.m_childCallbacks != null && this.m_childCallbacks.Any())
    182             {
    183                 foreach (string childKeyName in this.m_childKeyDatas.Keys)
    184                 {
    185                     object childKeyValue;
    186                     this.m_childKeyDatas.TryGetValue(childKeyName, out childKeyValue);
    187                     this.m_childCallbacks[childKeyName](entity, childKeyValue);
    188                 }
    189             }
    190         }
    191     }
    View Code

     

    领域层

    1.分析业务需求,

      假如我现在需要做一个平台的虚拟支付的功能(类似支付宝支付)

      业务功能分析

      1.开户功能

      2.支付功能

      3.转账功能

      4.冻结解冻功能

    2.结构设计

        账户类图 Account账户类   Encrypted密保类 密保类又分手机邮箱。   账户类是继承EntityBase类的这样就抽象出他是一个聚合边界,从而对他抽象出仓储(仓储说白了就是保存到数据库的行为)

        下面贴出仓储实现类的类图 ,AccountRepository 仓储类继承SqlRepositoryBase 并且继承仓储接口IAccountRepository 看他的方法主要实现了SqlRepositoryBase 的一些抽象方法而

        仓储接口则是为空接口,这样做是为了方便后面扩展。

    3.分析Account的职责

      账户类型的一些基本职责跟行为

      账户的职责就是拥有用户的基本新跟账户金额等等一些属性。

          账户的基本行为:

          1.登录

        登录的时候需要验证账户状态是否可登录,等等一些信息

     1         public void Login(string accountName, string loginPassWord)
     2         {
     3             this.ValidateEmpty();
     4             this.ValidateLoginStatus();
     5             if (this.AccountName != accountName)
     6             {
     7                 throw new ArgumentException("抱歉!账户名错误");
     8             }
     9 
    10             if (this.LoginPassWord != loginPassWord)
    11             {
    12                 throw new ArgumentException("抱歉!账户登录密码错误");
    13             }
    14         }
    View Code

          2.存款

        存款其实也很简单只需要往账户余额上加钱就完事了

    1         public void Deposit(decimal depositAmount)
    2         {
    3             this.Balance += depositAmount;
    4             this.AvailableBalance += depositAmount;
    5         }
    View Code

      3.取款

        取款跟存款就相反了但是要注意一点就是需要验证余额是否充足

    1         public void Withdraw(decimal withdrawAmout)
    2         {
    3             this.ValudateAvailableBalance(withdrawAmout);
    4             this.Balance -= withdrawAmout;
    5             this.AvailableBalance -= withdrawAmout;
    6         }
    View Code

      5.冻结

        冻结也跟取款类似

    1         public void Freeze(decimal freezeAmount)
    2         {
    3             this.ValudateAvailableBalance(freezeAmount);
    4             this.FreezeAmount += freezeAmount;
    5             this.AvailableBalance -= freezeAmount;
    6         }
    View Code

      6.解冻

        解冻就跟冻结相反需要注意的就是验证可解冻金额范围

    1         public void UnFreeze(decimal unFreezeAmount)
    2         {
    3             this.ValudateFreezeAmount(unFreezeAmount);
    4             this.FreezeAmount -= unFreezeAmount;
    5             this.AvailableBalance += unFreezeAmount;
    6         }
    View Code

      7.修改交易密码

    1         public void UpdatePayPassWord(string payPassWord)
    2         {
    3             this.PayPassWord = payPassWord;
    4         }
    View Code

      8.修改登录密码

    1         public void UpdateLoginPassWord(string loginPassWord)
    2         {
    3             this.LoginPassWord = loginPassWord;
    4         }
    View Code

     4.AccountRepository实现的基本方法

      主要是实现Account实体对象的 增删查改4个基本方法另外还有2个多的方法

      BuildEntityFactory:用来创建读取IDataReader对象的接口

        该方法返回一个IEntityFactory<Account>类型

        这里只需要新建一个类AccountFactory实现IEntityFactory<out, T>接口即可

     1     /// <summary>
     2     /// The account factory.
     3     /// </summary>
     4     public class AccountFactory : IEntityFactory<Account>
     5     {
     6         /// <summary>
     7         /// 把IDataReader对象解析成Account对象
     8         /// </summary>
     9         /// <param name="reader">
    10         /// The reader.
    11         /// </param>
    12         /// <returns>
    13         /// The <see cref="Account"/>.
    14         /// </returns>
    15         public Account BuildEntity(IDataReader reader)
    16         {
    17             Account account = new Account(Guid.Parse(reader[FieldNames.AccountID].ToString()));
    18             return account;
    19         }
    20 
    21         /// <summary>
    22         /// 把DataSet对象解析成Account对象
    23         /// </summary>
    24         /// <param name="table">
    25         /// The table.
    26         /// </param>
    27         /// <returns>
    28         /// The <see cref="Account"/>.
    29         /// </returns>
    30         public Account BuildEntity(DataSet table)
    31         {
    32             throw new NotImplementedException();
    33         }
    34 
    35         /// <summary>
    36         /// 映射数据库字段名称
    37         /// </summary>
    38         public static class FieldNames
    39         {
    40             /// <summary>
    41             /// 表名 Account
    42             /// </summary>
    43             public const string Account = "Account";
    44 
    45             /// <summary>
    46             /// 主键 AccountID
    47             /// </summary>
    48             public const string AccountID = "AccountID";
    49         }
    50     }
    View Code
    1         protected override IEntityFactory<Account> BuildEntityFactory()
    2         {
    3             return new AccountFactory();
    4         }
    View Code    

      BuildChildCallbacks:有来加载Acount的外键实体对象

        因为Account对象的属性Encrypted密保对象数据保存在其他的表所以这里就把他当成子对象来加载

     1         /// <summary>
     2         /// The build child callbacks.
     3         /// </summary>
     4         /// <param name="childCallbacks">
     5         /// The child callbacks.
     6         /// </param>
     7         protected override void BuildChildCallbacks(Dictionary<string, AppendChildData> childCallbacks)
     8         {
     9             // 主要实现加载密保的方法
    10             childCallbacks.Add(
    11                 AccountFactory.FieldNames.AccountID,
    12                 (a, b) =>
    13                     {
    14                         // 此处调用加载密保的方法
    15                         a.Encrypted = null;
    16                     });
    17         }
    View Code

      下面贴出增删查改的方法 只实现了增加的方法做为实例

     1         /// <summary>
     2         /// 查询
     3         /// </summary>
     4         /// <param name="key">
     5         /// The key.
     6         /// </param>
     7         /// <returns>
     8         /// The <see cref="Account"/>.
     9         /// </returns>
    10         public override Account FindBy(Guid key)
    11         {
    12             throw new NotImplementedException();
    13         }
    14 
    15         /// <summary>
    16         /// 增加
    17         /// </summary>
    18         /// <param name="item">
    19         /// The item.
    20         /// </param>
    21         public override void PersistNewItem(IEntity item)
    22         {
    23             // 因为Account是继承自IEntity接口这里直接把item转化成Account类型即可
    24             Account account = (Account)item;
    25             StringBuilder sql = new StringBuilder();
    26             sql.AppendFormat(" INSERT INTO {0}", AccountFactory.FieldNames.Account);
    27             sql.Append(" ( ");
    28             sql.AppendFormat("{0}", AccountFactory.FieldNames.AccountID);
    29             sql.Append(" ) VALUES ( ");
    30             sql.AppendFormat("@{0}", AccountFactory.FieldNames.AccountID);
    31             sql.Append(");");
    32 
    33             // 调用父亲类方法实现参数化添加参数
    34             // 调用支持先清除一下这是必须的
    35             this.ClearParameters();
    36             this.AddParameter("@" + AccountFactory.FieldNames.AccountID, account.Key);
    37 
    38             // 执行sql语句
    39             this.ExecuteNonQuery(sql.ToString());
    40         }
    41 
    42         /// <summary>
    43         /// 修改
    44         /// </summary>
    45         /// <param name="item">
    46         /// The item.
    47         /// </param>
    48         public override void PersistUpdatedItem(IEntity item)
    49         {
    50             throw new NotImplementedException();
    51         }
    52 
    53         /// <summary>
    54         /// 删除
    55         /// </summary>
    56         /// <param name="item">
    57         /// The item.
    58         /// </param>
    59         public override void PersistDeletedItem(IEntity item)
    60         {
    61             throw new NotImplementedException();
    62         }
    View Code

     5.现在来实现开户功能

      领域结构大致已经说完 现在来说最关心的业务了 第一个业务就是开户了

      现在我们需要一个服务类AccountService(这个类的方法基本为静态方法 主要是把各个领域的领域逻辑组织起来现成连贯的业务逻辑) 

      现在先定义一个方法签名 public static void Register(AccountDTO accountDTO)开户的方法签名

      AccountDTO  这个参数实际就是一个传输对象单独封装在一个程序集里面

      他的属性主要就是开户的时候录入用户填写的一些信息

     1     /// <summary>
     2     /// 账户传输对象
     3     /// </summary>
     4     public class AccountDTO
     5     {
     6         /// <summary>
     7         /// 账户名
     8         /// </summary>
     9         public string AccountName { get; set; }
    10 
    11         /// <summary>
    12         /// 昵称
    13         /// </summary>
    14         public string Nickname { get; set; }
    15 
    16         /// <summary>
    17         /// 登录密码
    18         /// </summary>
    19         public string LoginPassWord { get; set; }
    20 
    21         /// <summary>
    22         /// 交易密码
    23         /// </summary>
    24         public string PayPassWord { get; set; }
    25 
    26         /// <summary>
    27         /// 邮箱
    28         /// </summary>
    29         public string Emial { get; set; }
    30 
    31         /// <summary>
    32         /// 手机
    33         /// </summary>
    34         public string Phone { get; set; }
    35 
    36         /// <summary>
    37         /// 备注
    38         /// </summary>
    39         public string Remark { get; set; }
    40     }
    View Code

        下一下步就是要把AccountDTO传输对象转化成Account领域对象

      转化的时候我们就需要一个工厂类来创建 

     1     /// <summary>
     2     /// Builder
     3     /// </summary>
     4     public class Builder
     5     {
     6         /// <summary>
     7         /// 创建Account
     8         /// </summary>
     9         /// <param name="accountDTO">accountDTO</param>
    10         /// <returns>Account</returns>
    11         internal static Account BuilderAccount(AccountDTO accountDTO)
    12         {
    13             Account account = new Account
    14             {
    15                 AccountStatus = AccountStatus.Normal,
    16                 Balance = 0M,
    17                 AvailableBalance = 0M,
    18                 FreezeAmount = 0M,
    19                 Encrypted = null,
    20                 AccountName = accountDTO.AccountName,
    21                 Nickname = accountDTO.Nickname,
    22                 LoginPassWord = accountDTO.LoginPassWord,
    23                 PayPassWord = accountDTO.PayPassWord,
    24                 Remark = accountDTO.Remark
    25             };
    26 
    27             return account;
    28         }
    29     }
    View Code

     拿到Account对对象因为没有什么逻辑 就直接持久化到数据库了

     这时候只需要通过IAccountRepository的Add方法把数据插入到数据库即可

     IAccountRepository接口我们通过工厂方法创建

     1         /// <summary>
     2         /// The create i account repository.
     3         /// </summary>
     4         /// <returns>
     5         /// The <see cref="IAccountRepository"/>.
     6         /// </returns>
     7         internal static IAccountRepository CreateIAccountRepository()
     8         {
     9             return new AccountRepository(ConnectionString.Account);
    10         }
    View Code
     1     /// <summary>
     2     /// The connection string.
     3     /// </summary>
     4     public static class ConnectionString
     5     {
     6         /// <summary>
     7         /// The account.
     8         /// </summary>
     9         public const string Account = "Account";
    10     }
    View Code

      最后贴出开户的全部代码

    1         public static void Register(AccountDTO accountDTO)
    2         {
    3             Account.Account account = Account.Builder.BuilderAccount(accountDTO);
    4             using (IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository())
    5             {
    6                 accountRepository.Add(account);
    7             }
    8         }
    View Code

     6.既然用了账户当然我们就可以支付了

      现在开始来实现支付,其实支付就是一种交易 既然交易肯定有买家,卖家这时候就抽象一个交易类来咯

      Tread(交易类)

     1     /// <summary>
     2     /// 交易
     3     /// </summary>
     4     public class Trade : EntityBase<Guid>
     5     {
     6           /// <summary>
     7         /// Initializes a new instance of the <see cref="Trade"/> class.
     8         /// </summary>
     9         public Trade()
    10             : base(Guid.NewGuid())
    11         {
    12         }
    13 
    14         /// <summary>
    15         /// Initializes a new instance of the <see cref="Trade"/> class.
    16         /// </summary>
    17         /// <param name="accountID">
    18         /// The account id.
    19         /// </param>
    20         public Trade(Guid accountID)
    21             : base(accountID)
    22         {
    23         }
    24 
    25         /// <summary>
    26         /// 买家
    27         /// </summary>
    28         public Account Buyer { get; set; }
    29 
    30         /// <summary>
    31         /// 卖家
    32         /// </summary>
    33         public Account Seller { get; set; }
    34     }
    View Code

         现在我们需要的是支付交易只需要再新建一个支付类就可以了

       这个类主要包括支付的一些信息

     1     /// <summary>
     2     /// 支付
     3     /// </summary>
     4     public class PayOrder : Trade
     5     {
     6         /// <summary>
     7         /// 支付状态
     8         /// </summary>
     9         public PayStatus PayStatus { get; set; }
    10 
    11         /// <summary>
    12         /// 支付金额
    13         /// </summary>
    14         public decimal PayAmount { get; set; }
    15 
    16         /// <summary>
    17         /// 支付订单号
    18         /// </summary>
    19         public string PayOrderNumber { get; set; }
    20 
    21         /// <summary>
    22         /// 创建时间
    23         /// </summary>
    24         public DateTime CreateDateTime { get; set; }
    25 
    26         /// <summary>
    27         /// 支付时间
    28         /// </summary>
    29         public DateTime? PayDateTime { get; set; }
    30 
    31         /// <summary>
    32         /// 备注
    33         /// </summary>
    34         public string Remark { get; set; }
    35 
    36         /// <summary>
    37         /// 支付
    38         /// </summary>
    39         /// <returns>生成账单</returns>
    40         public List<Bill> Pay()
    41         {
    42             AccountService.AccountTransfer(this.Buyer, this.Seller, this.PayAmount);
    43             return null;
    44         }
    45     }
    View Code

        需要注意的是这个类里面包括了一个支付的方法 这个方法返回支付的账单信息集合

     1     /// <summary>
     2     /// 账单
     3     /// </summary>
     4     public class Bill : EntityBase<Guid>
     5     {
     6         /// <summary>
     7         /// 交易金额
     8         /// </summary>
     9         public decimal TradeAmount { get; set; }
    10 
    11         /// <summary>
    12         /// 账单流水号
    13         /// </summary>
    14         public string OrderNumber { get; set; }
    15 
    16         /// <summary>
    17         /// 交易类型
    18         /// </summary>
    19         public string TraderType { get; set; }
    20 
    21         /// <summary>
    22         /// 交易备注
    23         /// </summary>
    24         public string TradeRemark { get; set; }
    25 
    26         /// <summary>
    27         /// 交易时间
    28         /// </summary>
    29         public DateTime TradeDateTime { get; set; }
    30 
    31         /// <summary>
    32         /// 交易号
    33         /// </summary>
    34         public string TradeOrderNumber { get; set; }
    35 
    36         /// <summary>
    37         /// 交易账户
    38         /// </summary>
    39         public Account Account { get; set; }
    40 
    41         /// <summary>
    42         /// 交易对方账户
    43         /// </summary>
    44         public Account ToAccount { get; set; }
    45     }
    View Code

        这样一来只需要把业务组织起来就可以完成支付了

        还是跟开户一样先给支付服务的方法签名 public static void Pay(PayDTO payDTO)

      PayDTO传输对象没有什么好说的

     1     /// <summary>
     2     /// 支付传送对象
     3     /// </summary>
     4     public class PayDTO
     5     {
     6         /// <summary>
     7         /// 支付账号
     8         /// </summary>
     9         public string PayAccountNO { get; set; }
    10 
    11         /// <summary>
    12         /// 支付金额
    13         /// </summary>
    14         public decimal PayAmount { get; set; }
    15 
    16         /// <summary>
    17         /// 交易密码
    18         /// </summary>
    19         public string PayPassWord { get; set; }
    20 
    21         /// <summary>
    22         /// 交易备注
    23         /// </summary>
    24         public string Remark { get; set; }
    25     }
    View Code

       1.验证支付信息就没有什么好说的了

     2.根据支付账号加载支付账户 

     3.根据配置加载收款账户

       4.创建支付订单

       5.调用支付方法并且生成账单 

     1         /// <summary>
     2         /// 支付
     3         /// </summary>
     4         /// <param name="payDTO">支付信息</param>
     5         public static void Pay(PayDTO payDTO)
     6         {
     7             // 1 校验基本信息
     8             payDTO.ValidatePayDTO();
     9 
    10             // 2 加载账户
    11             // 支付账户
    12             Account.Account payAccount = QueryByAccountName(payDTO.PayAccountNO);
    13 
    14             // 收款账户
    15             Account.Account sellerAccount = QueryBySeller();
    16 
    17             // 3 校验交易密码
    18             payAccount.ValidatePayPassWord(payDTO.PayPassWord);
    19 
    20             // 4 创建支付订单
    21             PayOrder payOrder = Builder.BuilderPayOrder(payAccount, sellerAccount, payDTO);
    22 
    23             // 同步处理为支付成功
    24             payOrder.PaySucess();
    25 
    26             // 5 调用支付方法
    27             List<Bill> bills = payOrder.Pay();
    28 
    29             // 6 持久化数据(开启工作单元;开启数据库事务)
    30             using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
    31             {
    32                 // 更新账户余额
    33                 IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
    34                 accountRepository.Update(payAccount);
    35                 accountRepository.Update(sellerAccount);
    36 
    37                 // 生成订单
    38                 IPayOrderRepository payOrderRepository = Account.Factory.AccountFactory.CreateIPayOrderRepository(unitOfWork);
    39                 payOrderRepository.Add(payOrder);
    40 
    41                 // 生成账单
    42                 IBillRepository billRepository = Account.Factory.AccountFactory.CreateIBillRepository(unitOfWork);
    43                 billRepository.Add(bills);
    44 
    45                 // 提交工作单元(提交事务,失败自动回滚)
    46                 unitOfWork.Complete();
    47             }
    48         }
    View Code

     7.转账

      转账也是一种交易跟支付差不多 转账也需要继承至Trade交易类,因为转账属性正向业务,所以抽象一层ForwardTrade正向交易类

     1     /// <summary>
     2     /// 正向交易
     3     /// </summary>
     4     public class ForwardTrade : Trade
     5     {
     6         /// <summary>
     7         /// Initializes a new instance of the <see cref="ForwardTrade"/> class.
     8         /// </summary>
     9         public ForwardTrade()
    10         {
    11             this.TradeOrderNumber = Builder.BuilderOrderNumber();
    12         }
    13 
    14         /// <summary>
    15         /// Initializes a new instance of the <see cref="ForwardTrade"/> class.
    16         /// </summary>
    17         /// <param name="tradeID">
    18         /// The pay order id.
    19         /// </param>
    20         public ForwardTrade(Guid tradeID)
    21             : base(tradeID)
    22         {
    23         }
    24 
    25         /// <summary>
    26         /// 交易金额
    27         /// </summary>
    28         public decimal TradeAmount { get; set; }
    29 
    30         /// <summary>
    31         /// 交易订单号
    32         /// </summary>
    33         public string TradeOrderNumber { get; set; }
    34 
    35         /// <summary>
    36         /// 创建时间
    37         /// </summary>
    38         public DateTime CreateDateTime { get; set; }
    39 
    40         /// <summary>
    41         /// 支付时间
    42         /// </summary>
    43         public DateTime? TradeDateTime { get; set; }
    44 
    45         /// <summary>
    46         /// 备注
    47         /// </summary>
    48         public string Remark { get; set; }
    49 
    50         /// <summary>
    51         /// 更新交易时间
    52         /// </summary>
    53         /// <param name="tradeDateTime">交易时间</param>
    54         public void UpdateTradeDateTime(DateTime tradeDateTime)
    55         {
    56             this.TradeDateTime = tradeDateTime;
    57         }
    58 
    59         /// <summary>
    60         /// 交易
    61         /// </summary>
    62         /// <returns>生成账单</returns>
    63         public List<TradeBill> Trade()
    64         {
    65             AccountService.AccountTransfer(this.Buyer, this.Seller, this.TradeAmount);
    66             List<TradeBill> result = new List<TradeBill>
    67                                     {
    68                                         this.CreateBill(this.Buyer, this.Seller, TraderType.Out),
    69                                         this.CreateBill(this.Seller, this.Buyer, TraderType.In)
    70                                     };
    71             return result;
    72         }
    73 
    74         /// <summary>
    75         /// 创建账单
    76         /// </summary>
    77         /// <param name="account">交易账户</param>
    78         /// <param name="toAccount">交易对方账户</param>
    79         /// <param name="traderType">交易类型</param>
    80         /// <returns></returns>
    81         private TradeBill CreateBill(Account account, Account toAccount, TraderType traderType)
    82         {
    83             return new TradeBill
    84             {
    85                 Account = account,
    86                 ToAccount = toAccount,
    87                 TraderType = traderType,
    88                 TradeRemark = this.Remark,
    89                 TradeAmount = this.TradeAmount,
    90                 TradeDateTime = DateTime.Now,
    91                 TradeOrderNumber = this.TradeOrderNumber,
    92                 Balance = account.Balance,
    93                 AvailableBalance = account.AvailableBalance,
    94                 FreezeAmount = account.FreezeAmount,
    95                 BillType = BillType.Pay
    96             };
    97         }
    98     }
    View Code

        转账类只需要继承正向交易类就行了 转账只有一个转账的核心方法

     1     /// <summary>
     2     /// Transfer
     3     /// </summary>
     4     public class TransferOrder : ForwardTrade
     5     {
     6         /// <summary>
     7         /// Initializes a new instance of the <see cref="TransferOrder"/> class.
     8         /// </summary>
     9         public TransferOrder()
    10         {
    11         }
    12 
    13         /// <summary>
    14         /// Initializes a new instance of the <see cref="TransferOrder"/> class.
    15         /// </summary>
    16         /// <param name="transferID">
    17         /// The pay order id.
    18         /// </param>
    19         public TransferOrder(Guid transferID)
    20             : base(transferID)
    21         {
    22         }
    23 
    24         /// <summary>
    25         /// 状态
    26         /// </summary>
    27         public TransferStatus TransferStatus { get; set; }
    28 
    29         /// <summary>
    30         /// 支付成功处理
    31         /// </summary>
    32         public void TransferSucess()
    33         {
    34             if (this.TransferStatus == TransferStatus.Successful)
    35             {
    36                 throw new ArgumentException("抱歉!订单已经交易成功");
    37             }
    38 
    39             this.UpdateTradeDateTime(DateTime.Now);
    40             this.UpdatePayStatus(TransferStatus.Successful);
    41         }
    42 
    43         /// <summary>
    44         /// 转账
    45         /// </summary>
    46         /// <returns>账单</returns>
    47         public List<TradeBill> Transfer()
    48         {
    49             return this.Trade();
    50         }
    51 
    52         /// <summary>
    53         /// 修改订单状态
    54         /// </summary>
    55         /// <param name="transferStatus">订单状态</param>
    56         public void UpdatePayStatus(TransferStatus transferStatus)
    57         {
    58             this.TransferStatus = transferStatus;
    59         }
    60     }
    View Code

       最后在服务类组装业务

     1 校验基本信息

       2 加载 转账账户  

     3 加载收款账户

       4 校验交易密码

     5 创建订单 

       6 调用转账方法

     7 持久化数据

     1         /// <summary>
     2         /// 转账
     3         /// </summary>
     4         /// <param name="transferDTO">转账信息</param>
     5         public static void Transfer(TransferDTO transferDTO)
     6         {
     7             // 1 校验基本信息
     8             transferDTO.ValidateTransferDTO();
     9 
    10             // 2 加载账户
    11             // 转账账户
    12             Account.Account payAccount = QueryByAccountName(transferDTO.TransferNO);
    13 
    14             // 收款账户
    15             Account.Account sellerAccount = QueryByAccountName(transferDTO.CollectionNO);
    16 
    17             // 3 校验交易密码
    18             payAccount.ValidatePayPassWord(transferDTO.PayPassWord);
    19 
    20             // 4 创建订单
    21             TransferOrder transferOrder = Builder.BuilderTransferOrder(payAccount, sellerAccount, transferDTO);
    22 
    23             // 同步处理为成功
    24             transferOrder.TransferSucess();
    25 
    26             // 5 调用转账方法
    27             List<TradeBill> bills = transferOrder.Transfer();
    28 
    29             // 6 持久化数据(开启工作单元;开启数据库事务)
    30             using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
    31             {
    32                 // 更新账户余额
    33                 IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
    34                 accountRepository.Update(payAccount);
    35                 accountRepository.Update(sellerAccount);
    36 
    37                 // 生成订单
    38                 ITransferOrderRepsoitory transferOrderRepsoitory = Account.Factory.AccountFactory.CreateITransferOrderRepsoitory(unitOfWork);
    39                 transferOrderRepsoitory.Add(transferOrder);
    40 
    41                 // 生成账单
    42                 IBillRepository billRepository = Account.Factory.AccountFactory.CreateIBillRepository(unitOfWork);
    43                 billRepository.Add(bills);
    44 
    45                 // 提交工作单元(提交事务,失败自动回滚)
    46                 unitOfWork.Complete();
    47             }
    48         }
    View Code

    8.冻结

      冻结主要是将账户的可用余额冻结起来 ,其实就实现一个内部转账就是账户自身AvailableBalance可用余额转到FreezeAmount冻结金额上去 最终生成冻结订单来控制金额变化起到资金控制的作用

         这样就可以抽象出一个资金控制类出来

     1     /// <summary>
     2     /// 资金控制
     3     /// </summary>
     4     public class Control : EntityBase<Guid>
     5     {
     6         /// <summary>
     7         /// Initializes a new instance of the <see cref="Control"/> class.
     8         /// </summary>
     9         public Control()
    10             : base(Guid.NewGuid())
    11         {
    12         }
    13 
    14         /// <summary>
    15         /// Initializes a new instance of the <see cref="Control"/> class.
    16         /// </summary>
    17         /// <param name="accountID">
    18         /// The account id.
    19         /// </param>
    20         public Control(Guid accountID)
    21             : base(accountID)
    22         {
    23         }
    24 
    25         /// <summary>
    26         /// 控制账户
    27         /// </summary>
    28         public Account Account { get; set; }
    29     }
    View Code

      这样再去设计冻结订单类

      1     /// <summary>
      2     /// 冻结订单
      3     /// </summary>
      4     public class FreezeOrder : Control
      5     {
      6         /// <summary>
      7         /// Initializes a new instance of the <see cref="FreezeOrder"/> class.
      8         /// </summary>
      9         public FreezeOrder()
     10         {
     11             this.FrezeOrderNumber = Builder.BuilderOrderNumber();
     12         }
     13 
     14         /// <summary>
     15         /// 冻结订单号
     16         /// </summary>
     17         public string FrezeOrderNumber { get; set; }
     18 
     19         /// <summary>
     20         /// 冻结状态
     21         /// </summary>
     22         public FreezeStatus FreezeStatus { get; set; }
     23 
     24         /// <summary>
     25         /// 冻结金额
     26         /// </summary>
     27         public decimal FreezeAmount { get; set; }
     28 
     29         /// <summary>
     30         /// 已解冻金额
     31         /// </summary>
     32         public decimal ThawAmount { get; set; }
     33 
     34         /// <summary>
     35         /// 备注
     36         /// </summary>
     37         public string FreezeRemark { get; set; }
     38 
     39         /// <summary>
     40         /// 冻结
     41         /// </summary>
     42         /// <returns>
     43         /// The 
     44         /// </returns>
     45         public ControlBill Freeze()
     46         {
     47             this.Account.Freeze(this.FreezeAmount);
     48             this.UpdateFreezeStatus(FreezeStatus.冻结成功);
     49             return this.CreateControlBill();
     50         }
     51 
     52         /// <summary>
     53         /// 修改冻结订单状态
     54         /// </summary>
     55         /// <param name="freezeStatus">冻结订单状态</param>
     56         public void UpdateFreezeStatus(FreezeStatus freezeStatus)
     57         {
     58             this.FreezeStatus = freezeStatus;
     59         }
     60 
     61         /// <summary>
     62         /// 解冻
     63         /// </summary>
     64         /// <param name="thawAmount">解冻金额</param>
     65         public void Thaw(decimal thawAmount)
     66         {
     67             if (thawAmount > this.FreezeAmount)
     68             {
     69                 throw new AggregateException("抱歉!解冻金额大于冻结金额");
     70             }
     71 
     72             if (thawAmount > this.FreezeAmount - this.ThawAmount)
     73             {
     74                 throw new AggregateException("抱歉!解冻金额过大");
     75             }
     76 
     77             this.ThawAmount += thawAmount;
     78         }
     79 
     80         /// <summary>
     81         /// The create control bill.
     82         /// </summary>
     83         /// <returns>
     84         /// The <see cref="ControlBill"/>.
     85         /// </returns>
     86         private ControlBill CreateControlBill()
     87         {
     88             var bill = new ControlBill
     89             {
     90                 Account = this.Account,
     91                 Balance = this.Account.Balance,
     92                 AvailableBalance = this.Account.AvailableBalance,
     93                 FreezeAmount = this.Account.FreezeAmount,
     94                 ControlAmount = this.FreezeAmount,
     95                 ControlDateTime = DateTime.Now,
     96                 ControlOrderNumber = this.FrezeOrderNumber,
     97                 ControlRemark = this.FreezeRemark,
     98                 ControlType = ControlType.Freeze,
     99                 OrderNumber = Builder.BuilderOrderNumber()
    100             };
    101 
    102             return bill;
    103         }
    104     }
    View Code

        冻结包括2个核心方法冻结跟解冻

        服务类只需要组装这些业务冻结功能就完成了

     1         /// <summary>
     2         /// 冻结
     3         /// </summary>
     4         /// <param name="freezeDTO">冻结信息</param>
     5         public static void Freeze(FreezeDTO freezeDTO)
     6         {
     7             freezeDTO.ValidateFreezeDTO();
     8             Account.Account account = QueryByAccountName(freezeDTO.FreezeNO);
     9             FreezeOrder freezeOrder = Builder.BuilderFreezeOrder(account, freezeDTO);
    10             ControlBill controlBill = freezeOrder.Freeze();
    11             using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
    12             {
    13                 IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
    14                 accountRepository.UpdateFreezeAmount(account);
    15 
    16                 // 生成冻结订单
    17                 IFreezeOrderRepository freezeOrderRepository = Account.Factory.AccountFactory.CreateIFreezeOrderRepository(unitOfWork);
    18                 freezeOrderRepository.Add(freezeOrder);
    19 
    20                 // 生成冻结账单
    21                 IControlBillRepository controlBillRepository = Account.Factory.AccountFactory.CreateIControlBillRepository(unitOfWork);
    22                 controlBillRepository.Add(controlBill);
    23 
    24                 unitOfWork.Complete();
    25             }
    26         }
    View Code

    9.解冻

      解冻与冻结就相反了

      但是也是属于资金控制

      只需要设计一个解冻订单类继承资金控制就可以,解冻订单必须包含一个属性是冻结订单

      1     /// <summary>
      2     /// 解冻订单
      3     /// </summary>
      4     public class ThawOrder : Control
      5     {
      6         /// <summary>
      7         /// Initializes a new instance of the <see cref="ThawOrder"/> class.
      8         /// </summary>
      9         /// <param name="freezeOrder">
     10         /// The freeze order.
     11         /// </param>
     12         public ThawOrder(FreezeOrder freezeOrder)
     13         {
     14             this.Initialization(freezeOrder);
     15         }
     16 
     17         /// <summary>
     18         /// Initializes a new instance of the <see cref="ThawOrder"/> class.
     19         /// </summary>
     20         /// <param name="thawId">
     21         /// The thaw id.
     22         /// </param>
     23         /// <param name="freezeOrder">
     24         /// The freeze order.
     25         /// </param>
     26         public ThawOrder(Guid thawId, FreezeOrder freezeOrder)
     27             : base(thawId)
     28         {
     29             this.Initialization(freezeOrder);
     30         }
     31 
     32         /// <summary>
     33         /// The initialization.
     34         /// </summary>
     35         /// <param name="freezeOrder">
     36         /// The freeze order.
     37         /// </param>
     38         private void Initialization(FreezeOrder freezeOrder)
     39         {
     40             this.FreezeOrder = freezeOrder;
     41             this.Account = freezeOrder.Account;
     42         }
     43 
     44         /// <summary>
     45         /// 冻结订单
     46         /// </summary>
     47         public FreezeOrder FreezeOrder { get; private set; }
     48 
     49         /// <summary>
     50         /// 冻结订单号
     51         /// </summary>
     52         public string ThawOrderNumber { get; set; }
     53 
     54         /// <summary>
     55         /// 解冻状态
     56         /// </summary>
     57         public ThawStatus ThawStatus { get; set; }
     58 
     59         /// <summary>
     60         /// 解冻金额
     61         /// </summary>
     62         public decimal ThawAmount { get; set; }
     63 
     64         /// <summary>
     65         /// 备注
     66         /// </summary>
     67         public string ThawRemark { get; set; }
     68 
     69         /// <summary>
     70         /// 修改解冻订单状态
     71         /// </summary>
     72         /// <param name="freezeStatus">冻结订单状态</param>
     73         public void UpdateThawStatus(ThawStatus freezeStatus)
     74         {
     75             this.ThawStatus = freezeStatus;
     76         }
     77 
     78         /// <summary>
     79         /// 解冻
     80         /// </summary>
     81         /// <returns>账单</returns>
     82         public ControlBill Thaw()
     83         {
     84             this.FreezeOrder.Thaw(this.ThawAmount);
     85             this.Account.Thaw(this.ThawAmount);
     86             this.UpdateThawStatus(ThawStatus.解冻成功);
     87             return this.CreateControlBill();
     88         }
     89 
     90         /// <summary>
     91         /// The create control bill.
     92         /// </summary>
     93         /// <returns>
     94         /// The <see cref="ControlBill"/>.
     95         /// </returns>
     96         private ControlBill CreateControlBill()
     97         {
     98             var bill = new ControlBill
     99             {
    100                 Account = this.Account,
    101                 Balance = this.Account.Balance,
    102                 AvailableBalance = this.Account.AvailableBalance,
    103                 FreezeAmount = this.Account.FreezeAmount,
    104                 ControlAmount = this.ThawAmount,
    105                 ControlDateTime = DateTime.Now,
    106                 ControlOrderNumber = this.ThawOrderNumber,
    107                 ControlRemark = this.ThawRemark,
    108                 ControlType = ControlType.Thaw,
    109                 OrderNumber = Builder.BuilderOrderNumber()
    110             };
    111 
    112             return bill;
    113         }
    114     }
    View Code

      这样设计出来就简单明了了 

     1         /// <summary>
     2         /// 解冻
     3         /// </summary>
     4         /// <param name="thawDTO">解冻信息</param>
     5         public static void Thaw(ThawDTO thawDTO)
     6         {
     7             thawDTO.ValidateThawDTO();
     8             FreezeOrder freezeOrder = QueryFreezeOrder(thawDTO.FreezeOrderNumber);
     9             ThawOrder thawOrder = Builder.BuilderThawOrder(freezeOrder, thawDTO);
    10             ControlBill controlBill = thawOrder.Thaw();
    11             using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
    12             {
    13                 IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
    14                 accountRepository.UpdateFreezeAmount(thawOrder.Account);
    15 
    16                 // 生成解冻顶
    17                 IThawOrderRepsoitory thawOrderRepsoitory = Account.Factory.AccountFactory.CreateIThawOrderRepsoitory(unitOfWork);
    18                 thawOrderRepsoitory.Add(thawOrder);
    19 
    20                 // 修改冻结订单
    21                 IFreezeOrderRepository freezeOrderRepository = Account.Factory.AccountFactory.CreateIFreezeOrderRepository(unitOfWork);
    22                 freezeOrderRepository.Update(freezeOrder);
    23 
    24                 // 生成解冻账单
    25                 IControlBillRepository controlBillRepository = Account.Factory.AccountFactory.CreateIControlBillRepository(unitOfWork);
    26                 controlBillRepository.Add(controlBill);
    27 
    28                 unitOfWork.Complete();
    29             }
    30         }
    View Code

         到此为止 本篇文章也就结束了 。

         本文的目的做到了 业务与持久化无关(数据库操作), 做到了 CodeFirst(代码优先)

         最后要做的就是根据领域对象去设计数据库就行

         附源代码

     

        

      

     

       

       

      

  • 相关阅读:
    rabbitMQ rabbitmq-server -detached rabbitmq-server -detached rabbitmq-server -detached
    ElasticSearch 深度分页解决方案 {"index":{"number_of_replicas":0}}
    git 服务器新建仓库 远程仓库
    mongo 记得开启验证 auth = true
    虚拟机创建及安装ELK
    JSF action actionListner 详解
    Developing JSF applications with Spring Boot
    从问题看本质: 研究TCP close_wait的内幕
    linux server 产生大量 Too many open files CLOSE_WAIT激增
    wildfly tomcat 服务器不响应 不返回 死住了 查看tcp CLOSE_WAIT 暴多
  • 原文地址:https://www.cnblogs.com/liuxiaoji/p/4290246.html
Copyright © 2020-2023  润新知