您的位置:首页 > 其它

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

2016-05-31 19:02 417 查看

转自 http://www.cnblogs.com/retop/p/5193394.html

理论介绍

在进行数据库添加、修改、删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败。例如银行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     }


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     }


后记

该实现中并未实现对多表进行的联合查询,使用Lambda的方式去多表查询,有点自己写一个ORM的性质,由于Lz能力有限,顾有需求的园友可以自行扩展或者使用ORM,若有实现自行扩展的园友,望指教。

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

源码网盘地址:链接:http://pan.baidu.com/s/1hqXJ3GK 密码:o0he
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: