Entity Framework的横空出世确立了其在.net领域官方ORM中的霸主地位,给我们开发者带来了福音,但是使用使用上还是有些不便捷的地方,尤其是在三层架构的项目中,在业务层不容许出现直接操作ObjectContext 的情况下,需要针对不同实体编写不同DAO的工作是令人感到繁琐的。于是封装一个DaoTemplate类试图通过泛型手段涵盖所有可能的查询封装要解决几个问题:
1、持久层用一个类DaoTemplate尽量涵盖80%的查询需求,也可以根据需要编写子类进行扩展
2、业务层不容许直接操作ObjectContext对象,业务层只关注业务,可以调用DaoTemplate实现各种读写能力
3、业务层对持久层的多次调用要支持事务
4、业务层事务代码对于成员是透明的,程序员无需知道事务的存在,而只管在业务方法里面编写复杂的业务
我采用model first的思路,模型如下:
项目结构如下:
一些类的介绍:
下面这个类来自网络一位仁兄的博客,实现的是对Expression<Func<T, bool>>这种Lambda表达式提供And和Or扩展方法以实现动态查询中动态构造Lambda条件表达式的需要:
public static class PredicateExtensions { public static Expression<Func<T, bool>> True<T>() { return f => true; } public static Expression<Func<T, bool>> False<T>() { return f => false; } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters); } public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); Expression<Func<T,bool>> lambda =Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters); return lambda; } }
namespace EFLabModelFirst.JT.Dao { /// <summary> /// 分页信息类 /// </summary> /// <typeparam name="T">分页的实体类型</typeparam> /// <typeparam name="TKey">排序的属性类型</typeparam> /// <typeparam name="TResult">投影结果类型</typeparam> [Serializable] public class PageInfo<T, TKey, TResult> { /// <summary> /// 条件表达式树 /// </summary> public Expression<Func<T, bool>> Where { get; set; } /// <summary> /// 排序表达式树 /// </summary> public Expression<Func<T,TKey>> Order { get; set; } private String _include=string.Empty; /// <summary> /// 要抓取的导航属性 /// </summary> public string Include { get { return _include; } set { _include = value; } } /// <summary> /// 投影表达式树 /// </summary> public Expression<Func<T,TResult>> Select { get; set; } private int _pageSize = 10; /// <summary> /// 页大小 /// </summary> public int PageSize { get { return _pageSize; } set { _pageSize = value; } } private int _pageIndex = 1; /// <summary> /// 页号 /// </summary> public int PageIndex { get { return _pageIndex; } set { _pageIndex = value; } } /// <summary> /// 总条数 /// </summary> public long RecordCount { get; set; } /// <summary> /// 总页数 /// </summary> public long PageCount { get; set; } /// <summary> /// 分页结果 /// </summary> public ICollection<TResult> List { get; set; } } }
<?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <!--连接字符串的名称--> <add key="ConnectionStringKey" value="modelfirstEntities"/> <!--实体容器的名称--> <add key="EntityContainerName" value="modelfirstEntities"/> <!--对象上下文类型 value="对象上下文类型全名,程序集名称"--> <add key="ObjectContextType" value="EFLabModelFirst.modelfirstEntities,EFLabModelFirst"/> </appSettings> <connectionStrings> <add name="modelfirstEntities" connectionString="metadata=res://*/ModelFirst.csdl|res://*/ModelFirst.ssdl|res://*/ModelFirst.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\sqlexpress;Initial Catalog=modelfirst;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration>