新的IRepository接口+搜索和排序解耦(+基于Castle实现)

时间:2023-03-08 23:58:07
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

新的IRepository接口+搜索和排序解耦(+基于Castle实现)

经过了上篇IRepositoryIRepository<T>的讨论【文章地址为:http://www.cnblogs.com/yomho/p/3296759.html

我选择了IRepository作为我重构框架的仓储接口

一、接口定义  

新的IRepository接口设计如下:

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
 1 namespace Yom.NFramework2_0
2 {
3 public interface IRepository<TCompositeKey>
4 where TCompositeKey : IEquatable<string>
5 {
6 #region 实体操作接口
7 T FindBy<T>(TCompositeKey primaryKey) where T : IEntity;
8 IEnumerable<T> FindAll<T>() where T : IEntity;
9 IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity;
10 IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity;
11 IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity;
12 void Add<T>(T entity) where T : IEntity;
13 void Delete<T>(T entity) where T : IEntity;
14 void DeleteAll<T>() where T : IEntity;
15 void DeleteAll<T>(IWhere[] where) where T : IEntity;
16 void DeleteAll<T>(string where) where T : IEntity;
17 void DeleteAll<T>(IEnumerable<TCompositeKey> pkValues) where T : IEntity;
18 void Update<T>(T entity) where T : IEntity;
19 bool Exists<T>(TCompositeKey primaryKey) where T : IEntity;
20 #endregion
21 #region 静态方法接口
22 int ExecuteSql(string sql, params System.Data.IDataParameter[] ps);
23 object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps);
24 System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps);
25 #endregion
26 }
27 }
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

其中IEntity和IWhere以及IOrder的设计接口如下:

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
public interface IEntity
{
}
public interface IOrder
{
}
public interface IWhere
{
}
public interface ICompositeKey : IEquatable<string>
{
}
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

ICompositeKey为组合主键接口

为什么ICompositeKey要继承为IEquatable<string>这个接口呢?

因为IEquatable<string>是string的基类,且string为不能继承的类,

所以目的是和string兼容,经过处理可以变成一个string类,从而可以兼容普通的非组合主键。

(此文不讲组合主键的实现原理,展示组合主键接口只是让大家看看组合主键实现解耦的方法)

二、嫁接Castle实现搜索以及排序

很多人不知道怎么把自己的IRepository接口的排序和搜索对象解耦,

在用不同的ORM实现IRepository接口的时候总不知道怎么弄排序和搜索

下面就来看我怎么把Castle的排序和搜索用IOrder以及IWhere解耦的

首先是IOrder -> NHibernate.Expression.Order 的变身

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
1 namespace Yom.NFramework2_0.CastleExtend
2 {
3 public class OrderBase : NHibernate.Expression.Order, Yom.NFramework2_0.IOrder
4 {
5 public OrderBase(string propertyName, bool ascending) : base(propertyName, ascending) {
6
7 }
8 }
9 }
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

这个很简单,OrderBase一下子就变成了NHibernate.Expression.Order

那么IWhere是否可以顺利完成像IOrder这种变身么?

研究后发现:Castle是用NHibernate.Expression.Expression的静态方法创建查询对象的

静态方法都是返回NHibernate.Expression.AbstractCriterion抽象类或者ICriterion接口

可以继承这个抽象对象或者接口吧,这样就可以实现变身了!!!

但如果真要这样做,必然有抽象方法要实现,这实在是一个下下策(想嫁接个接口和抽象类不容易吖)

那有没有直接实现NHibernate.Expression.AbstractCriterion抽象类的类呢?

反正我是没有找到,但是Castle肯定有,如果找到这么个类,就可以像IOrder一样实现嫁接,现在没有发现只能想他法。

最后我对WhereBase的变身是:

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
  1 namespace Yom.NFramework2_0.CastleExtend
2 {
3 public class WhereBase : Yom.NFramework2_0.IWhere
4 {
5 public NHibernate.Expression.ICriterion Instance
6 {
7 get;
8 set;
9 }
10 public override string ToString()
11 {
12 return Instance.ToString();
13 }
14 #region 废弃代码
15 //public static void AllEq(WhereBase where, System.Collections.IDictionary propertyNameValues)
16 //{
17 // where.Instance = NHibernate.Expression.Expression.AllEq(propertyNameValues);
18 //}
19 //public static void And(WhereBase where, WhereBase whereA, WhereBase whereB)
20 //{
21 // where.Instance = NHibernate.Expression.Expression.And(whereA.Instance, whereB.Instance);
22 //}
23 //public static void Between(WhereBase where, string propertyName, object lo, object hi)
24 //{
25 // where.Instance = NHibernate.Expression.Expression.Between(propertyName, lo, hi);
26 //}
27 //public static void Eq(WhereBase where, string propertyName, object value) {
28 // where.Instance = NHibernate.Expression.Expression.Eq(propertyName, value);
29 //}
30 //public static void EqProperty(WhereBase where, string propertyName, string otherPropertyName)
31 //{
32 // where.Instance = NHibernate.Expression.Expression.EqProperty(propertyName, otherPropertyName);
33 //}
34 //public static void Ge(WhereBase where, string propertyName, object value)
35 //{
36 // where.Instance = NHibernate.Expression.Expression.Ge(propertyName, value);
37 //}
38 //public static void GeProperty(WhereBase where, string propertyName, string otherPropertyName)
39 //{
40 // where.Instance = NHibernate.Expression.Expression.GeProperty(propertyName, otherPropertyName);
41 //}
42 //public static void Gt(WhereBase where, string propertyName, object value)
43 //{
44 // where.Instance = NHibernate.Expression.Expression.Gt(propertyName, value);
45 //}
46 //public static void GtProperty(WhereBase where, string propertyName, string otherPropertyName)
47 //{
48 // where.Instance = NHibernate.Expression.Expression.GtProperty(propertyName, otherPropertyName);
49 //}
50 //public static void IdEq(WhereBase where, object value)
51 //{
52 // where.Instance = NHibernate.Expression.Expression.IdEq(value);
53 //}
54 //public static void In(WhereBase where, string propertyName, System.Collections.ICollection values)
55 //{
56 // where.Instance = NHibernate.Expression.Expression.In(propertyName, values);
57 //}
58 //public static void InG<T>(WhereBase where, string propertyName, ICollection<T> values)
59 //{
60 // where.Instance = NHibernate.Expression.Expression.InG<T>(propertyName, values);
61 //}
62 //public static void InsensitiveLike(WhereBase where, string propertyName, object value)
63 //{
64 // where.Instance = NHibernate.Expression.Expression.InsensitiveLike(propertyName, value);
65 //}
66 //public static void IsEmpty(WhereBase where, string propertyName)
67 //{
68 // where.Instance = NHibernate.Expression.Expression.IsEmpty(propertyName);
69 //}
70 //public static void propertyName(WhereBase where, string propertyName)
71 //{
72 // where.Instance = NHibernate.Expression.Expression.IsNotEmpty(propertyName);
73 //}
74 //public static void IsNotNull(WhereBase where, string propertyName)
75 //{
76 // where.Instance = NHibernate.Expression.Expression.IsNotNull(propertyName);
77 //}
78 //public static void IsNull(WhereBase where, string propertyName)
79 //{
80 // where.Instance = NHibernate.Expression.Expression.IsNull(propertyName);
81 //}
82 //public static void Le(WhereBase where, string propertyName, object value)
83 //{
84 // where.Instance = NHibernate.Expression.Expression.Le(propertyName, value);
85 //}
86 //public static void LeProperty(WhereBase where, string propertyName, string otherPropertyName)
87 //{
88 // where.Instance = NHibernate.Expression.Expression.LeProperty(propertyName, otherPropertyName);
89 //}
90 //public static void Like(WhereBase where, string propertyName, string value, NHibernate.Expression.MatchMode matchModes)
91 //{
92 // where.Instance = NHibernate.Expression.Expression.Like(propertyName, value, matchModes);
93 //}
94
95 //public static void Lt(WhereBase where, string propertyName, object value)
96 //{
97 // where.Instance = NHibernate.Expression.Expression.Lt(propertyName, value);
98 //}
99 //public static void LtProperty(WhereBase where, string propertyName, string otherPropertyName)
100 //{
101 // where.Instance = NHibernate.Expression.Expression.LtProperty(propertyName, otherPropertyName);
102 //}
103 //public static void Not(WhereBase where)
104 //{
105 // where.Instance = NHibernate.Expression.Expression.Not(where.Instance);
106 //}
107 //public static void NotEqProperty(WhereBase where, string propertyName, string otherPropertyName)
108 //{
109 // where.Instance = NHibernate.Expression.Expression.NotEqProperty(propertyName, otherPropertyName);
110 //}
111 //public static void Or(WhereBase where, WhereBase whereA, WhereBase whereB)
112 //{
113 // where.Instance = NHibernate.Expression.Expression.Or(whereA.Instance, whereB.Instance);
114 //}
115 //public static void Sql(WhereBase where, string sql)
116 //{
117 // where.Instance = NHibernate.Expression.Expression.Sql(sql);
118 //}
119 #endregion
120 }
121 }
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

最好注释也去掉,这样的好处是别人开发的可以不管ORM是用什么第三方框架,直接调用WhereBase静态方法(代理模式)

WhereBase直接携带了Castle的搜索接口ICriterion,

在RepositoryBase有个这么个方法转换IWhere为Castle的搜索对象

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
 1 #region 其他方法
2 NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
3 {
4 if (where == null) {
5 return null;
6 }
7 NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
8 for (var i = 0; i < where.Length; i++)
9 {
10 wheres[i] = (where[i] as WhereBase).Instance;
11 }
12 return wheres;
13 }
14 #endregion
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

这样就可以完美地实现搜索和排序的解耦

仓储基类有个方法实现如下:

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
1 public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
2 {
3 if (where == null) {
4 return FindAll<T>();
5 }
6 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
7 }
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

三、总结:    

1:搜索和排序的解耦不算是个难题

2: 实现的仓储基类可以通过IoC注入实例化,这样可以插拔式更换ORM

3: 定义的仓储接口和实现最好放在不同的类库,以更好的解耦

四、后记:Repository实现仓储--Castle实现      

1 namespace Yom.NFramework2_0.CastleExtend
2 {
3 public abstract class EntityBase : Castle.ActiveRecord.ActiveRecordBase, Yom.NFramework2_0.IEntity
4 {
5 }
6 }

实体基类嫁接

1 namespace Yom.NFramework2_0
2 {
3 public interface ISinglePrimaryKeyRepository : IRepository<string>
4 {
5 }
6 }

非组合主键仓储扩展

新的IRepository接口+搜索和排序解耦(+基于Castle实现)
  1 namespace Yom.NFramework2_0.CastleExtend
2 {
3 public class CastleSinglePrimaryKeyRepository : ISinglePrimaryKeyRepository//, System.Configuration.IConfigurationSectionHandler
4 {
5 #region IRepository<string> 成员
6
7 #region 实体相关操作
8 public T FindBy<T>(string primaryKey) where T : IEntity
9 {
10 return Castle.ActiveRecord.ActiveRecordBase<T>.Find(primaryKey);
11 }
12
13 public IEnumerable<T> FindAll<T>() where T : IEntity
14 {
15 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
16 }
17
18 public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
19 {
20 if (where == null) {
21 return FindAll<T>();
22 }
23 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
24 }
25
26 public IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity
27 {
28 if (order == null)
29 {
30 if (where == null)
31 {
32 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
33 }
34 else
35 {
36 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
37 }
38 }
39 else if (where == null)
40 {
41 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[]);
42 }
43
44 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
45 }
46
47 public IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity
48 {
49 if (where == null)
50 {
51 count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T));
52 if (order == null) {
53 return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize);
54
55 }else{
56 return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[]);
57 }
58 }
59 else
60 {
61 count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T), IWhere2ICriterion(where));
62 if (order == null) {
63 return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, IWhere2ICriterion(where));
64 }
65 }
66 return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
67 }
68
69 public void Add<T>(T entity) where T : IEntity
70 {
71 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
72 {
73 (entity as Castle.ActiveRecord.ActiveRecordBase).CreateAndFlush();
74 tran.VoteCommit();
75 }
76 }
77
78 public void Delete<T>(T entity) where T : IEntity
79 {
80 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
81 {
82 (entity as Castle.ActiveRecord.ActiveRecordBase).DeleteAndFlush();
83 tran.VoteCommit();
84 }
85 }
86
87 public void DeleteAll<T>() where T : IEntity
88 {
89 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
90 {
91 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll();
92 tran.VoteCommit();
93 }
94 }
95
96 public void DeleteAll<T>(IWhere[] where) where T : IEntity
97 {
98 IEnumerable<T> entities;
99 if (where == null)
100 {
101 entities = this.FindAll<T>();
102 }
103 else
104 {
105 entities = this.FindAll<T>(where);
106 }
107 if (entities != null)
108 {
109 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
110 {
111 foreach (T entity in entities) {
112 this.Delete<T>(entity);
113 }
114 tran.VoteCommit();
115 }
116 }
117 }
118 public void DeleteAll<T>(string where) where T : IEntity
119 {
120
121 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
122 {
123 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(where);
124 tran.VoteCommit();
125 }
126
127 }
128 public void DeleteAll<T>(IEnumerable<string> pkValues) where T : IEntity
129 {
130 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
131 {
132 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(pkValues);
133 tran.VoteCommit();
134 }
135 }
136
137 public void Update<T>(T entity) where T : IEntity
138 {
139 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
140 {
141 (entity as Castle.ActiveRecord.ActiveRecordBase).UpdateAndFlush();
142 tran.VoteCommit();
143 }
144 }
145
146 public bool Exists<T>(string primaryKey) where T : IEntity
147 {
148 return Castle.ActiveRecord.ActiveRecordBase<T>.Exists<string>(primaryKey);
149 }
150 #endregion
151 #region ado执行sql
152 public int ExecuteSql(string sql, params System.Data.IDataParameter[] ps)
153 {
154 using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
155 {
156 cmd.CommandText = sql;
157 if (ps != null && ps.Length > 0)
158 {
159 foreach (System.Data.IDataParameter p in ps)
160 {
161 cmd.Parameters.Add(p);
162 }
163 }
164 return cmd.ExecuteNonQuery();
165 }
166 }
167
168 public object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps)
169 {
170 using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
171 {
172 cmd.CommandText = sql;
173 if (ps != null && ps.Length > 0)
174 {
175 foreach (System.Data.IDataParameter p in ps)
176 {
177 cmd.Parameters.Add(p);
178 }
179 }
180 return cmd.ExecuteScalar();
181 }
182 }
183
184 public System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps)
185 {
186 using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
187 {
188 cmd.CommandText = sql;
189 if (ps != null && ps.Length > 0)
190 {
191 foreach (System.Data.IDataParameter p in ps)
192 {
193 cmd.Parameters.Add(p);
194 }
195 }
196 System.Data.DataTable result = new System.Data.DataTable();
197 result.Load(cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection));
198 return result;
199 }
200 }
201 #endregion
202 #endregion
203 #region 其他方法
204 NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
205 {
206 if (where == null) {
207 return null;
208 }
209 NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
210 for (var i = 0; i < where.Length; i++)
211 {
212 wheres[i] = (where[i] as WhereBase).Instance;
213 }
214 return wheres;
215 }
216 #endregion
217 }
218 }
新的IRepository接口+搜索和排序解耦(+基于Castle实现)

Castle实现IReposoitory

五、项目开发的层次结构                                                                                              

新的IRepository接口+搜索和排序解耦(+基于Castle实现)