代码是个程序员都能写,

怎么的代码才是好的,

 

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

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. }

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() : ;
  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. }

     做一个泛型的标识继承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. }

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. }

 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. }

 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. }

工作单元接口

  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. }

工作单元

  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. }

 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. }

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, );
  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, );
  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, );
  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, );
  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, );
  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, );
  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, );
  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, );
  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, ))
  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, );
  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, );
  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, );
  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, );
  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. }

8.Sql仓储基类

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

     /// <summary>
/// The sql repository base.
/// </summary>
/// <typeparam name="TKey">
/// </typeparam>
/// <typeparam name="TValue">
/// </typeparam>
public abstract class SqlRepositoryBase<TKey, TValue> : SqlCeRepositoryBase<TKey, TValue>
where TValue : EntityBase<TKey>
{
/// <summary>
/// 有子对象的回调委托
/// </summary>
/// <param name="entityAggregate">实体聚合根</param>
/// <param name="childEntityKeyValue">子实体键</param>
public delegate void AppendChildData(TValue entityAggregate, object childEntityKeyValue); /// <summary>
/// 实体工厂
/// </summary>
private readonly IEntityFactory<TValue> m_entityFactory; /// <summary>
/// 子对象集
/// </summary>
private readonly Dictionary<string, AppendChildData> m_childCallbacks; /// <summary>
/// The m_child key datas.
/// </summary>
private readonly Dictionary<string, object> m_childKeyDatas; /// <summary>
/// Initializes a new instance of the <see cref="SqlRepositoryBase{TKey,TValue}"/> class.
/// </summary>
/// <param name="connectionSetting">
/// The connection setting.
/// </param>
protected SqlRepositoryBase(string connectionSetting)
: base(connectionSetting)
{
} /// <summary>
/// Initializes a new instance of the <see cref="SqlRepositoryBase{TKey,TValue}"/> class.
/// </summary>
/// <param name="unitOfWork">
/// The unit of work.
/// </param>
/// <param name="connectionSetting">
/// The connection setting.
/// </param>
protected SqlRepositoryBase(IUnitOfWork unitOfWork, string connectionSetting)
: base(unitOfWork, connectionSetting)
{
this.m_entityFactory = this.BuildEntityFactory();
this.m_childCallbacks = new Dictionary<string, AppendChildData>();
this.m_childKeyDatas = new Dictionary<string, object>();
this.BuildChildCallbacks(this.m_childCallbacks);
} /// <summary>
/// 改为由子类创建实体,不使用工厂
/// </summary>
/// <returns>TValue</returns>
protected abstract IEntityFactory<TValue> BuildEntityFactory(); /// <summary>
/// 创建子对象回调
/// </summary>
/// <param name="childCallbacks">子对象集</param>
protected abstract void BuildChildCallbacks(Dictionary<string, AppendChildData> childCallbacks); /// <summary>
/// 子对象回调集
/// </summary>
protected Dictionary<string, AppendChildData> ChildCallbacks
{
get
{
return this.m_childCallbacks;
}
} /// <summary>
/// The build entity from reader.
/// </summary>
/// <param name="reader">
/// The reader.
/// </param>
/// <returns>
/// The <see cref="TValue"/>.
/// </returns>
protected virtual TValue BuildEntityFromReader(IDataReader reader)
{
TValue entity = this.m_entityFactory.BuildEntity(reader);
if (this.m_childCallbacks != null && this.m_childCallbacks.Count > )
{
DataTable columnData = reader.GetSchemaTable();
foreach (string childKeyName in this.m_childCallbacks.Keys)
{
object childKeyValue;
////判断 DataReader 的数据集合中是否存在一个特定的列名(或字段名)
if (columnData != null && columnData.Rows.Cast<DataRow>().Any(row => row["ColumnName"].ToString() == childKeyName))
{
childKeyValue = reader[childKeyName];
}
else
{
childKeyValue = null;
}
if (m_childKeyDatas.ContainsKey(childKeyName))
{
m_childKeyDatas[childKeyName] = childKeyValue;
}
else
{
m_childKeyDatas.Add(childKeyName, childKeyValue);
}
}
}
return entity;
} /// <summary>
/// The build entity from sql.
/// </summary>
/// <param name="sql">
/// The sql.
/// </param>
/// <returns>
/// The <see cref="TValue"/>.
/// </returns>
protected virtual TValue BuildEntityFromSql(string sql)
{
TValue entity = default(TValue);
using (IDataReader reader = this.ExecuteReader(sql))
{
if (reader.Read())
{
entity = this.BuildEntityFromReader(reader);
}
}
if (entity != null)
{
this.InvokeChildCallbacks(entity);
}
return entity;
} /// <summary>
/// The build entities from sql.
/// </summary>
/// <param name="sql">
/// The sql.
/// </param>
/// <returns>
/// The
/// </returns>
protected virtual List<TValue> BuildEntitiesFromSql(string sql)
{
List<TValue> entities = new List<TValue>();
using (IDataReader reader = this.ExecuteReader(sql))
{
while (reader.Read())
{
entities.Add(this.BuildEntityFromReader(reader));
}
}
return entities;
} /// <summary>
/// The invoke child callbacks.
/// </summary>
/// <param name="entity">
/// The entity.
/// </param>
private void InvokeChildCallbacks(TValue entity)
{
if (this.m_childCallbacks != null && this.m_childCallbacks.Any())
{
foreach (string childKeyName in this.m_childKeyDatas.Keys)
{
object childKeyValue;
this.m_childKeyDatas.TryGetValue(childKeyName, out childKeyValue);
this.m_childCallbacks[childKeyName](entity, childKeyValue);
}
}
}
}

 

领域层

1.分析业务需求,

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

  业务功能分析

  1.开户功能

  2.支付功能

  3.转账功能

  4.冻结解冻功能

2.结构设计

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

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

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

3.分析Account的职责

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

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

账户的基本行为:

1.登录

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

         public void Login(string accountName, string loginPassWord)
{
this.ValidateEmpty();
this.ValidateLoginStatus();
if (this.AccountName != accountName)
{
throw new ArgumentException("抱歉!账户名错误");
} if (this.LoginPassWord != loginPassWord)
{
throw new ArgumentException("抱歉!账户登录密码错误");
}
}

2.存款

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

         public void Deposit(decimal depositAmount)
{
this.Balance += depositAmount;
this.AvailableBalance += depositAmount;
}

  3.取款

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

         public void Withdraw(decimal withdrawAmout)
{
this.ValudateAvailableBalance(withdrawAmout);
this.Balance -= withdrawAmout;
this.AvailableBalance -= withdrawAmout;
}

  5.冻结

    冻结也跟取款类似

         public void Freeze(decimal freezeAmount)
{
this.ValudateAvailableBalance(freezeAmount);
this.FreezeAmount += freezeAmount;
this.AvailableBalance -= freezeAmount;
}

  6.解冻

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

         public void UnFreeze(decimal unFreezeAmount)
{
this.ValudateFreezeAmount(unFreezeAmount);
this.FreezeAmount -= unFreezeAmount;
this.AvailableBalance += unFreezeAmount;
}

  7.修改交易密码

         public void UpdatePayPassWord(string payPassWord)
{
this.PayPassWord = payPassWord;
}

  8.修改登录密码

         public void UpdateLoginPassWord(string loginPassWord)
{
this.LoginPassWord = loginPassWord;
}

 4.AccountRepository实现的基本方法

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

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

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

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

     /// <summary>
/// The account factory.
/// </summary>
public class AccountFactory : IEntityFactory<Account>
{
/// <summary>
/// 把IDataReader对象解析成Account对象
/// </summary>
/// <param name="reader">
/// The reader.
/// </param>
/// <returns>
/// The <see cref="Account"/>.
/// </returns>
public Account BuildEntity(IDataReader reader)
{
Account account = new Account(Guid.Parse(reader[FieldNames.AccountID].ToString()));
return account;
} /// <summary>
/// 把DataSet对象解析成Account对象
/// </summary>
/// <param name="table">
/// The table.
/// </param>
/// <returns>
/// The <see cref="Account"/>.
/// </returns>
public Account BuildEntity(DataSet table)
{
throw new NotImplementedException();
} /// <summary>
/// 映射数据库字段名称
/// </summary>
public static class FieldNames
{
/// <summary>
/// 表名 Account
/// </summary>
public const string Account = "Account"; /// <summary>
/// 主键 AccountID
/// </summary>
public const string AccountID = "AccountID";
}
}
         protected override IEntityFactory<Account> BuildEntityFactory()
{
return new AccountFactory();
}

    

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

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

         /// <summary>
/// The build child callbacks.
/// </summary>
/// <param name="childCallbacks">
/// The child callbacks.
/// </param>
protected override void BuildChildCallbacks(Dictionary<string, AppendChildData> childCallbacks)
{
// 主要实现加载密保的方法
childCallbacks.Add(
AccountFactory.FieldNames.AccountID,
(a, b) =>
{
// 此处调用加载密保的方法
a.Encrypted = null;
});
}

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

         /// <summary>
/// 查询
/// </summary>
/// <param name="key">
/// The key.
/// </param>
/// <returns>
/// The <see cref="Account"/>.
/// </returns>
public override Account FindBy(Guid key)
{
throw new NotImplementedException();
} /// <summary>
/// 增加
/// </summary>
/// <param name="item">
/// The item.
/// </param>
public override void PersistNewItem(IEntity item)
{
// 因为Account是继承自IEntity接口这里直接把item转化成Account类型即可
Account account = (Account)item;
StringBuilder sql = new StringBuilder();
sql.AppendFormat(" INSERT INTO {0}", AccountFactory.FieldNames.Account);
sql.Append(" ( ");
sql.AppendFormat("{0}", AccountFactory.FieldNames.AccountID);
sql.Append(" ) VALUES ( ");
sql.AppendFormat("@{0}", AccountFactory.FieldNames.AccountID);
sql.Append(");"); // 调用父亲类方法实现参数化添加参数
// 调用支持先清除一下这是必须的
this.ClearParameters();
this.AddParameter("@" + AccountFactory.FieldNames.AccountID, account.Key); // 执行sql语句
this.ExecuteNonQuery(sql.ToString());
} /// <summary>
/// 修改
/// </summary>
/// <param name="item">
/// The item.
/// </param>
public override void PersistUpdatedItem(IEntity item)
{
throw new NotImplementedException();
} /// <summary>
/// 删除
/// </summary>
/// <param name="item">
/// The item.
/// </param>
public override void PersistDeletedItem(IEntity item)
{
throw new NotImplementedException();
}

 5.现在来实现开户功能

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

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

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

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

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

     /// <summary>
/// 账户传输对象
/// </summary>
public class AccountDTO
{
/// <summary>
/// 账户名
/// </summary>
public string AccountName { get; set; } /// <summary>
/// 昵称
/// </summary>
public string Nickname { get; set; } /// <summary>
/// 登录密码
/// </summary>
public string LoginPassWord { get; set; } /// <summary>
/// 交易密码
/// </summary>
public string PayPassWord { get; set; } /// <summary>
/// 邮箱
/// </summary>
public string Emial { get; set; } /// <summary>
/// 手机
/// </summary>
public string Phone { get; set; } /// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
}

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

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

     /// <summary>
/// Builder
/// </summary>
public class Builder
{
/// <summary>
/// 创建Account
/// </summary>
/// <param name="accountDTO">accountDTO</param>
/// <returns>Account</returns>
internal static Account BuilderAccount(AccountDTO accountDTO)
{
Account account = new Account
{
AccountStatus = AccountStatus.Normal,
Balance = 0M,
AvailableBalance = 0M,
FreezeAmount = 0M,
Encrypted = null,
AccountName = accountDTO.AccountName,
Nickname = accountDTO.Nickname,
LoginPassWord = accountDTO.LoginPassWord,
PayPassWord = accountDTO.PayPassWord,
Remark = accountDTO.Remark
}; return account;
}
}

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

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

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

         /// <summary>
/// The create i account repository.
/// </summary>
/// <returns>
/// The <see cref="IAccountRepository"/>.
/// </returns>
internal static IAccountRepository CreateIAccountRepository()
{
return new AccountRepository(ConnectionString.Account);
}
     /// <summary>
/// The connection string.
/// </summary>
public static class ConnectionString
{
/// <summary>
/// The account.
/// </summary>
public const string Account = "Account";
}

最后贴出开户的全部代码

         public static void Register(AccountDTO accountDTO)
{
Account.Account account = Account.Builder.BuilderAccount(accountDTO);
using (IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository())
{
accountRepository.Add(account);
}
}

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

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

  Tread(交易类)

     /// <summary>
/// 交易
/// </summary>
public class Trade : EntityBase<Guid>
{
/// <summary>
/// Initializes a new instance of the <see cref="Trade"/> class.
/// </summary>
public Trade()
: base(Guid.NewGuid())
{
} /// <summary>
/// Initializes a new instance of the <see cref="Trade"/> class.
/// </summary>
/// <param name="accountID">
/// The account id.
/// </param>
public Trade(Guid accountID)
: base(accountID)
{
} /// <summary>
/// 买家
/// </summary>
public Account Buyer { get; set; } /// <summary>
/// 卖家
/// </summary>
public Account Seller { get; set; }
}

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

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

     /// <summary>
/// 支付
/// </summary>
public class PayOrder : Trade
{
/// <summary>
/// 支付状态
/// </summary>
public PayStatus PayStatus { get; set; } /// <summary>
/// 支付金额
/// </summary>
public decimal PayAmount { get; set; } /// <summary>
/// 支付订单号
/// </summary>
public string PayOrderNumber { get; set; } /// <summary>
/// 创建时间
/// </summary>
public DateTime CreateDateTime { get; set; } /// <summary>
/// 支付时间
/// </summary>
public DateTime? PayDateTime { get; set; } /// <summary>
/// 备注
/// </summary>
public string Remark { get; set; } /// <summary>
/// 支付
/// </summary>
/// <returns>生成账单</returns>
public List<Bill> Pay()
{
AccountService.AccountTransfer(this.Buyer, this.Seller, this.PayAmount);
return null;
}
}

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

     /// <summary>
/// 账单
/// </summary>
public class Bill : EntityBase<Guid>
{
/// <summary>
/// 交易金额
/// </summary>
public decimal TradeAmount { get; set; } /// <summary>
/// 账单流水号
/// </summary>
public string OrderNumber { get; set; } /// <summary>
/// 交易类型
/// </summary>
public string TraderType { get; set; } /// <summary>
/// 交易备注
/// </summary>
public string TradeRemark { get; set; } /// <summary>
/// 交易时间
/// </summary>
public DateTime TradeDateTime { get; set; } /// <summary>
/// 交易号
/// </summary>
public string TradeOrderNumber { get; set; } /// <summary>
/// 交易账户
/// </summary>
public Account Account { get; set; } /// <summary>
/// 交易对方账户
/// </summary>
public Account ToAccount { get; set; }
}

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

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

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

     /// <summary>
/// 支付传送对象
/// </summary>
public class PayDTO
{
/// <summary>
/// 支付账号
/// </summary>
public string PayAccountNO { get; set; } /// <summary>
/// 支付金额
/// </summary>
public decimal PayAmount { get; set; } /// <summary>
/// 交易密码
/// </summary>
public string PayPassWord { get; set; } /// <summary>
/// 交易备注
/// </summary>
public string Remark { get; set; }
}

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

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

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

4.创建支付订单

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

         /// <summary>
/// 支付
/// </summary>
/// <param name="payDTO">支付信息</param>
public static void Pay(PayDTO payDTO)
{
// 1 校验基本信息
payDTO.ValidatePayDTO(); // 2 加载账户
// 支付账户
Account.Account payAccount = QueryByAccountName(payDTO.PayAccountNO); // 收款账户
Account.Account sellerAccount = QueryBySeller(); // 3 校验交易密码
payAccount.ValidatePayPassWord(payDTO.PayPassWord); // 4 创建支付订单
PayOrder payOrder = Builder.BuilderPayOrder(payAccount, sellerAccount, payDTO); // 同步处理为支付成功
payOrder.PaySucess(); // 5 调用支付方法
List<Bill> bills = payOrder.Pay(); // 6 持久化数据(开启工作单元;开启数据库事务)
using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
{
// 更新账户余额
IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
accountRepository.Update(payAccount);
accountRepository.Update(sellerAccount); // 生成订单
IPayOrderRepository payOrderRepository = Account.Factory.AccountFactory.CreateIPayOrderRepository(unitOfWork);
payOrderRepository.Add(payOrder); // 生成账单
IBillRepository billRepository = Account.Factory.AccountFactory.CreateIBillRepository(unitOfWork);
billRepository.Add(bills); // 提交工作单元(提交事务,失败自动回滚)
unitOfWork.Complete();
}
}

 7.转账

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

     /// <summary>
/// 正向交易
/// </summary>
public class ForwardTrade : Trade
{
/// <summary>
/// Initializes a new instance of the <see cref="ForwardTrade"/> class.
/// </summary>
public ForwardTrade()
{
this.TradeOrderNumber = Builder.BuilderOrderNumber();
} /// <summary>
/// Initializes a new instance of the <see cref="ForwardTrade"/> class.
/// </summary>
/// <param name="tradeID">
/// The pay order id.
/// </param>
public ForwardTrade(Guid tradeID)
: base(tradeID)
{
} /// <summary>
/// 交易金额
/// </summary>
public decimal TradeAmount { get; set; } /// <summary>
/// 交易订单号
/// </summary>
public string TradeOrderNumber { get; set; } /// <summary>
/// 创建时间
/// </summary>
public DateTime CreateDateTime { get; set; } /// <summary>
/// 支付时间
/// </summary>
public DateTime? TradeDateTime { get; set; } /// <summary>
/// 备注
/// </summary>
public string Remark { get; set; } /// <summary>
/// 更新交易时间
/// </summary>
/// <param name="tradeDateTime">交易时间</param>
public void UpdateTradeDateTime(DateTime tradeDateTime)
{
this.TradeDateTime = tradeDateTime;
} /// <summary>
/// 交易
/// </summary>
/// <returns>生成账单</returns>
public List<TradeBill> Trade()
{
AccountService.AccountTransfer(this.Buyer, this.Seller, this.TradeAmount);
List<TradeBill> result = new List<TradeBill>
{
this.CreateBill(this.Buyer, this.Seller, TraderType.Out),
this.CreateBill(this.Seller, this.Buyer, TraderType.In)
};
return result;
} /// <summary>
/// 创建账单
/// </summary>
/// <param name="account">交易账户</param>
/// <param name="toAccount">交易对方账户</param>
/// <param name="traderType">交易类型</param>
/// <returns></returns>
private TradeBill CreateBill(Account account, Account toAccount, TraderType traderType)
{
return new TradeBill
{
Account = account,
ToAccount = toAccount,
TraderType = traderType,
TradeRemark = this.Remark,
TradeAmount = this.TradeAmount,
TradeDateTime = DateTime.Now,
TradeOrderNumber = this.TradeOrderNumber,
Balance = account.Balance,
AvailableBalance = account.AvailableBalance,
FreezeAmount = account.FreezeAmount,
BillType = BillType.Pay
};
}
}

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

     /// <summary>
/// Transfer
/// </summary>
public class TransferOrder : ForwardTrade
{
/// <summary>
/// Initializes a new instance of the <see cref="TransferOrder"/> class.
/// </summary>
public TransferOrder()
{
} /// <summary>
/// Initializes a new instance of the <see cref="TransferOrder"/> class.
/// </summary>
/// <param name="transferID">
/// The pay order id.
/// </param>
public TransferOrder(Guid transferID)
: base(transferID)
{
} /// <summary>
/// 状态
/// </summary>
public TransferStatus TransferStatus { get; set; } /// <summary>
/// 支付成功处理
/// </summary>
public void TransferSucess()
{
if (this.TransferStatus == TransferStatus.Successful)
{
throw new ArgumentException("抱歉!订单已经交易成功");
} this.UpdateTradeDateTime(DateTime.Now);
this.UpdatePayStatus(TransferStatus.Successful);
} /// <summary>
/// 转账
/// </summary>
/// <returns>账单</returns>
public List<TradeBill> Transfer()
{
return this.Trade();
} /// <summary>
/// 修改订单状态
/// </summary>
/// <param name="transferStatus">订单状态</param>
public void UpdatePayStatus(TransferStatus transferStatus)
{
this.TransferStatus = transferStatus;
}
}

最后在服务类组装业务

 1 校验基本信息

2 加载 转账账户  

 3 加载收款账户

4 校验交易密码

 5 创建订单 

6 调用转账方法

 7 持久化数据

         /// <summary>
/// 转账
/// </summary>
/// <param name="transferDTO">转账信息</param>
public static void Transfer(TransferDTO transferDTO)
{
// 1 校验基本信息
transferDTO.ValidateTransferDTO(); // 2 加载账户
// 转账账户
Account.Account payAccount = QueryByAccountName(transferDTO.TransferNO); // 收款账户
Account.Account sellerAccount = QueryByAccountName(transferDTO.CollectionNO); // 3 校验交易密码
payAccount.ValidatePayPassWord(transferDTO.PayPassWord); // 4 创建订单
TransferOrder transferOrder = Builder.BuilderTransferOrder(payAccount, sellerAccount, transferDTO); // 同步处理为成功
transferOrder.TransferSucess(); // 5 调用转账方法
List<TradeBill> bills = transferOrder.Transfer(); // 6 持久化数据(开启工作单元;开启数据库事务)
using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
{
// 更新账户余额
IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
accountRepository.Update(payAccount);
accountRepository.Update(sellerAccount); // 生成订单
ITransferOrderRepsoitory transferOrderRepsoitory = Account.Factory.AccountFactory.CreateITransferOrderRepsoitory(unitOfWork);
transferOrderRepsoitory.Add(transferOrder); // 生成账单
IBillRepository billRepository = Account.Factory.AccountFactory.CreateIBillRepository(unitOfWork);
billRepository.Add(bills); // 提交工作单元(提交事务,失败自动回滚)
unitOfWork.Complete();
}
}

8.冻结

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

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

     /// <summary>
/// 资金控制
/// </summary>
public class Control : EntityBase<Guid>
{
/// <summary>
/// Initializes a new instance of the <see cref="Control"/> class.
/// </summary>
public Control()
: base(Guid.NewGuid())
{
} /// <summary>
/// Initializes a new instance of the <see cref="Control"/> class.
/// </summary>
/// <param name="accountID">
/// The account id.
/// </param>
public Control(Guid accountID)
: base(accountID)
{
} /// <summary>
/// 控制账户
/// </summary>
public Account Account { get; set; }
}

  这样再去设计冻结订单类

     /// <summary>
/// 冻结订单
/// </summary>
public class FreezeOrder : Control
{
/// <summary>
/// Initializes a new instance of the <see cref="FreezeOrder"/> class.
/// </summary>
public FreezeOrder()
{
this.FrezeOrderNumber = Builder.BuilderOrderNumber();
} /// <summary>
/// 冻结订单号
/// </summary>
public string FrezeOrderNumber { get; set; } /// <summary>
/// 冻结状态
/// </summary>
public FreezeStatus FreezeStatus { get; set; } /// <summary>
/// 冻结金额
/// </summary>
public decimal FreezeAmount { get; set; } /// <summary>
/// 已解冻金额
/// </summary>
public decimal ThawAmount { get; set; } /// <summary>
/// 备注
/// </summary>
public string FreezeRemark { get; set; } /// <summary>
/// 冻结
/// </summary>
/// <returns>
/// The
/// </returns>
public ControlBill Freeze()
{
this.Account.Freeze(this.FreezeAmount);
this.UpdateFreezeStatus(FreezeStatus.冻结成功);
return this.CreateControlBill();
} /// <summary>
/// 修改冻结订单状态
/// </summary>
/// <param name="freezeStatus">冻结订单状态</param>
public void UpdateFreezeStatus(FreezeStatus freezeStatus)
{
this.FreezeStatus = freezeStatus;
} /// <summary>
/// 解冻
/// </summary>
/// <param name="thawAmount">解冻金额</param>
public void Thaw(decimal thawAmount)
{
if (thawAmount > this.FreezeAmount)
{
throw new AggregateException("抱歉!解冻金额大于冻结金额");
} if (thawAmount > this.FreezeAmount - this.ThawAmount)
{
throw new AggregateException("抱歉!解冻金额过大");
} this.ThawAmount += thawAmount;
} /// <summary>
/// The create control bill.
/// </summary>
/// <returns>
/// The <see cref="ControlBill"/>.
/// </returns>
private ControlBill CreateControlBill()
{
var bill = new ControlBill
{
Account = this.Account,
Balance = this.Account.Balance,
AvailableBalance = this.Account.AvailableBalance,
FreezeAmount = this.Account.FreezeAmount,
ControlAmount = this.FreezeAmount,
ControlDateTime = DateTime.Now,
ControlOrderNumber = this.FrezeOrderNumber,
ControlRemark = this.FreezeRemark,
ControlType = ControlType.Freeze,
OrderNumber = Builder.BuilderOrderNumber()
}; return bill;
}
}

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

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

         /// <summary>
/// 冻结
/// </summary>
/// <param name="freezeDTO">冻结信息</param>
public static void Freeze(FreezeDTO freezeDTO)
{
freezeDTO.ValidateFreezeDTO();
Account.Account account = QueryByAccountName(freezeDTO.FreezeNO);
FreezeOrder freezeOrder = Builder.BuilderFreezeOrder(account, freezeDTO);
ControlBill controlBill = freezeOrder.Freeze();
using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
{
IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
accountRepository.UpdateFreezeAmount(account); // 生成冻结订单
IFreezeOrderRepository freezeOrderRepository = Account.Factory.AccountFactory.CreateIFreezeOrderRepository(unitOfWork);
freezeOrderRepository.Add(freezeOrder); // 生成冻结账单
IControlBillRepository controlBillRepository = Account.Factory.AccountFactory.CreateIControlBillRepository(unitOfWork);
controlBillRepository.Add(controlBill); unitOfWork.Complete();
}
}

9.解冻

  解冻与冻结就相反了

  但是也是属于资金控制

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

     /// <summary>
/// 解冻订单
/// </summary>
public class ThawOrder : Control
{
/// <summary>
/// Initializes a new instance of the <see cref="ThawOrder"/> class.
/// </summary>
/// <param name="freezeOrder">
/// The freeze order.
/// </param>
public ThawOrder(FreezeOrder freezeOrder)
{
this.Initialization(freezeOrder);
} /// <summary>
/// Initializes a new instance of the <see cref="ThawOrder"/> class.
/// </summary>
/// <param name="thawId">
/// The thaw id.
/// </param>
/// <param name="freezeOrder">
/// The freeze order.
/// </param>
public ThawOrder(Guid thawId, FreezeOrder freezeOrder)
: base(thawId)
{
this.Initialization(freezeOrder);
} /// <summary>
/// The initialization.
/// </summary>
/// <param name="freezeOrder">
/// The freeze order.
/// </param>
private void Initialization(FreezeOrder freezeOrder)
{
this.FreezeOrder = freezeOrder;
this.Account = freezeOrder.Account;
} /// <summary>
/// 冻结订单
/// </summary>
public FreezeOrder FreezeOrder { get; private set; } /// <summary>
/// 冻结订单号
/// </summary>
public string ThawOrderNumber { get; set; } /// <summary>
/// 解冻状态
/// </summary>
public ThawStatus ThawStatus { get; set; } /// <summary>
/// 解冻金额
/// </summary>
public decimal ThawAmount { get; set; } /// <summary>
/// 备注
/// </summary>
public string ThawRemark { get; set; } /// <summary>
/// 修改解冻订单状态
/// </summary>
/// <param name="freezeStatus">冻结订单状态</param>
public void UpdateThawStatus(ThawStatus freezeStatus)
{
this.ThawStatus = freezeStatus;
} /// <summary>
/// 解冻
/// </summary>
/// <returns>账单</returns>
public ControlBill Thaw()
{
this.FreezeOrder.Thaw(this.ThawAmount);
this.Account.Thaw(this.ThawAmount);
this.UpdateThawStatus(ThawStatus.解冻成功);
return this.CreateControlBill();
} /// <summary>
/// The create control bill.
/// </summary>
/// <returns>
/// The <see cref="ControlBill"/>.
/// </returns>
private ControlBill CreateControlBill()
{
var bill = new ControlBill
{
Account = this.Account,
Balance = this.Account.Balance,
AvailableBalance = this.Account.AvailableBalance,
FreezeAmount = this.Account.FreezeAmount,
ControlAmount = this.ThawAmount,
ControlDateTime = DateTime.Now,
ControlOrderNumber = this.ThawOrderNumber,
ControlRemark = this.ThawRemark,
ControlType = ControlType.Thaw,
OrderNumber = Builder.BuilderOrderNumber()
}; return bill;
}
}

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

         /// <summary>
/// 解冻
/// </summary>
/// <param name="thawDTO">解冻信息</param>
public static void Thaw(ThawDTO thawDTO)
{
thawDTO.ValidateThawDTO();
FreezeOrder freezeOrder = QueryFreezeOrder(thawDTO.FreezeOrderNumber);
ThawOrder thawOrder = Builder.BuilderThawOrder(freezeOrder, thawDTO);
ControlBill controlBill = thawOrder.Thaw();
using (IUnitOfWork unitOfWork = Account.Factory.AccountFactory.CreateIUnitOfWork())
{
IAccountRepository accountRepository = Account.Factory.AccountFactory.CreateIAccountRepository(unitOfWork);
accountRepository.UpdateFreezeAmount(thawOrder.Account); // 生成解冻顶
IThawOrderRepsoitory thawOrderRepsoitory = Account.Factory.AccountFactory.CreateIThawOrderRepsoitory(unitOfWork);
thawOrderRepsoitory.Add(thawOrder); // 修改冻结订单
IFreezeOrderRepository freezeOrderRepository = Account.Factory.AccountFactory.CreateIFreezeOrderRepository(unitOfWork);
freezeOrderRepository.Update(freezeOrder); // 生成解冻账单
IControlBillRepository controlBillRepository = Account.Factory.AccountFactory.CreateIControlBillRepository(unitOfWork);
controlBillRepository.Add(controlBill); unitOfWork.Complete();
}
}

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

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

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

附源代码

 

 

 

   

   

  

c#领域驱动设计的更多相关文章

  1. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  2. DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?

    写在前面 阅读目录: 具体业务场景 业务需求变化 "愚蠢"的应对 消息列表实现 消息详情页实现 消息发送.回复.销毁等实现 回到原点的一些思考 业务需求变化,领域模型变化了吗? 对 ...

  3. DDD 领域驱动设计-商品建模之路

    最近在做电商业务中,有关商品业务改版的一些东西,后端的架构设计采用现在很流行的微服务,有关微服务的简单概念: 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独 ...

  4. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...

  5. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  6. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  7. [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店

    一.前言 在前面专题一中,我已经介绍了我写这系列文章的初衷了.由于dax.net中的DDD框架和Byteart Retail案例并没有对其形成过程做一步步分析,而是把整个DDD的实现案例展现给我们,这 ...

  8. 领域驱动设计实战—基于DDDLite的权限管理OpenAuth.net

    在园子里面,搜索一下“权限管理”至少能得到上千条的有效记录.记得刚开始工作的时候,写个通用的权限系统一直是自己的一个梦想.中间因为工作忙(其实就是懒!)等原因,被无限期搁置了.最近想想,自己写东西时, ...

  9. 我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践

    写在前面 插一句:本人超爱落网-<平凡的世界>这一期,分享给大家. 阅读目录: 关于DDD 前期分析 框架搭建 代码实现 开源-发布 后记 第一次听你,清风吹送,田野短笛:第一次看你,半弯 ...

  10. 一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?

    写在前面 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repository(仓储)职责所在? Domain Model(领域模型)重新设计 Domain ...

随机推荐

  1. 【Mac】-NO.161.Mac.1 -【MacOS Error running 'Tomcat 8.5.371': Cannot run program Permission denied】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  2. JavaWeb学习之三层架构实例(三)

    引言 通过上一篇博客JavaWeb学习之三层架构实例(二)我们基本上已经实现了对学生信息列表的增删改查操作(UI除外),但是不难看出,代码冗余度太高了,尤其是StudentDao这个类,其中的增删改查 ...

  3. centOS 7 设置DNS方法 同之前版本不同

    在CentOS 7下,手工设置 /etc/resolv.conf 里的DNS,过了一会,发现被系统重新覆盖或者清除了.和CentOS 6下的设置DNS方法不同,有几种方式: 1.使用全新的命令行工具 ...

  4. 构造方法,this关键字,static关键字,封装,静态变量

    1.构造方法 构造方法是一种特殊的方法,是专门用于创建/实例化对象的方法. 构造方法根据是否有参数分为两类:1.无参构造方法  2.有参构造方法 1.1无参构造方法 无参构造方法就是构造方法中没有参数 ...

  5. leetcode网学习笔记(1)

    https://leetcode-cn.com/problems/reverse-linked-list/submissions/ 206 反转链表 错误原因:没有考虑到链表为空以及链表只有一个元素的 ...

  6. JDK8 HashMap--removeNode()移除节点方法

    /*删除节点*/ final Node<K,V> removeNode(int hash, Object key, Object value, boolean matchValue, bo ...

  7. python练习--利用while循环和if语句,完成猜骰子的数字大小

    #exampleimport random# 骰子投掷的随机叔numnum = random.randint(1,6)# 输入一个猜测的数字temp = input("请输入一个整数:&qu ...

  8. codeforces-3

    C Game"23" #include<iostream> using namespace std; int main() { long long n,m; long ...

  9. redis 字符串(string)函数

    字符串(string)函数 get 命令/方法/函数 Description Get the value related to the specified key 取得与指定的键值相关联的值 Para ...

  10. 2018-2019-2 20165305《网络攻防技术》Exp5 MSF基础应用

    1. 实践内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践,如ms08_067; (1分) 1.2 一个针对浏览器的攻击, ...