【Yom框架】漫谈个人框架的设计之二:新的IRepository接口+搜索和排序解耦(+基于Castle实现)

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

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

一、接口定义                                                 

新的IRepository接口设计如下:

 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 }

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

public interface IEntity
    {
    }
public interface IOrder
    {
    }
public interface IWhere
    {
    }
public interface ICompositeKey : IEquatable<string>
    {
    }

ICompositeKey为组合主键接口

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

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

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

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

 

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

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

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

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

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

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 }

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

 

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

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

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

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

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

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

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

最后我对WhereBase的变身是:

  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 }

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

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

在RepositoryBase有个这么个方法转换IWhere为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

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

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

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         }

三、总结:                                                                                 

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 }


非组合主键仓储扩展

  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 }

 

 

Castle实现IReposoitory

五、项目开发的层次结构                                                                                              

 

posted @ 2013-09-02 23:11  哈哈好玩  阅读(2865)  评论(5编辑  收藏  举报