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(代码优先)

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

     附源代码