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(代碼優先)

     最后要做的就是根據領域對象去設計數據庫就行

     附源代碼

 

 

    

  

 

   

   

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM