1.建立数据库OA,表UserInfo

    

2.创建类库项目以及mvc4 web项目

  1)OA.Model 层:模型

  2)OA.IDal 层 :数据接口

  3)OA.Dal层 :数据实现

4)OA.IDBSession层 :会话接口

5)OA.DBSession 层 :会话层

6)OA.IBLL 层 :业务员接口

7)OA.BLL 层 :业务实现

8)OA.Web MVC UI层

3.编写代码

  1)在model层中添加EF上下文,

2)编写数据接口层的代码:对表的操作(1增2删3改4查5分页),在分页中返回总记录数,在查询中根据用户输入的lambda表达式进行具体查询一条记录或者多条记录

//增删改查 分页
T AddEntity(T t);
bool DeleteEntity(T t);
bool UpdateEntity(T t);
IQueryable<T> LoadEntities(Expression<Func<T,bool>> whereLambda);
IQueryable<T> LoadPageEntitis<s>(int pageIndex, int pageSize, out int toalCount,
Expression<Func<T, bool>> whereLambda,
Expression<Func<T,s>> orderByLambda,
bool IsAsc); 

View Code

  在分页中实现排序,并可选顺序或者逆序。LoadPageEntites<s> s代表orderByLambda值的类型,当使用id进行排序时,<s>值为int,当使用name进行排序时,<s>值为string。

因为每一张表都要实现这个接口,因此将如上“//增删改查 分页”封装成IBaseDal<T>。其他表只需要继承IBaseDal<T>,将对应的表传入T即可。

1     public interface IDeviceInfoDal : IBaseDao<SYS_DEVICE_TABLE>
2     {
3
4     }

View Code

3)编写Dal层,继承自IDal,一个表对应一个dal,例如userinfo这张表,创建UserInfoDal继承自IUserInfoDal,实现IUserInfoDal的接口,IUserInfoDal继承自IBaseDal,每一张表都需要实现这些接口((1增2删3改4查5分页)),因此,需要继续封装这些接口的实现,封装成BaseDal

 1     public class BaseDal<T>
 2         where T:class,new()
 3     {
 4         MLedSystemEntities dbContext = DBContxtFactory.CreateDbContext();
 5         public T AddEntity(T t)
 6         {
 7             dbContext.Entry<T>(t).State = EntityState.Added;
 8             //dbContext.SaveChanges();
 9             return t;
10         }
11
12         public bool DeleteEntity(T t)
13         {
14             dbContext.Entry<T>(t).State = EntityState.Deleted;
15             return true;//dbContext.SaveChanges() > 0;
16         }
17
18         public bool UpdateEntity(T t)
19         {
20             dbContext.Entry<T>(t).State = EntityState.Modified;
21             return true;//dbContext.SaveChanges() > 0;
22         }
23
24         public IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda)
25         {
26             return dbContext.Set<T>().Where(whereLambda);
27         }
28
29         public IQueryable<T> LoadPageEntitis<s>(int pageIndex, int pageSize, out int toalCount, System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T,s>> orderByLambda, bool IsAsc)
30         {
31             var res = dbContext.Set<T>().Where(whereLambda);
32             toalCount = res.Count();
33             IQueryable<T> temp;
34             if (IsAsc)
35             {
36                 temp = res.OrderBy<T, s>(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
37             }
38             else
39             {
40                 temp = res.OrderByDescending<T, s>(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
41             }
42             return temp;
43         }
44
45     }

View Code

而每一张表只需要继承自BaseDal即可,如此大大提高代码重用。先继承实现,再继承接口,

    public class DeviceTypeInfoDal : BaseDal<SYS_DEVICE_TYPE_TABLE>, IDeviceTypeInfoDal{}

View Code

    public class DeviceInfoDal :BaseDal<SYS_DEVICE_TABLE>, IDeviceInfoDal{}

View Code

  这里需要改进的地方是:每一次操作增删查改都需要savechange()一次,每一次操作都需要连接数据库,假设用户的有一次操作是关联三张表,那么一次操作就需要三次打开数据库连接,然后又关闭数据库连接,如此,效率大大下降。解决办法:将SaveChange()提取出来,使得用户操作一次无任关联多少张表,只需要一次数据库操作即可。(由会话层来实现)

  4)编写中间会话层,会话层的作用是降低业务层与数据层的耦合。

  编写会话层接口和实现

  会话层主要作用:是对数据实现层的管理,以及如上提到的一次性SaveChange的问题。

        IDeviceInfoDal DeviceInfoDal { get; set; }IDeviceTypeInfoDal DeviceTypeInfoDal { get; set; }bool SaveChange();

View Code

 1 MLedSystemEntities dbContext {
 2             get {
 3                 return DBContxtFactory.CreateDbContext();
 4 //这里需要保证EF上下文唯一,也就是线程安全
 5             }
 6         }
 7         public IDeviceInfoDal DeviceInfoDal
 8         {
 9             get
10             {
11                  //return DBSessionFactory.CreateDeviceInfoDal();
12                 return AbstractFactory.CreateDeviceInfoDal();
13         //这里使用抽象工厂创建对象实例-》目的:降低耦合度
14 } set { DeviceInfoDal = value; } } public IDeviceTypeInfoDal DeviceTypeInfoDal {
15 get {
16 //return DBSessionFactory.CreateDeviceTypeInfoDal();
17 return AbstractFactory.CreateDeviceTypeInfoDal();
18 //这里使用抽象工厂创建对象实例-》目的:降低耦合度
19 } set { DeviceTypeInfoDal = value; } } public bool SaveChange() { return dbContext.SaveChanges()>0; }

View Code

  如何保证EF上下文线程安全呢?这里使用的是CallContext这个类进行管理。

/// <summary>
/// EF上下文,线程唯一性
/// </summary>
public static MLedSystemEntities CreateDbContext()
{
MLedSystemEntities DbContext = CallContext.GetData("dbContext") as MLedSystemEntities;
if (DbContext == null) {
DbContext = new MLedSystemEntities();
CallContext.SetData("dbContext",DbContext);
}
return DbContext;
}

  //抽象工厂 使用反射的方法进行 解耦

  在web.config中添加配置节点

<add key="DalAssemblyPath" value="OA.Dal"/>
<add key="NameSpace" value="OA.Dal"/>

代码如下:

private static readonly string DalAssemblyPath = ConfigurationManager.AppSettings["DalAssemblyPath"];
private static readonly string NameSpace = ConfigurationManager.AppSettings["NameSpace"];

/// <summary>
/// 创建DeviceInfo实例
/// </summary>
/// <returns></returns>
public static IDeviceInfoDal CreateDeviceInfoDal()
{
string fullClassName = NameSpace + ".DeviceInfoDal";
var assembly = Assembly.Load(NameSpace);
return assembly.CreateInstance(fullClassName) as IDeviceInfoDal;
}

  5)编写业务接口层和业务实现层。在业务接口层同数据操作DAL层类似

    需要注意的是:需要保证会话层线程安全,同样是使用CallContext来进行管理

  public DBSession CreateDBSession(){

    DBSession dbSession=CallContext.GetData("dbsession") as DBSession;

if(dbSession==null){

dbSession=new DBSession();

CallContext.SetData("dbsession",dbSession);

}

return dbSession;

  }

  6)MVC ui层调用业务层,业务层调用会话层,会话层调用数据层。

  在UI层中,添加对应表的Controller,异步加载方式获取数据。

view中:

<table border="1 solid red" id="tab">
@Html.ActionLink("添加","Create")
<tr>
<th width="50">id</th>
<th width="50">name</th>
<th width="50">ip</th>
<th width="50">port</th>
</tr>
<tbody id="list"></tbody>
</table>

js代码:

<script type="text/javascript">
$(function () {
onAsynLoad(3,5);
});
function onAsynLoad(pageindex, pagesize) {
$.getJSON(
'@Url.Action("AsynLoad","DeviceInfo")',
{ pageIndex: pageindex, pageSize: pagesize },//传入参数
function (temp) {//temp为返回的结果
var list = $('#list');
list.empty();
$.each(temp.list1, function (index, item) {
list.append('<tr><td>' +
item.id + '</td><td>' +
item.Name + '</td><td>' +
item.Ip + '</td><td>' +
item.Port + '<a href="@Url.Action("Delete","DeviceInfo")?id=' + item.id + '">删除</a></td></tr>')
});
list.append('<tr><td colspan=4>总记录数:' + temp.tolCount + '</td></tr>');
}
);
}
</script>

View Code

Controller中的异步加载代码:

 1 public ActionResult AsynLoad(int pageIndex, int pageSize)
 2         {
 3             //int pageIndex=1;
 4             //int pageSize=4;
 5             int totalCount=0;
 6             var result = DeviceInfoService.LoadPageEntitis<int>(pageIndex, pageSize, out totalCount, u => true, u => u.DEVID, true).ToList();
 7             List<DeviceInfoViewModel> listDeviceInfoViewModel=new List<DeviceInfoViewModel>();
 8             foreach(var res in result){
 9                 DeviceInfoViewModel item=new DeviceInfoViewModel();
10                 item.id=res.DEVID;
11                 item.Name=res.DEVNAME;
12                 item.Ip=res.DEVIP;
13                 item.Port=res.DEVPORT;
14                 listDeviceInfoViewModel.Add(item);
15             }
16             var temp = new
17             {
18                 list1 = listDeviceInfoViewModel,
19                 tolCount = totalCount.ToString()
20             };
21             return Json(temp,JsonRequestBehavior.AllowGet);
22         }

View Code

总结:关键知识点:1、EF线程安全、会话层线程安全。

         2、抽象工厂创建实例解耦。

         3、使用会话层解耦。

代码下载

http://files.cnblogs.com/files/jxsd/OA.Web.zip

http://files.cnblogs.com/files/jxsd/OA1.zip

转载于:https://www.cnblogs.com/jxsd/p/4993748.html

MVC三层+会话层+线程安全+抽象工厂+DataBase First的基础框架相关推荐

  1. 剪不断,理不乱——三层架构之抽象工厂加反射

    三层架构前面已经介绍过了,浅谈三层架构.本篇文章主要介绍三层架构中加入抽象工厂和反射加配置文件.以机房收费系统的登录为例. 首先对机房收费系统进行分层,分为三层表示层,业务逻辑层,数据访问层.为了降低 ...

  2. 漫画:什么是 “抽象工厂模式” ?

    作者 | 小灰 来源 | 程序员小灰(ID:chengxuyuanxiaohui) 所谓"工厂模式",是三种常见设计模式的统称,它们分别是简单工厂模式.工厂方法模式.抽象工厂模式. ...

  3. MVC+EF三层+抽象工厂

    MVC+EF三层+抽象工厂项目搭建 注意:项目经过两次搭建,所以截图中顶级命名空间有ZHH和ZHH2区别,但是架构的内容是一样的,可以将ZHH和ZHH2视为同一命名空间 一:权限管理 二:搜索 |-L ...

  4. MVC+EF三层+抽象工厂项目搭建

    注意:项目经过两次搭建,所以截图中顶级命名空间有ZHH和ZHH2区别,但是架构的内容是一样的,可以将ZHH和ZHH2视为同一命名空间 一:权限管理 二:搜索 |-Lucene.net(速度快)+盘古分 ...

  5. 《三层架构之抽象工厂加反射》纠错

    每当别人问我关于三层的知识的时候我总是推荐自己的<三层架构之抽象工厂加反射>这篇博客.这篇博客是自己当时学习三层的时候写的一个简单的登录例子.这个例子通过登录这个用例简单的介绍了三层,然后 ...

  6. 三层架构之抽象工厂加反射mdash;mdash;实现数据库转换

    在做系统的时候有意识的用到了抽象工厂这个设计模式,主要解决的是数据库更换的问题. 下面就以简单的登录来逐步的分析一下这个模式. 经典的三层架构 数据库如下 1.      一般的数据库连接方式 界面层 ...

  7. java实现仿qq界面及功能、网路编程、实现抽象工厂模式、线程池代码与测试

    java实现仿qq界面及功能 用Swing 代码在百度网盘:http://pan.baidu.com/s/1pJjxI4b 具体见https://www.iteye.com/topic/1137293 ...

  8. 抽象工厂————三层架构

    抽象工厂作用:降低BLL和Model层耦合度 核心思想:1.通过接口类实现对象的分离   2.通过一个类,实现指定对象的创建,并且这个类通过配置文件决定获取哪个对象 这样只要调用一个接口和这个类,就能 ...

  9. 《大话设计模式(C#实现)》(Yanlz+VR云游戏+Unity+SteamVR+云技术+5G+AI+设计模式+GoF+UML+单例模式+观察者模式+抽象工厂+代理模式+框架编程+立钻哥哥++OK+)

    <大话设计模式(C#实现)> 版本 作者 参与者 完成日期 备注 YanlzFramework_GoF_V01_1.0 严立钻 2020.02.10 ##<大话设计模式(C#实现)& ...

最新文章

  1. 解决Oracle数据库不能导出空表的问题
  2. candence的图纸大小设置_在Orcad Cadence中设置原理图页码
  3. ASP.NET技术的学习顺序
  4. 用选框工具画圆角矩形
  5. 确定进制(信息学奥赛一本通-T1413)
  6. RMAN报错:ORA-19573: 无法获得 exclusive 入队
  7. 封装系统驱动放哪里啊_MPS做一体化电机驱动方案有三大绝招
  8. python fread_fwrite 和 fread函数的用法小结
  9. 锐文网络安全网闸卡各种应用场景
  10. arm嵌入式led灯闪烁实验报告_ARM嵌入式系统与应用实验报告
  11. Mac上添加自己/公司的网络服务器盘
  12. ctf流量分析练习二
  13. 登录页面,登录后跳转不成功
  14. 高德地图定位失败_常见问题
  15. Matlab之在城市环境中基于动态占用网格图的的运动规划仿真(附源码)
  16. 多维分析,为什么企业开始大规模应用商业智能(BI)
  17. 支付宝支付接口遇到的问题总结
  18. UnityGUI简介
  19. adb bugreport -- Failed to get bugreportz version
  20. “调节阀”发脾气了你怎么办?

热门文章

  1. 入门机器学习,看这些材料就够了
  2. 无法下载linux系统的驱动精灵,有没有LINUX版的 驱动精灵 破系统搞驱动太费劲,尤其笔记本电脑...
  3. java网格式布局登录界面_Java学习笔记------自己书写的登录界面实例
  4. 设计模式之工厂模式和抽象工厂
  5. 010_AOPXml方式开发
  6. 005_JavaScript使用
  7. mysql主从架构搭建_MySQL主从架构搭建
  8. Linux安装jellyfin硬件加速,proxmoxVE LXC 安装设置 Jellyfin 多媒体家庭影院
  9. mysql 一键脚本_mysql一键安装脚本
  10. linux怎么改程序图标,如何在Ubuntu Unity上更换应用程序图标