1、建立好如上图所示的类库和MVC项目 添加相应的引用,创建EF实体模型
2、定义数据操作基类接口 (具备基本的增、删、改、查、分页方法)
namespace Core.ProjectOA.IDAL
{
public interface IBaseDal<T> where T : class, new()
{
IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda);//列表展示
IQueryable<T> LoadPageEntities<s>(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, s>> orderByLambda, int pageIndex, int pageSize, bool isAsc, out int totalCount);//分页
bool DeleteEntity(T entity);//删除
bool EditEntity(T entity);//编辑
T AddEntity(T entity);//添加
}
}
3、定义具体Model的数据操作类接口继承数据操作基类接口(IDAL引用Model)
namespace Core.ProjectOA.IDAL
{
public interface IUserInfoDal:IBaseDal<Model.UserInfo>
{
//这里写UserInfo特有的方法
}
}
4、创建数据操作类基类(DAL引用IDAL 、Model)
<pre name="code" class="csharp">namespace Core.ProjectOA.DAL
{
public class BaseDal<T> where T:class,new()
{
//Model1Container Db = new Model1Container();
<pre name="code" class="csharp">//需要对数据进行操作 所以要新建DbContext类的子类(EF定义模型时候指定的类型 此处为<span style="font-family: Arial, Helvetica, sans-serif;">Model1Container )</span>
Model1Container Db = (Model1Container)DBContextFactory.CreateDbContext();
public T AddEntity(T entity)
{
Db.Set<T>().Add(entity);
//Db.SaveChanges();
return entity;
}
public bool DeleteEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
//return Db.SaveChanges() > 0;
return true;
}
public bool EditEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
//return Db.SaveChanges() > 0;
return true;
}
public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
{
return Db.Set<T>().Where(whereLambda);
}
public IQueryable<T> LoadPageEntities<s>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, s>> orderByLambda, int pageIndex, int pageSize, bool isAsc, out int totalCount)
{
var temp = Db.Set<T>().Where<T>(whereLambda);
totalCount = temp.Count();
if (isAsc)
{
temp = temp.OrderBy<T, s>(orderByLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageIndex);
}
else
{
temp = temp.OrderByDescending<T, s>(orderByLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageIndex);
}
return temp;
}
}
5、创建具体Model数据操作类 继承数据操作类基类并实现Model数据操作类的接口
namespace Core.ProjectOA.DAL
{
public class UserInfoDAL :BaseDal<UserInfo>,IUserInfoDal
{
}
}
---------------------------------------------------------------------------------------开始考虑数据会话层--------------------------------------------------------------------------------------------------------------------
6、创建数据会话层(DALFactory)
数据会话层:就是一个工厂类,负责完成所有数据操作类实例的创建,然后业务层通过调用数据会话层来获取要操作数据类的实例,所以会话层将业务层与数据层解耦。
引用了DAL、IDAL\
namespace Core.ProjectOA.DALFactory
{
public class DBSession : IDBSession (第9步定义DBSession接口)
{
// Model1Container Db = new Model1Container();
public DbContext Db//由于DBSession中有Db.SaveChange()方法 所以要有一个Db对象
{
get
{
return DAL.DBContextFactory.CreateDbContext();//第7步
}
}
private IUserInfoDal _UserInfoDal;
public IUserInfoDal UserInfoDal //数据操作类对象
{
get
{
if (_UserInfoDal == null)
{
// _UserInfoDal = new DAL.UserInfoDAL();
_UserInfoDal = AbstractFactory.CreateUserInfoDal();//通过抽象工厂类创建数据操作的实例 (第8步)
}
return _UserInfoDal;
}
set
{
_UserInfoDal = value;
}
}
//保存修改的方法(用于批量修改数据 一次提交)
public bool SaveChanges()
{
return Db.SaveChanges() > 0;
}
}
}
7、由于DbContext的子类 实例要求线程内唯一 ,所以在DAL中新建一个DBContextFactory类 新建CreateDbContext()方法来创建线程内唯一DbContext
(之所以放在DAL中是因为这个DBContext对象在DAL中的增删改查方法和DALFactory中的DBSession中的SaveChanges()方法都要用 而且DALFactory引用了DAL 避免 循环引用)
namespace Core.ProjectOA.DAL
{
public class DBContextFactory
{
//保证线程内唯一EF (EF对象存储在HttpContext中的CallContext中,如果存在就返回 ,如果不存在就创建)
public static DbContext CreateDbContext()
{
DbContext dbContext = (DbContext)CallContext.GetData("DbContext");
if (dbContext == null)
{
dbContext = new Model1Container();
CallContext.SetData("DbContext", dbContext);
}
return dbContext;
}
}
}
8、通过抽象工厂类创建数据操作类的实例(应用反射 实现解耦) 程序集名称和命名空间名称需要在Web.config中设置
<appSettings>
<add key="AssemblyPath" value="Core.ProjectOA.DAL"/>
<add key="Namespace" value="Core.ProjectOA.DAL"/>
</appSettings>
namespace Core.ProjectOA.DALFactory
{
//抽象工厂类 用来数据操作对象实例
public class AbstractFactory
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["AssemblyPath"];//程序集名称
private static readonly string NamespacePath = ConfigurationManager.AppSettings["Namespace"];//命名空间名称
/// <summary>
/// 创建UserInfoDal实例
/// </summary>
/// <returns></returns>
public static IUserInfoDal CreateUserInfoDal()
{
string fullClassName = NamespacePath + ".UserInfoDAL";//如需其他Model操作类实例 新建此方法 改变此处即可
return CreateInstance(fullClassName) as IUserInfoDal;
}
/// <summary>
/// 通过反射创建指定类型的实例
/// </summary>
/// <param name="fullClassName"></param>
/// <returns></returns>
private static object CreateInstance(string fullClassName)
{
var assembly = Assembly.Load(AssemblyPath);
return assembly.CreateInstance(fullClassName);
}
}
}
-----------------------------------------------------------------------------------开始考虑业务层------------------------------------------------------------------------------------------------------------------------------
9、业务层调用数据会话层也要通过DBSession的接口调用 所以 建立一个DBSession的接口(放在IDAL里)
namespace Core.ProjectOA.IDAL
{
public interface IDBSession
{
//EF数据操作对象的属性
DbContext Db { get; }
IUserInfoDal UserInfoDal { get; set; }
bool SaveChanges();
}
}
10、定义业务层基类接口(IBLL里 引用IDAL Model)
namespace Core.ProjectOA.IBLL
{
public interface IBaseService<T> where T:class ,new()
{
IDBSession CurrentDBSession { get; }
IDAL.IBaseDal<T> CurrentDal { get; set; }
T AddEntity(T entity);
bool DeleteEntity(T entity);
bool EditEntity(T entity);
IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda);
IQueryable<T> LoadPageEntities<s>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, s>> orderByLambda, int pageIndex, int pageSize, bool isAsc, out int totalCount);
}
}
11 、定义业务层具体类接口(继承基类接口)
namespace Core.ProjectOA.IBLL
{
public interface IUserInfoService : IBaseService<UserInfo>
{
//此处写具体类特有方法
}
}
12、定义业务层基类(BLL) 实现业务层基类接口 (此类里面要有DBSession对象<线程内唯一>、CurrentDal<对应具体Model数据操作类,所以设置一个抽象方法SetCurrentDal要求子类必须通过实现此方法给CurrentDal赋对应的ModelDal值>)
namespace Core.ProjectOA.BLL
{
public abstract class BaseService<T>:IBaseService<T> where T : class, new()
{
//数据会话层对象
public IDBSession CurrentDBSession
{
get {
//return new DALFactory.DBSession();//暂时
return DBSessionFactory.CreateDBSession();//创建线程内唯一对象(第13步)
}
}
public IDAL.IBaseDal<T> CurrentDal { get; set; }//数据操作类对象
public abstract void SetCurrentDal();//抽象方法 子类必须实现
public BaseService()//构造方法 执行上面的抽象方法
{
SetCurrentDal();
}
public T AddEntity(T entity)
{
CurrentDal.AddEntity(entity);
CurrentDBSession.SaveChanges();
return entity;
}
public bool DeleteEntity(T entity)
{
CurrentDal.DeleteEntity(entity);
return CurrentDBSession.SaveChanges();
}
public bool EditEntity(T entity)
{
CurrentDal.EditEntity(entity);
return CurrentDBSession.SaveChanges();
}
public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
{
return CurrentDal.LoadEntities(whereLambda);
}
public IQueryable<T> LoadPageEntities<s>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, s>> orderByLambda, int pageIndex, int pageSize, bool isAsc, out int totalCount)
{
return CurrentDal.LoadPageEntities(whereLambda, orderByLambda, pageIndex, pageSize, isAsc, out totalCount);
}
}
}
13、DBSession 线程内唯一 所以DALFactory中定义工厂类创建DBSession对象
namespace Core.ProjectOA.DALFactory
{
public class DBSessionFactory
{
public static IDBSession CreateDBSession()
{
IDBSession dbSession = (IDBSession)CallContext.GetData("dbsession");
if (dbSession == null)
{
dbSession = new DBSession();
CallContext.SetData("dbsession", dbSession);
}
return dbSession;
}
}
}
14 、业务层建立具体Model模型业务操作类 ,继承业务基类,实现具体业务类接口
namespace Core.ProjectOA.BLL
{
public class UserInfoService : BaseService<UserInfo>,IUserInfoService
{
public override void SetCurrentDal()//此处必须实现抽象方法 给具体数据操作类赋值
{
CurrentDal = this.CurrentDBSession.UserInfoDal;
}
public void SetUserInfo(UserInfo user)//此处模拟一个比较复杂的业务(由于面向接口变成,如果想在表现层被调用 接口中也要有这个方法)
{
CurrentDal.AddEntity(user);
CurrentDal.EditEntity(user);
CurrentDal.DeleteEntity(user);//假设这三次是各种增删改查不同操作
CurrentDBSession.SaveChanges();//批量操作 一次保存
}
}
}
--------------------------------------------------------------------------------表现层----------------------------------------------------------------------------------------------------------------------------------------------
</pre></p><p>15、表现层简单调用范例</p><p><pre name="code" class="csharp">namespace Core.ProjectOA.WebApp.Controllers
{
public class UserInfoController : Controller
{
// GET: UserInfo
public ActionResult Index()
{
IBLL.IUserInfoService userInfoService = new BLL.UserInfoService();//建立接口类型
UserInfo userInfo = new UserInfo() { DelFlag = 0, ModifiedOn = DateTime.Now, Remark = "11", Sort = "22", SubTime = DateTime.Now, UName = "zhangsan", UPwd = "321" };
userInfoService.AddEntity(userInfo);
//此处调不出来来接口中没定义的方法
userInfoService.SetUserInfo(userInfo);//此处仅示范 方法中操作不适合这个对象
List<UserInfo> list=userInfoService.LoadEntities(u => u.ID==2).ToList();
return View();
}
}
}