一:框架搭建 web
1:先建立Model. 數據庫
2:建立數據訪問接口層。IUserInfoDal 框架
在該接口中定義了常見的方法CURD以及分頁方法。 性能
public interface IUserInfoDal spa
{ 線程
IQueryable<UserInfo> LoadEntities(System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda); 對象
IQueryable<UserInfo> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda, System.Linq.Expressions.Expression<Func<UserInfo, s>> orderbyLambda, bool isAsc); 繼承
bool DeleteEntity(UserInfo entity); 接口
bool EditEntity(UserInfo entity); ip
UserInfo AddEntity(UserInfo entity);
}
3:每一個接口中都須要CURD以及分頁方法的定義,並且這些方法的定義基本上是一致的,因此封裝。封裝到IBaseDal
public interface IBaseDal<T>where T:class,new()//注意該泛型的使用
{
IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda);
IQueryable<T> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, s>> orderbyLambda, bool isAsc);
bool DeleteEntity(T entity);
bool EditEntity(T entity);
T AddEntity(T entity);
}
4:讓IUserInfoDal繼承IBaseDal
public interface IUserInfoDal:IBaseDal<UserInfo>
{
//定義本身特有的方法。
}
5:讓具體的數據操做類UserInfoDal去實現IUserInfoDal接口中的方法。
public class UserInfoDal :IUserInfoDal
{
OAEntities Db = new OAEntities();
/// <summary>
/// 查詢過濾
/// </summary>
/// <param name="whereLambda"></param>
/// <returns></returns>
public IQueryable<UserInfo> LoadEntities(System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda)
{
return Db.UserInfo.Where<UserInfo>(whereLambda);//
}
/// <summary>
/// 分頁
/// </summary>
/// <typeparam name="s"></typeparam>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalCount"></param>
/// <param name="whereLambda"></param>
/// <param name="orderbyLambda"></param>
/// <param name="isAsc"></param>
/// <returns></returns>
public IQueryable<UserInfo> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda, System.Linq.Expressions.Expression<Func<UserInfo, s>> orderbyLambda, bool isAsc)
{
var temp = Db.UserInfo.Where<UserInfo>(whereLambda);
totalCount = temp.Count();
if (isAsc)//升序
{
temp = temp.OrderBy<UserInfo, s>(orderbyLambda).Skip<UserInfo>((pageIndex - 1) * pageSize).Take<UserInfo>(pageSize);
}
else
{
temp = temp.OrderByDescending<UserInfo, s>(orderbyLambda).Skip<UserInfo>((pageIndex - 1) * pageSize).Take<UserInfo>(pageSize);
}
return temp;
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool DeleteEntity(UserInfo entity)
{
Db.Entry<UserInfo>(entity).State = System.Data.EntityState.Deleted;
return Db.SaveChanges() > 0;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool EditEntity(UserInfo entity)
{
Db.Entry<UserInfo>(entity).State = System.Data.EntityState.Modified;
return Db.SaveChanges() > 0;
}
/// <summary>
/// 添加數據
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public UserInfo AddEntity(UserInfo entity)
{
Db.Set <UserInfo>().Add(entity);
Db.SaveChanges();
return entity;
}
}
6:因爲每一個數據操做類都要實現本身的接口(每個接口都繼承了IBaseDal),因此每一個數據操做類中都要重複實現CURD以及分頁的方法,因此把具體的實現封裝到了BaseDal中。
public class BaseDal<T>where T:class,new()
{
OAEntities Db = new OAEntities();
/// <summary>
/// 查詢過濾
/// </summary>
/// <param name="whereLambda"></param>
/// <returns></returns>
public IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda)
{
return Db.Set <T>().Where<T>(whereLambda);//
}
/// <summary>
/// 分頁
/// </summary>
/// <typeparam name="s"></typeparam>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalCount"></param>
/// <param name="whereLambda"></param>
/// <param name="orderbyLambda"></param>
/// <param name="isAsc"></param>
/// <returns></returns>
public IQueryable<T> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, s>> orderbyLambda, bool isAsc)
{
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>(pageSize);
}
else
{
temp = temp.OrderByDescending<T, s>(orderbyLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
}
return temp;
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool DeleteEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.EntityState.Deleted;
return Db.SaveChanges() > 0;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool EditEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.EntityState.Modified;
return Db.SaveChanges() > 0;
}
/// <summary>
/// 添加數據
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public T AddEntity(T entity)
{
Db.Set <T>().Add(entity);
Db.SaveChanges();
return entity;
}
7:讓UserInfoDal繼承BaseDal.
public class UserInfoDal : BaseDal<UserInfo>,IUserInfoDal
{
}
8:建立DBSession(數據會話層:就是一個工廠類,負責完成全部數據操做類實例的建立,而後業務層經過數據會話層來獲取要操做數據類的實例。因此數據會話層將業務層與數據層解耦。
/// 在數據會話層中提供一個方法:完成全部數據的保存。)
做用:封裝了數據層全部實例的建立,將BLL和DAL進行解耦,提供對數據操的統一訪問點。提供一個方法,完成全部數據的保存。
private IUserInfoDal _UserInfoDal;
public IUserInfoDal UserInfoDal
{
get {
if (_UserInfoDal == null)
{
_UserInfoDal = new UserInfoDal();
}
return _UserInfoDal;
}
set
{
_UserInfoDal = value;
}
}
9: /// <summary>
/// 一個業務中常常涉及到對多張操做,咱們但願連接一次數據庫,完成對張表數據的操做。提升性能。 工做單元模式。
/// </summary>
/// <returns></returns>
public bool SaveChanges()
{
return Db.SaveChanges() > 0;
}
10:將數據層中的全部的保存數據的SaveChanges註釋掉。
11:在數據層中用到了EF的實例,數據會話層中也用到了,因此在一個請求中只能建立一個EF實例(線程內惟一對象)
/// <summary>
/// 負責建立EF數據操做上下文實例,必須保證線程內惟一.
/// </summary>
public class DBContextFactory
{
public static DbContext CreateDbContext()
{
DbContext dbContext = (DbContext)CallContext.GetData("dbContext");
if (dbContext == null)
{
dbContext = new OAEntities();
CallContext.SetData("dbContext", dbContext);
}
return dbContext;
}
}
12:在DBSession和BaseDal中調用上面的方法(CreateDbContext)完成EF實例的建立。
DBSession獲取EF實例
public DbContext Db
{
get
{
return DBContextFactory.CreateDbContext();
}
}
BaseDal中獲取EF的實例
DbContext Db = DAL.DBContextFactory.CreateDbContext();
13:抽象抽象工廠封裝數據操做類實例建立,而後DBSession調用抽象工廠。
在web.config 中配置數據層程序集的相關信息。
/// <summary>
/// 經過反射的形式建立類的實例
/// </summary>
public class AbstractFactory
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["AssemblyPath"];
private static readonly string NameSpace = ConfigurationManager.AppSettings["NameSpace"];
public static IUserInfoDal CreateUserInfoDal()
{
string fullClassName = NameSpace + ".UserInfoDal";
return CreateInstance(fullClassName) as IUserInfoDal;
}
private static object CreateInstance(string className)
{
var assembly= Assembly.Load(AssemblyPath);
return assembly.CreateInstance(className);
}
}
而後修改DBSession
private IUserInfoDal _UserInfoDal;
public IUserInfoDal UserInfoDal
{
get {
if (_UserInfoDal == null)
{
//_UserInfoDal = new UserInfoDal();
_UserInfoDal = AbstractFactory.CreateUserInfoDal();//經過抽象工廠封裝了類的實例的建立
}
return _UserInfoDal;
}
set
{
_UserInfoDal = value;
}
}
14:定義DBSession的接口
/// <summary>
/// 業務層調用的是數據會話層的接口。
/// </summary>
public interface IDBSession
{
DbContext Db { get; }
IUserInfoDal UserInfoDal { get; set; }
bool SaveChanges();
}
而後讓DBSession實現該接口。
15:定義具體的業務基類
//在業務基類中完成DBSession的調用,而後將業務層中公共的方法定義在基類中,可是這些方法不知道經過DBSession來獲取哪一個數據操做類的實例。因此將該業務基類定義成抽象類,加上一個抽象方法,加上一個IBaseDal屬性,而且讓基類的構造方法調用抽象方法目的是在表現層new具體的業務子類,父類的構造方法被調用,這些執行抽象方法,可是執行的的是子類中具體的實現。業務子類知道經過DBSession獲取哪一個數據操做類的實例。
public abstract class BaseService<T> where T:class,new()
{
public IDBSession CurrentDBSession
{
get
{
return new DBSession();//暫時
}
}
public IDAL.IBaseDal<T> CurrentDal { get; set; }
public abstract void SetCurrentDal();
public BaseService()
{
SetCurrentDal();//子類必定要實現抽象方法。
}
public IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda)
{
return CurrentDal.LoadEntities(whereLambda);
}
}
16:定義業務層的接口。
17:保證業務層的DbSession線程內惟一
17:將數據庫連接字符串拷貝到web.config文件中。