珍惜他人劳动成果,转载请注明出处,谢谢!
上篇我们已经构建好了EF模型,本篇我们在这个模型的基础上应用Repository模式。
从现在开始,如果你是菜鸟,一定要仔细的慢慢分析啊,这可是接触到核心了啊,呵呵,吓你呢,其实没有那么难。
第一步,我们要把所有的公共操作抽象出来,无外乎我们多次提到的增删改查等操作,这样以后只要继承这个类就可以了。好,首先,我们在Models文件夹下定义一个IRepository接口,这时候,你可能要问:你怎么知道这个接口的类型啊。你别急,我不知道以后要继承的类是什么类型,但我知道它们基本上都有增删改查的功能,这个时候就要用到大名鼎鼎的泛型啦。代码如下:
using
System;
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); 这句有点疑惑啊,其实
ICriteria
是我定义的一个查询条件,我们都知道项目中经常有组合查询,那么多的组合条件,写起来比较麻烦而且非常容易出错,比如起止日期、姓名、地点、金额等一大堆组合条件,写起来确实很累人,这时候我就想到何不定义一个条件类呢。另外,我们现实列表的时候还要用到分页,我们在接口中也写好了这个方法,
IList
<
T
>
Find(ICriteria criteria,
int
page,
int
pageSize, Order orderExpr);厉害吧,你只要填入条件(criteria)、当前页码(page)、每页条数(pageSize)以及排序条件(orderExpr),那么就可以直接分页显示啦。这个在以后你会发现它的极大的优越性,它与JQuery 的flexigrid (类似GridView控件)的分页显示简直就是珠联璧合。下面代码是
ICriteria接口 与
Order类的定义。
using
System;
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;
}
}
}
以上就是
IRepository
接口以及相关的一些类,
这里面涉及到得知识就多了一些,虽然有注释,但是如果以前接触很少的话可能看起来还是比较困难,不过不用着急,下面我再介绍一下啊,这里面你要弄懂两个概念,
ObjectQuery
和
IQueryable
,如果你一点都不明白,那么强烈建议你看看这个
http://www.it.oaod.com/PcTech-73703.html , 另外也要搞清楚 Entity SQL ,参考
http://tech.ddvip.com/2009-05/1242029734118538.html ,了解一个大概就可以啦。
我们定义了
ICriteria,现在我们就要对它实现,我们要在Models中创建一个
Criteria类继承
ICriteria接口,代码如下:
Code
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模式、分页