【.Net设计模式系列】工作单元(Unit Of Work)模式 ( 二 )

回顾

在上一篇博客【.Net设计模式系列】仓储(Repository)模式 ( 一 ) 中,通过各位兄台的评论中,可以看出在设计上还有很多的问题,在这里特别感谢 @横竖都溢 @ 浮云飞梦 2位兄台对博文中存在的问题给予指出,并提供出好的解决方案,同时也感谢其他园友的支持。欢迎各位园友对博文中出现的错误或者是设计误区给予指出,一方面防止“误人子弟”,另一方面则可以让大家共同成长。

对于上一篇博客,只是给大家提供了一种对于小型项目数据访问层的一种实现方式,通过Sql语句和传递参数来实现CRUD。并未达到真正意义上的解耦。特此在本篇继续完善。

理论介绍

在进行数据库添加、修改、删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败。例如银行A、B两个账户的转账业务。一方失败都会导致事务的不完整性,从而事务回滚。而工作单元模式可以跟踪事务,在操作完成时对事务进行统一提交。

理论参考:http://martinfowler.com/eaaCatalog/unitOfWork.html

具体实践

首先,讲解下设计思想:领域层通过相应的库实现泛型仓储接口来持久化聚合类,之后在抽象库中将对泛型仓储接口提供基础实现,并将对应的实体转化为SQl语句。这样领域层就不需要操作Sql语句即可完成CRUD操作,同时使用工作单元对事务进行统一提交。

1)定义仓储接口,包含基本的CRUD操作及其重载不同的查询

 1 public interface IRepository<T>
 2     {
 3         /// <summary>
 4         /// 插入对象
 5         /// </summary>
 6         /// <param name="entity"></param>
 7         int Insert(T entity);
 8
 9         /// <summary>
10         /// 更新对象
11         /// </summary>
12         /// <param name="entity"></param>
13         /// <param name="predicate"></param>
14         int Update(T entity, Expression<Func<T, bool>> express);
15
16         /// <summary>
17         /// 删除对象
18         /// </summary>
19         /// <param name="predicate"></param>
20         int Delete(Expression<Func<T, bool>> express = null);
21
22         /// <summary>
23         /// 查询对象集合
24         /// </summary>
25         /// <param name="predicate"></param>
26         /// <returns></returns>
27         List<T> QueryAll(Expression<Func<T, bool>> express = null);
28
29         /// <summary>
30         /// 查询对象集合
31         /// </summary>
32         /// <param name="index"></param>
33         /// <param name="pagesize"></param>
34         /// <param name="order"></param>
35         /// <param name="asc"></param>
36         /// <param name="express"></param>
37         /// <returns></returns>
38         List<T> QueryAll(int index,int pagesize,List<PropertySortCondition> orderFields, Expression<Func<T, bool>> express = null);
39
40         /// <summary>
41         /// 查询对象集合
42         /// </summary>
43         /// <param name="type"></param>
44         /// <param name="predicate"></param>
45         /// <returns></returns>
46         List<object> QueryAll(Type type, Expression<Func<T, bool>> express = null);
47
48         /// <summary>
49         /// 查询对象
50         /// </summary>
51         /// <param name="predicate"></param>
52         /// <returns></returns>
53         T Query(Expression<Func<T, bool>> express);
54
55         /// <summary>
56         /// 查询数量
57         /// </summary>
58         /// <param name="predicate"></param>
59         /// <returns></returns>
60         object QueryCount(Expression<Func<T, bool>> express = null);
61     }

其次,对仓储接口提供基本实现,这里由于使用了Lambda表达式,所以就需要进行表达式树的解析。

  1  public abstract class BaseRepository<T> : IRepository<T>
  2         where T:class,new()
  3     {
  4         private IUnitOfWork unitOfWork;
  5
  6         private IUnitOfWorkContext context;
  7
  8         public BaseRepository(IUnitOfWork unitOfWork, IUnitOfWorkContext context)
  9         {
 10             this.unitOfWork = unitOfWork;
 11             this.context = context;
 12         }
 13
 14         Lazy<ConditionBuilder> builder = new Lazy<ConditionBuilder>();
 15
 16         public string tableName {
 17             get
 18             {
 19                 TableNameAttribute attr= (TableNameAttribute)typeof(T).GetCustomAttribute(typeof(TableNameAttribute));
 20                 return attr.Name;
 21             }
 22         }
 23
 24         /// <summary>
 25         /// 插入对象
 26         /// </summary>
 27         /// <param name="entity"></param>
 28         public virtual int Insert(T entity)
 29         {
 30             Func<PropertyInfo[], string, IDictionary<string, object>, int> excute = (propertys, condition, parameters) =>
 31             {
 32                 List<string> names = new List<string>();
 33                 foreach (PropertyInfo property in propertys)
 34                 {
 35                     if (property.GetCustomAttribute(typeof(IncrementAttribute)) == null)
 36                     {
 37                         string attrName = property.Name;
 38                         object value = property.GetValue(entity);
 39                         names.Add(string.Format("@{0}", attrName));
 40                         parameters.Add(attrName, value);
 41                     }
 42                 }
 43                 string sql = "Insert into {0} values({1})";
 44                 string combineSql = string.Format(sql, tableName, string.Join(",", names), builder.Value.Condition);
 45                 return unitOfWork.Command(combineSql, parameters);
 46             };
 47             return CreateExcute<int>(null, excute);
 48         }
 49
 50         /// <summary>
 51         /// 修改对象
 52         /// </summary>
 53         /// <param name="entity"></param>
 54         /// <param name="express"></param>
 55         public virtual int Update(T entity, Expression<Func<T, bool>> express)
 56         {
 57
 58             Func<PropertyInfo[], string, IDictionary<string, object>, int> excute = (propertys, condition, parameters) =>
 59             {
 60                 List<string> names = new List<string>();
 61                 foreach (PropertyInfo property in propertys)
 62                 {
 63                     if (property.GetCustomAttribute(typeof(IncrementAttribute)) == null)
 64                     {
 65                         string attrName = property.Name;
 66                         object value = property.GetValue(entity);
 67                         names.Add(string.Format("{0}[email protected]{1}", attrName, attrName));
 68                         parameters.Add(attrName, value);
 69                     }
 70                 }
 71                 string sql = "update {0} set {1} where {2}";
 72                 string combineSql = string.Format(sql, tableName, string.Join(",", names), builder.Value.Condition);
 73                 return unitOfWork.Command(combineSql, parameters);
 74             };
 75             return CreateExcute<int>(express, excute);
 76         }
 77         /// <summary>
 78         /// 删除对象
 79         /// </summary>
 80         /// <param name="express"></param>
 81         public virtual int Delete(Expression<Func<T, bool>> express = null)
 82         {
 83             Func<PropertyInfo[], string, IDictionary<string, object>, int> excute = (propertys, condition, parameters) =>
 84             {
 85                 string sql = "delete from {0} {1}";
 86                 string combineSql = string.Format(sql, tableName, condition);
 87                 return unitOfWork.Command(combineSql, parameters);
 88             };
 89             return CreateExcute<int>(express, excute);
 90         }
 91
 92         /// <summary>
 93         /// 查询对象集合
 94         /// </summary>
 95         /// <param name="express"></param>
 96         /// <returns></returns>
 97         public virtual List<T> QueryAll(Expression<Func<T, bool>> express = null)
 98         {
 99             Func<PropertyInfo[], string, IDictionary<string, object>, List<T>> excute = (propertys, condition, parameters) =>
100             {
101                 string sql = "select {0} from {1} {2}";
102                 string combineSql = string.Format(sql, string.Join(",", propertys.Select(x => x.Name)), tableName, condition);
103                 return context.ReadValues<T>(combineSql, parameters);
104             };
105             return CreateExcute<List<T>>(express, excute);
106         }
107
108         /// <summary>
109         /// 查询对象集合(分页)
110         /// </summary>
111         /// <param name="index"></param>
112         /// <param name="pagesize"></param>
113         /// <param name="order"></param>
114         /// <param name="asc"></param>
115         /// <param name="express"></param>
116         /// <returns></returns>
117         public virtual List<T> QueryAll(int index,int pagesize,List<PropertySortCondition> orderFields,Expression<Func<T, bool>> express = null)
118         {
119             Func<PropertyInfo[], string, IDictionary<string, object>, List<T>> excute = (propertys, condition, parameters) =>
120             {
121                 if (orderFields == null) { throw new Exception("排序字段不能为空"); }
122                 string sql = "select * from (select {0} , ROW_NUMBER() over(order by {1}) as rownum from {2} {3}) as t where t.rownum >= {4} and t.rownum < {5}";
123                 string combineSql = string.Format(sql, string.Join(",", propertys.Select(x => x.Name)),string.Join(",", orderFields), tableName, condition, (index - 1) * pagesize + 1, index * pagesize);
124                 return context.ReadValues<T>(combineSql, parameters);
125             };
126             return CreateExcute<List<T>>(express, excute);
127         }
128
129         /// <summary>
130         /// 查询对象集合
131         /// </summary>
132         /// <param name="type"></param>
133         /// <param name="express"></param>
134         /// <returns></returns>
135         public virtual List<object> QueryAll(Type type, Expression<Func<T, bool>> express = null)
136         {
137             Func<PropertyInfo[], string, IDictionary<string, object>, List<object>> excute = (propertys, condition, parameters) =>
138             {
139                 string sql = "select {0} from {1} {2}";
140                 string combineSql = string.Format(sql, string.Join(",", propertys.Select(x => x.Name)), tableName, condition);
141                 return context.ReadValues(combineSql, type, parameters);
142             };
143             return CreateExcute<List<object>>(express, excute);
144         }
145
146         /// <summary>
147         /// 查询对象
148         /// </summary>
149         /// <param name="express"></param>
150         /// <returns></returns>
151         public virtual T Query(Expression<Func<T, bool>> express)
152         {
153             Func<PropertyInfo[], string, IDictionary<string, object>, T> excute = (propertys, condition, parameters) =>
154             {
155                 string sql = "select {0} from {1} {2}";
156                 string combineSql = string.Format(sql, string.Join(",", propertys.Select(x => x.Name)), tableName, condition);
157                 return context.ExecuteReader<T>(combineSql, parameters);
158             };
159             return CreateExcute<T>(express, excute);
160         }
161
162         /// <summary>
163         /// 查询数量
164         /// </summary>
165         /// <param name="express"></param>
166         /// <returns></returns>
167         public virtual object QueryCount(Expression<Func<T, bool>> express = null)
168         {
169             Func<PropertyInfo[], string, IDictionary<string, object>, object> excute = (propertys, condition, parameters) =>
170             {
171                 string sql = "select * from {0} {1}";
172                 string combineSql = string.Format(sql, string.Join(",", propertys.Select(x => x.Name)), tableName, condition);
173                 return context.ExecuteScalar(combineSql, parameters);
174             };
175
176             return CreateExcute<object>(express, excute);
177         }
178
179         private TValue CreateExcute<TValue>(Expression<Func<T, bool>> express, Func<PropertyInfo[], string, IDictionary<string, object>, TValue> excute)
180         {
181             Dictionary<string, object> parameters = new Dictionary<string, object>();
182             PropertyInfo[] propertys = typeof(T).GetProperties();
183             string condition = "";
184             if (express != null)
185             {
186                 builder.Value.Build(express, tableName);
187                 condition = string.Format("where {0} ", builder.Value.Condition);
188                 for (int i = 0; i < builder.Value.Arguments.Length; i++)
189                 {
190                     parameters.Add(string.Format("Param{0}", i), builder.Value.Arguments[i]);
191                 }
192             }
193             return excute(propertys, condition, parameters);
194         }
195     }

接下来,定义工作单元,所有的添加、删除、修改操作都会被储存到工作单元中。

 1 public interface IUnitOfWork
 2     {
 3         /// <summary>
 4         /// 命令
 5         /// </summary>
 6         /// <param name="commandText"></param>
 7         /// <param name="parameters"></param>
 8         /// <returns></returns>
 9         int Command(string commandText, IDictionary<string, object> parameters);
10
11         /// <summary>
12         /// 事务的提交状态
13         /// </summary>
14         bool IsCommited { get; set; }
15
16         /// <summary>
17         /// 提交事务
18         /// </summary>
19         /// <returns></returns>
20         void Commit();
21
22         /// <summary>
23         /// 回滚事务
24         /// </summary>
25         void RollBack();
26     }

接下来是对工作单元的实现,其内部维护了一个命令集合,存储Sql语句。

 1 public class UnitOfWork:IUnitOfWork
 2     {
 3         /// <summary>
 4         /// 注入对象
 5         /// </summary>
 6         private IUnitOfWorkContext context;
 7
 8         /// <summary>
 9         /// 维护一个Sql语句的命令列表
10         /// </summary>
11         private List<CommandObject> commands;
12
13         public UnitOfWork(IUnitOfWorkContext context)
14         {
15             commands = new List<CommandObject>();
16             this.context = context;
17         }
18
19         /// <summary>
20         /// 增、删、改命令
21         /// </summary>
22         /// <param name="commandText"></param>
23         /// <param name="parameters"></param>
24         /// <returns></returns>
25         public int Command(string commandText, IDictionary<string, object> parameters)
26         {
27             IsCommited = false;
28             commands.Add(new CommandObject(commandText, parameters));
29             return 1;
30         }
31
32         /// <summary>
33         /// 提交状态
34         /// </summary>
35         public bool IsCommited{ get; set; }
36
37         /// <summary>
38         /// 提交方法
39         /// </summary>
40         /// <returns></returns>
41         public void Commit()
42         {
43             if (IsCommited) { return ; }
44             using (TransactionScope scope = new TransactionScope())
45             {
46                 foreach (var command in commands)
47                 {
48                     context.ExecuteNonQuery(command.command, command.parameters);
49                 }
50                 scope.Complete();
51                 IsCommited = true;
52             }
53         }
54
55         /// <summary>
56         /// 事务回滚
57         /// </summary>
58         public void RollBack()
59         {
60             IsCommited = false;
61         }
62     }

最后定义工作单元对事务提交处理的上下文及其实现,同仓储模式中的代码。

 1 public interface IUnitOfWorkContext
 2     {
 3
 4         /// <summary>
 5         /// 注册新对象到上下文
 6         /// </summary>
 7         /// <param name="commandText"></param>
 8         /// <param name="parameters"></param>
 9         int ExecuteNonQuery(string commandText, IDictionary<string, object> parameters = null);
10
11         /// <summary>
12         ///  查询对象集合
13         /// </summary>
14         /// <typeparam name="T"></typeparam>
15         /// <param name="commandText"></param>
16         /// <param name="parameters"></param>
17         /// <param name="load">自定义处理</param>
18         /// <returns></returns>
19         List<T> ReadValues<T>(string commandText, IDictionary<string, object> parameters = null, Func<IDataReader, T> load = null) where T : class, new();
20
21         /// <summary>
22         /// 查询对象集合
23         /// </summary>
24         /// <param name="commandText"></param>
25         /// <param name="type"></param>
26         /// <param name="parameters"></param>
27         /// <param name="setItem"></param>
28         /// <returns></returns>
29         List<object> ReadValues(string commandText, Type type, IDictionary<string, object> parameters = null, Action<dynamic> setItem = null);
30
31         /// <summary>
32         /// 查询对象
33         /// </summary>
34         /// <typeparam name="TEntity"></typeparam>
35         /// <param name="commandText"></param>
36         /// <param name="parameters"></param>
37         /// <param name="excute"></param>
38         /// <returns></returns>
39         T ExecuteReader<T>(string commandText, IDictionary<string, object> parameters = null, Func<IDataReader, T> load = null) where T : class,new();
40
41         /// <summary>
42         /// 查询数量
43         /// </summary>
44         /// <param name="commandText"></param>
45         /// <param name="parameters"></param>
46         /// <returns></returns>
47         object ExecuteScalar(string commandText, IDictionary<string, object> parameters = null);
48     }

最后实现。

  1 public abstract class UnitOfWorkContext : IUnitOfWorkContext,IDisposable
  2     {
  3         /// <summary>
  4         /// 数据库连接字符串标识
  5         /// </summary>
  6         public abstract string Key { get; }
  7
  8         private SqlConnection connection;
  9
 10         private SqlConnection Connection
 11         {
 12             get
 13             {
 14                 if (connection == null)
 15                 {
 16                     ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[Key];
 17                     connection = new SqlConnection(settings.ConnectionString);
 18                 }
 19                 return connection;
 20             }
 21         }
 22
 23         /// <summary>
 24         /// 注册新对象到事务
 25         /// </summary>
 26         /// <typeparam name="TEntity"></typeparam>
 27         /// <param name="entity"></param>
 28         public int ExecuteNonQuery(string commandText, IDictionary<string, object> parameters = null)
 29         {
 30             Func<SqlCommand, int> excute = (commend) =>
 31             {
 32                 return commend.ExecuteNonQuery();
 33             };
 34             return CreateDbCommondAndExcute<int>(commandText, parameters, excute);
 35         }
 36
 37         /// <summary>
 38         /// 查询对象集合
 39         /// </summary>
 40         /// <typeparam name="T"></typeparam>
 41         /// <param name="commandText"></param>
 42         /// <param name="parameters"></param>
 43         /// <param name="load">自定义处理</param>
 44         /// <returns>泛型实体集合</returns>
 45
 46         public List<T> ReadValues<T>(string commandText, IDictionary<string, object> parameters = null, Func<IDataReader, T> load = null) where T : class,new()
 47         {
 48             Func<SqlCommand, List<T>> excute = (dbCommand) =>
 49             {
 50                 List<T> result = new List<T>();
 51                 using (IDataReader reader = dbCommand.ExecuteReader())
 52                 {
 53                     while (reader.Read())
 54                     {
 55                         if (load == null)
 56                         {
 57                             load = (s) => { return s.GetReaderData<T>(); };
 58                         }
 59                         var item = load(reader);
 60                         result.Add(item);
 61                     }
 62                     return result;
 63                 }
 64             };
 65             return CreateDbCommondAndExcute(commandText, parameters, excute);
 66         }
 67
 68         /// <summary>
 69         /// 查询对象集合
 70         /// </summary>
 71         /// <param name="commandText"></param>
 72         /// <param name="parameters"></param>
 73         /// <param name="setItem"></param>
 74         /// <returns></returns>
 75         public List<object> ReadValues(string commandText, Type type, IDictionary<string, object> parameters = null, Action<dynamic> setItem = null)
 76         {
 77             Func<SqlCommand, List<object>> excute = (dbCommand) =>
 78             {
 79                 var result = new List<object>();
 80
 81                 using (IDataReader dataReader = dbCommand.ExecuteReader())
 82                 {
 83                     while (dataReader.Read())
 84                     {
 85                         var item = dataReader.GetReaderData(type);
 86                         if (setItem != null)
 87                         {
 88                             setItem(item);
 89                         }
 90                         result.Add(item);
 91                     }
 92                 }
 93                 return result;
 94             };
 95             return CreateDbCommondAndExcute<List<object>>(commandText, parameters,
 96                 excute);
 97         }
 98
 99         /// <summary>
100         /// 查询对象
101         /// </summary>
102         /// <typeparam name="TEntity"></typeparam>
103         /// <param name="commandText"></param>
104         /// <param name="parameters"></param>
105         /// <param name="excute"></param>
106         /// <returns></returns>
107         public T ExecuteReader<T>(string commandText, IDictionary<string, object> parameters = null, Func<IDataReader, T> load = null) where T : class,new()
108         {
109             Func<SqlCommand, T> excute = (dbCommand) =>
110             {
111                 var result = default(T);
112                 using (IDataReader reader = dbCommand.ExecuteReader())
113                 {
114                     while (reader.Read())
115                     {
116                         if (load == null)
117                         {
118                             load = (s) => { return s.GetReaderData<T>(); };
119                         }
120                         result = load(reader);
121                     }
122                     return result;
123                 }
124             };
125             return CreateDbCommondAndExcute<T>(commandText, parameters, excute);
126         }
127
128         /// <summary>
129         /// 查询数量
130         /// </summary>
131         /// <param name="commandText"></param>
132         /// <param name="parameters"></param>
133         /// <returns></returns>
134         public object ExecuteScalar(string commandText, IDictionary<string, object> parameters = null)
135         {
136             Func<SqlCommand, object> excute = (dbCommand) =>
137             {
138                 return dbCommand.ExecuteScalar();
139             };
140             return CreateDbCommondAndExcute(commandText, parameters, excute);
141         }
142
143         /// <summary>
144         /// 创建命令并执行
145         /// </summary>
146         /// <typeparam name="TValue"></typeparam>
147         /// <param name="commandText"></param>
148         /// <param name="parameters"></param>
149         /// <param name="excute"></param>
150         /// <returns></returns>
151         private TValue CreateDbCommondAndExcute<TValue>(string commandText,
152             IDictionary<string, object> parameters, Func<SqlCommand, TValue> excute)
153         {
154             if (Connection.State == ConnectionState.Closed) { Connection.Open(); };
155             using (SqlCommand command = new SqlCommand())
156             {
157                 command.CommandType = CommandType.Text;
158                 command.CommandText = commandText;;
159                 command.Connection = Connection;
160                 command.SetParameters(parameters);
161                 return excute(command);
162             }
163         }
164
165         /// <summary>
166         /// 关闭连接
167         /// </summary>
168         public void Dispose()
169         {
170             if (connection != null)
171             {
172                 Connection.Dispose();//非托管资源
173             }
174         }
175     }

在调用方法时需要注意,一个事务涉及多个聚合时,需要保证传递同一工作单元,并在方法的最后调用Commit() 方法。

 1 public class Services : IService
 2     {
 3         private IMemberRespository member;
 4
 5         private IUnitOfWork unitOfWork;
 6
 7         public Services(IMemberRespository member, IUnitOfWork unitOfWork)
 8         {
 9             this.member = member;
10             this.unitOfWork = unitOfWork;
11         }
12
13         /// <summary>
14         /// 测试用例
15         /// </summary>
16         public void Demo()
17         {
18
19             member.Test();
20
21             unitOfWork.Commit();
22         }
23     }

后记

至此,既实现对数据访问层和领域层解耦,如果园友对我的比较认可,欢迎尝试去使用,在使用中遇到什么问题或有什么好的意见,也希望及时反馈给我。若某些园友不太认可我的设计,也希望批评指出。

时间: 02-14

【.Net设计模式系列】工作单元(Unit Of Work)模式 ( 二 )的相关文章

工作单元(Unit Of Work)模式 ( 二 )

转自 http://www.cnblogs.com/retop/p/5193394.html 理论介绍 在进行数据库添加.修改.删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败.例如银行A.B两个账户的转账业务.一方失败都会导致事务的不完整性,从而事务回滚.而工作单元模式可以跟踪事务,在操作完成时对事务进行统一提交. 理论参考:http://martinfowler.com/eaaCatalog/unitOfWork.html 具体实践 首先,讲解下设计思想:领域层通过相应的库实现

基于DDD的.NET开发框架 - ABP工作单元(Unit of Work)

返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板. ABP的官方网站:http://www.aspnetboilerplate.com ABP官方文档:http://www.aspnetboilerplate.com/Pages/Documents Github上的开源项目:http

工作单元 — Unit Of Work

在进行数据库添加.修改.删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败.例如银行A.B两个账户的转账业务.一方失败都会导致事务的不完整性,从而事务回滚.而工作单元模式可以跟踪事务,在操作完成时对事务进行统一提交. 具体实践 首先,讲解下设计思想:领域层通过相应的库实现泛型仓储接口来持久化聚合类,之后在抽象库中将对泛型仓储接口提供基础实现,并将对应的实体转化为SQl语句.这样领域层就不需要操作Sql语句即可完成CRUD操作,同时使用工作单元对事务进行统一提交. 1)定义仓储接口,包

菜鸟学设计模式系列笔记之适配器模式(adapter模式)

一.结构模式简介: 在面向对象软件系统中,每个类都承担了一定的职责,它们可以相互协作,实现一些复杂的功能 结构型模式关注的是如何将现有类或对象组织在一起形成更加强大的结构 不同的结构型模式从不同的角度来组合类和对象 1.结构模式描述如何将类或者对象结合在一起形成更大的结构 (1)类的结构模式:类的结构模式使用继承把类.接口等组合在一起,以形成更大的结构.当一个类从父类继承并实现某接口时,这个新的类就把父类的结构和接口的结构组合起来.类的结构模式是静态的. (2)对象的结构模式:对象的结构模式描述

PHP设计模式系列(一):策略模式

策略模式 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法.组成 抽象策略角色:策略类,通常由一个接口或者抽象类实现.    具体策略角色:包装了相关的算法和行为.    环境角色:持有一个策略类的引用,最终给客户端调用. 实现结构图 步骤 定义抽象角色类(定义好各个实现的共同抽象方法)    定义具体策略类(具体实现父类的共同方法)    定义环境角色

ABP(现代ASP.NET样板开发框架)系列之12、ABP领域层——工作单元(Unit Of work)

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之12.ABP领域层——工作单元(Unit Of work) ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 通用连接和事务管理方法 连接和事务管理是使用数据库的应用程

ABP领域层——工作单元(Unit Of work)

ABP领域层——工作单元(Unit Of work) 点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之12.ABP领域层——工作单元(Unit Of work) ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 通用

ABP领域层——工作单元

仓储类,应用服务,[UnitOfWork] ABP开启了一个数据库连接并且在进入到仓储方法时会启用一个事务.因此, 你可以安全地使用连接于仓储方法中.在仓储方法结束后,事务会被提交并且 会释放掉连接.假如仓储方法抛出任何异常,事务会被回滚并且释放掉连接. 在这个模式中,仓储方法是单元性的(一个工作单元unit of work) public class TaskRepository : TestRepositoryBase<ETask, long>, ITaskRepository { pub

解析ABP框架中的事务处理和工作单元,ABP事务处理

通用连接和事务管理方法连接和事务管理是使用数据库的应用程序最重要的概念之一.当你开启一个数据库连接,什么时候开始事务,如何释放连接...诸如此类的. 正如大家都知道的,.Net使用连接池(connection pooling).因此,创建一个连接实际上是从连接池中取得一个连接,会这么做是因为创建新连接会有成本.如果没有任何连接存在于连接池中,一个新的连接对象会被创建并且添加到连接池中.当你释放连接,它实际上是将这个连接对象送回到连接池.这并不是实际意义上的释放.这个机制是由.Net所提供的.因此