珍惜他人劳动成果,转载请注明出处,谢谢! 上篇我们已经构建好了EF模型,本篇我们在这个模型的基础上应用Repository模式。 从现在开始,如果你是菜鸟,一定要仔细的慢慢分析啊,这可是接触到核心了啊,呵呵,吓你呢,其实没有那么难。 第一步,我们要把所有的公共操作抽象出来,无外乎我们多次提到的增删改查等操作,这样以后只要继承这个类就可以了。好,首先,我们在Models文件夹下定义一个IRepository接口,这时候,你可能要问:你怎么知道这个接口的类型啊。你别急,我不知道以后要继承的类是什么类型,但我知道它们基本上都有增删改查的功能,这个时候就要用到大名鼎鼎的泛型啦。代码如下: using System; 看看上面的代码,是不是常用的操作都有了啊,你是不是对 IList<T> Find(ICriteria criteria); 这句有点疑惑啊,其实ICriteria using System.Collections.Generic; using System.Linq; using System.Text; namespace PBAccount.Models { public interface IRepository<T> { void Add(T entity); void Del(T entity); void Update(T entity); T Find(Guid entityId); IList<T> Find(ICriteria criteria); IList<T> FindAll(); IList<T> Find(ICriteria criteria, int page, int pageSize, Order orderExpr); int Count(ICriteria criteria); void SaveChanges(); } } 是我定义的一个查询条件,我们都知道项目中经常有组合查询,那么多的组合条件,写起来比较麻烦而且非常容易出错,比如起止日期、姓名、地点、金额等一大堆组合条件,写起来确实很累人,这时候我就想到何不定义一个条件类呢。另外,我们现实列表的时候还要用到分页,我们在接口中也写好了这个方法,IList<T> Find(ICriteria criteria, int page, int pageSize, Order orderExpr);厉害吧,你只要填入条件(criteria)、当前页码(page)、每页条数(pageSize)以及排序条件(orderExpr),那么就可以直接分页显示啦。这个在以后你会发现它的极大的优越性,它与JQuery 的flexigrid (类似GridView控件)的分页显示简直就是珠联璧合。下面代码是ICriteria接口 与 Order类的定义。 using System; 以上就是 IRepository接口以及相关的一些类,这里面涉及到得知识就多了一些,虽然有注释,但是如果以前接触很少的话可能看起来还是比较困难,不过不用着急,下面我再介绍一下啊,这里面你要弄懂两个概念,ObjectQuery 和 IQueryable,如果你一点都不明白,那么强烈建议你看看这个using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Objects; namespace PBAccount.Models { public interface IRepository<T> { void Add(T entity); void Del(T entity); void Update(T entity); T Find(Guid entityId); IList<T> Find(ICriteria criteria); IList<T> FindAll(); IList<T> Find(ICriteria criteria, int page, int pageSize, Order orderExpr); int Count(ICriteria criteria); void SaveChanges(); } /// <summary> /// 查询条件类型 /// </summary> public enum CriteriaType { /// <summary> /// 0 表示查询条件是个表达式 /// </summary> Expression = 0, /// <summary> /// 1表示查询条件是个参数 /// </summary> Parameter = 1 } /// <summary> /// 查询条件参数类 /// </summary> public class CriteriaParameter { /// <summary> /// 参数的值 /// </summary> public object Value { get; private set; } /// <summary> /// 参数的名称 /// </summary> public string Name { get; set; } /// <summary> /// 参数字段 ?如果你暂时不明白,在以后我们具体使用的时候一看就知道啦,别着急,慢慢来啊 /// </summary> public string Field { get; private set; } /// <summary> /// 构造函数 /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <param name="field"></param> public CriteriaParameter(string name, object value, string field) { this.Name = name; this.Value = value; this.Field = field; } } /// <summary> /// 查询条件接口 /// </summary> public interface ICriteria { CriteriaType CriteriaType { get; } string Expression { get; } CriteriaParameter[] Parameters { get; } /// <summary> /// 并 操作 比如查询“姓名”+“金额” 等 /// </summary> /// <param name="other"></param> /// <returns></returns> ICriteria And(ICriteria other); ICriteria Or(ICriteria other); ICriteria Not(); } /// <summary> /// 排序类型 /// </summary> public enum OrderType { ASC, DESC } /// <summary> /// 拍戏类 /// </summary> public class Order { public OrderType OrderType { get; set; } /// <summary> /// 排序的字段 /// </summary> public string[] Fields { get; set; } public Order(OrderType orderType, params string[] fields) { this.OrderType = orderType; this.Fields = fields; } public Order(params string[] fields) : this(OrderType.ASC, fields) { } /// <summary> /// 取出排序的表达式 /// </summary> public string Expression { get { string str = string.Empty; foreach (var field in Fields) { if (str.Length > 0) str += ","; str += string.Format("it.{0} {1}", field, OrderType.ToString()); } return str; } } /// <summary> /// 排序 返回 IQueryable<T> 类型的结果 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="query"></param> /// <returns></returns> public IQueryable<T> OrderFrom<T>(ObjectQuery<T> query) where T : class { switch (this.OrderType) { case OrderType.ASC: return query.OrderBy(Expression); case OrderType.DESC: return query.OrderBy(Expression); } return query; } } } http://www.it./PcTech-73703.html , 另外也要搞清楚 Entity SQL ,参考 http://tech./2009-05/1242029734118538.html ,了解一个大概就可以啦。 我们定义了ICriteria,现在我们就要对它实现,我们要在Models中创建一个Criteria类继承ICriteria接口,代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using PBAccount.Models; namespace PBAccount.Models { public abstract class BaseCriteria : ICriteria { public const string FieldPrefix = "it."; public const string NamePrefix = "@"; public BaseCriteria() { this.CriteriaType = CriteriaType.Expression; } #region ICriteria 成员 public abstract string Expression { get; } public ICriteria And(ICriteria other) { return new AndCriteria(this, other); } public ICriteria Or(ICriteria other) { return new OrCriteria(this, other); } public ICriteria Not() { return new NotCriteria(this); } protected List<CriteriaParameter> parameters = new List<CriteriaParameter>(); public CriteriaParameter[] Parameters { get { return parameters.ToArray(); } } public CriteriaType CriteriaType { get; protected set; } #endregion static protected string ParameterNameFormat(string field) { return field.Replace('.', '_'); } } public class TrueCriteria : BaseCriteria { public override string Expression { get { return "(1=1)"; } } } public class EqualParameterCriteria : BaseCriteria { CriteriaParameter cp; public EqualParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}={3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class EqualCriteria : BaseCriteria { protected String field; protected Object value; public EqualCriteria(String field, Object value) { this.field = field; this.value = value; } public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double) || value.GetType() == typeof(bool)) return string.Format("{2}{0}={1}", field, value, FieldPrefix); return string.Format("{2}{0}='{1}'", field, value, FieldPrefix); } } } public class NotEqualParameterCriteria : BaseCriteria { CriteriaParameter cp; public NotEqualParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}!={3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class NotEqualCriteria : BaseCriteria { protected String field; protected Object value; public NotEqualCriteria(String field, Object value) { this.field = field; this.value = value; } #region ICriteria 成员 public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double) || value.GetType() == typeof(bool)) return string.Format("{2}{0}!={1}", field, value, FieldPrefix); return string.Format("{2}{0}!='{1}'", field, value, FieldPrefix); } } #endregion } public class GreaterThanParameterCriteria : BaseCriteria { CriteriaParameter cp; public GreaterThanParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}>{3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class GreaterThanCriteria : BaseCriteria { protected String field; protected Object value; public GreaterThanCriteria(String field, Object value) { this.field = field; this.value = value; } #region ICriteria 成员 public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double)) return string.Format("{2}{0}>{1}", field, value, FieldPrefix); return string.Format("{2}{0}>'{1}'", field, value, FieldPrefix); } } #endregion } public class GreaterEqualThanParameterCriteria : BaseCriteria { CriteriaParameter cp; public GreaterEqualThanParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}>={3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class GreaterEqualThanCriteria : BaseCriteria { protected String field; protected Object value; public GreaterEqualThanCriteria(String field, Object value) { this.field = field; this.value = value; } #region ICriteria 成员 public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double)) return string.Format("{2}{0}>={1}", field, value, FieldPrefix); return string.Format("{2}{0}>='{1}'", field, value, FieldPrefix); } } #endregion } public class LessThanParameterCriteria : BaseCriteria { CriteriaParameter cp; public LessThanParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}<{3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class LessThanCriteria : BaseCriteria { protected String field; protected Object value; public LessThanCriteria(String field, Object value) { this.field = field; this.value = value; } #region ICriteria 成员 public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double)) return string.Format("{2}{0}<{1}", field, value, FieldPrefix); return string.Format("{2}{0}<'{1}'", field, value, FieldPrefix); } } #endregion } public class LessEqualThanParameterCriteria : BaseCriteria { CriteriaParameter cp; public LessEqualThanParameterCriteria(String field, Object value) { this.CriteriaType = CriteriaType.Parameter; cp = new CriteriaParameter(ParameterNameFormat(field), value, field); parameters.Add(cp); } public override string Expression { get { return string.Format("{2}{0}<={3}{1}", cp.Field, cp.Name, FieldPrefix, NamePrefix); } } } public class LessEqualThanCriteria : BaseCriteria { protected String field; protected Object value; public LessEqualThanCriteria(String field, Object value) { this.field = field; this.value = value; } #region ICriteria 成员 public override string Expression { get { if (value.GetType() == typeof(int) || value.GetType() == typeof(double)) return string.Format("{2}{0}<={1}", field, value, FieldPrefix); return string.Format("{2}{0}<='{1}'", field, value, FieldPrefix); } } #endregion } public class LikeCriteria : BaseCriteria { public enum LikeCriteriaType { NoneWildcard, LeftWildcard, RightWildcard, BothWildcard } LikeCriteriaType wildcard = LikeCriteriaType.NoneWildcard; protected String field; protected Object value; public LikeCriteria(String field, Object value, LikeCriteriaType wildcard) { this.field = field; this.value = value; this.wildcard = wildcard; } public LikeCriteria(String field, Object value) : this(field, value, LikeCriteriaType.BothWildcard) { } #region ICriteria 成员 public override string Expression { get { switch (wildcard) { case LikeCriteriaType.NoneWildcard: return string.Format("{2}{0} like '{1}'", field, value, FieldPrefix); case LikeCriteriaType.LeftWildcard: return string.Format("{2}{0} like '%{1}'", field, value, FieldPrefix); case LikeCriteriaType.RightWildcard: return string.Format("{2}{0} like '{1}%'", field, value, FieldPrefix); case LikeCriteriaType.BothWildcard: return string.Format("{2}{0} like '%{1}%'", field, value, FieldPrefix); default: return string.Empty; } } } #endregion } public class BetweenCriteria : BaseCriteria { string begin_expression; string end_expression; string field; public BetweenCriteria(String field, string begin_expression, string end_expression) { this.field = field; this.begin_expression = begin_expression; this.end_expression = end_expression; } #region ICriteria 成员 public override string Expression { get { return string.Format("{3}{0} BETWEEN {1} AND {2}", field, begin_expression, end_expression, FieldPrefix); } } #endregion } public class BetweenParameterCriteria : BaseCriteria { CriteriaParameter cp1; CriteriaParameter cp2; public BetweenParameterCriteria(string field, object begin_expression, object end_expression) { string fieldPamaName1 = string.Format("{0}1", field); string fieldPamaName2 = string.Format("{0}2", field); cp1 = new CriteriaParameter(ParameterNameFormat(fieldPamaName1), begin_expression, field); parameters.Add(cp1); cp2 = new CriteriaParameter(ParameterNameFormat(fieldPamaName2), end_expression, field); parameters.Add(cp2); this.CriteriaType = CriteriaType.Parameter; } public override string Expression { get { return string.Format("{3}{0} BETWEEN {4}{1} AND {4}{2}", cp1.Field, cp1.Name, cp2.Name, FieldPrefix, NamePrefix); } } } public class NotCriteria : BaseCriteria { protected ICriteria c1; public NotCriteria(ICriteria c1) { this.c1 = c1; if (c1.CriteriaType == CriteriaType.Parameter) { parameters.AddRange(c1.Parameters); CriteriaType = CriteriaType.Parameter; } } #region ICriteria 成员 public override string Expression { get { return string.Format("NOT({0})", this.c1.Expression); } } #endregion } public class AndCriteria : BaseCriteria { protected ICriteria c1, c2; public AndCriteria(ICriteria c1, ICriteria c2) { this.c1 = c1; this.c2 = c2; CriteriaType = c1.CriteriaType | c2.CriteriaType; c1.UniqueCriteriaParameter(c2); if (c1.CriteriaType == CriteriaType.Parameter) parameters.AddRange(c1.Parameters); if (c2.CriteriaType == CriteriaType.Parameter) parameters.AddRange(c2.Parameters); } #region ICriteria 成员 public override string Expression { get { return string.Format("{0} AND {1}", c1.Expression, c2.Expression); } } #endregion } public class OrCriteria : BaseCriteria { protected ICriteria c1, c2; public OrCriteria(ICriteria c1, ICriteria c2) { this.c1 = c1; this.c2 = c2; CriteriaType = c1.CriteriaType | c2.CriteriaType; c1.UniqueCriteriaParameter(c2); if (c1.CriteriaType == CriteriaType.Parameter) parameters.AddRange(c1.Parameters); if (c2.CriteriaType == CriteriaType.Parameter) parameters.AddRange(c2.Parameters); } #region ICriteria 成员 public override string Expression { get { return string.Format("{0} OR {1}", c1.Expression, c2.Expression); } } #endregion } public static class CriteriaExtentsions { static public void UniqueCriteriaParameter(this ICriteria c1, ICriteria c2) { bool isBothParameter = (c1.CriteriaType & c2.CriteriaType) > 0; if (isBothParameter) { foreach (var p in c1.Parameters) { var it = c2.Parameters.FirstOrDefault(x => x.Name == p.Name); if (it != null) { int index = 1; string testName = it.Name + index.ToString(); while (c2.Parameters.ToList().Exists(x => x.Name == testName) || c1.Parameters.ToList().Exists(x => x.Name == testName)) { ++index; testName = it.Name + index.ToString(); } it.Name = testName; } } } } } } OK,现在我们继续,我们在Repository文件夹下创建一个类BaseRepositoryBase.cs,这个类是要继承IRepository接口,实现里面的方法,这样,就把增删查改方法给抽象出来,以后的类只要继承BaseRepositoryBase.cs,就不用自己去实现啦。 本篇结束,请继续阅读 跟我学MVC系列(Repository模式、LINQ、EF、IOC框架Castle、JQuery、AJAX)(四)Models(ORM、Repository模式、分页 |
|