MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一

抽象一个数据库访问层的统一入口(类似于EF的上下文,拿到上下文,就可以拿到所有的表).实际这个入口就是一个类,类里面有所有的仓储对应的属性.这样,只要拿到这个类的实例,就可以点出所有的仓储,我们在 Repository层里面添加一个类 DbSession.cs

namespace YouJiao.MvcWeb.Repository
{
/// <summary>
/// 相当于是简单工厂:通过DbSession可以拿到所有的仓储的实例,所以我们也可以将此DbSession看做是简单工厂.
/// 职责:对整个数据库访问层做了高度抽象,它是整个数据库访问层的统一入口,BLL层来调用Repository层的时候
/// 只要拿到DbSession就可以拿到所有的仓储,就可以对所有的表进行增删改查了
/// </summary>
public class DbSession : IDbSession
{
public ObjectContext db = new ModelContainer(); //EF上下文 我们先直接new 后面再来修改成线程内唯一
private IUserInfoRepository _userInfoRepository;
public IUserInfoRepository UserInfoRepository
{
get
{
if (_userInfoRepository == null)
{
_userInfoRepository = new UserInfoRepository();
}
return _userInfoRepository;
} set
{
_userInfoRepository = value;
}
} private IProductRepository _productRepository;
public IProductRepository ProductRepository
{
get
{
if (_productRepository == null)
{
_productRepository = new ProductRepository();
}
return _productRepository;
}
set { _productRepository = value; }
} //执行sql脚本
public int ExecuteSql(string sql, ObjectParameter[] parameters)
{
return db.ExecuteFunction(sql, parameters);
} //单元工作模式
public int SaveChanges()
{
return db.SaveChanges();
}
}
}

然后我们抽象出一个接口,在 IRepository里面增加一个 IDbSession.cs

namespace YouJiao.MvcWeb.IRepository
{
public interface IDbSession
{
IUserInfoRepository UserInfoRepository { get; set; }
IProductRepository ProductRepository { get; set; } int ExecuteSql(string sql, ObjectParameter[] parameters); /// <summary>
/// 将整个数据库访问层的所有修改都一次性的提交回数据库
/// 业务逻辑层:一个业务场景,肯定会对多个表做修改,对多个表进行处理
/// 此方法的存在:极大的提高数据库访问层批量提交sql的性能,提高数据库的吞吐量,减少跟数据库的交互次数
/// </summary>
/// <returns></returns>
int SaveChanges(); //UnitWork模式
}
}

这样结构就变成了下图所示

MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一

然后我们再来修改一下 EF上下文的实例,在BaseRepository和DbSession里面都有用到 上下文,我们要保证这个上下文在线程内是唯一的

MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一

MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一

我们在 Repository层,创建一个EF的简单工厂   实际也就是一个类(DbEfContextFactory),里面一个静态方法(GetCurrentDbEfContext)

namespace YouJiao.MvcWeb.Repository
{
public class DbEfContextFactory
{
public static ObjectContext GetCurrentDbEfContext()
{
//CallContext:是线程内部唯一的独用的数据槽(一块内存空间) //传递dbcontext进去获取实例的信息,在这里进行强制转换。 ObjectContext context = (ObjectContext) CallContext.GetData("dbcontext");
if (context == null) //如果线程在数据槽里面没有此上下文
{
context=new ModelContainer(); //那么我们自己就new一个
CallContext.SetData("dbcontext",context); //放到数据槽中
}
return context;
}
}
}

现在我们来修改一下刚才 DbSession.cs  和 BaseRepository.cs

namespace YouJiao.MvcWeb.Repository
{
/// <summary>
/// 相当于是简单工厂:通过DbSession可以拿到所有的仓储的实例,所以我们也可以将此DbSession看做是简单工厂.
/// 职责:对整个数据库访问层做了高度抽象,它是整个数据库访问层的统一入口,BLL层来调用Repository层的时候
/// 只要拿到DbSession就可以拿到所有的仓储,就可以对所有的表进行增删改查了
/// </summary>
public class DbSession : IDbSession
{
public ObjectContext db
{
get
{
return DbEfContextFactory.GetCurrentDbEfContext();//EF上下文线程内唯一
}
}
private IUserInfoRepository _userInfoRepository;
public IUserInfoRepository UserInfoRepository
{
get
{
if (_userInfoRepository == null)
{
_userInfoRepository = new UserInfoRepository();
}
return _userInfoRepository;
}
set{_userInfoRepository = value;}
} private IProductRepository _productRepository;
public IProductRepository ProductRepository
{
get
{
if (_productRepository == null)
{
_productRepository = new ProductRepository();
}
return _productRepository;
}
set { _productRepository = value; }
} //执行sql脚本
public int ExecuteSql(string sql, ObjectParameter[] parameters)
{
return db.ExecuteFunction(sql, parameters);
} //单元工作模式
public int SaveChanges()
{
return db.SaveChanges();
}
}
}
namespace YouJiao.MvcWeb.Repository
{
public class BaseRepository<T> where T : class // 这里约束泛型T必须是个类
{
private ObjectContext db
{
get
{
return DbEfContextFactory.GetCurrentDbEfContext();//获取EF上下文的实例
}
} public IList<T> LoadEneities(Func<T, bool> whereLambda)
{
return db.CreateObjectSet<T>().Where(whereLambda).ToList();
} public IList<T> LoadPageEneities<S>(int pageSize, int pageIndex, out int total,
Func<T, bool> whereLambda, Func<T, S> orderbyLambda, bool isAsc)
{
var tempList = db.CreateObjectSet<T>().Where(whereLambda).ToList();
total = tempList.Count;
if (isAsc) //如果是升序
{
tempList = tempList.OrderBy(orderbyLambda)
.Skip(pageIndex * pageSize - 1) //越过多少条
.Take(pageSize).ToList(); //取出多少条
}
else
{
tempList = tempList.OrderByDescending(orderbyLambda)
.Skip(pageIndex * pageSize - 1)
.Take(pageSize).ToList();
}
return tempList;
} public T AddEntity(T model)
{
db.CreateObjectSet<T>().AddObject(model);
db.SaveChanges();
return model;
} public bool DeleteEntity(T model)
{
db.CreateObjectSet<T>().Attach(model);
db.ObjectStateManager.ChangeObjectState(model, EntityState.Deleted);
return db.SaveChanges() > 0;
} public bool UpdateEntity(T model)
{
db.CreateObjectSet<T>().Attach(model);
db.ObjectStateManager.ChangeObjectState(model, EntityState.Modified);
return db.SaveChanges() > 0;
}
}
}
上一篇:【转】仿百度输入框智能提示的js代码


下一篇:SQLite介绍、学习笔记、性能测试