上一篇博客小编简单介绍了一下近期在软件开发过程中由三层架构演变而来的“七层架构”基本理论点。理论知识与产生结果之间还夹杂着一个重要的点---实践。用实践来检验理论知识,丰富知识内涵、加深对其理解。接下来小编用一个简单的小实例来为您分享由三层架构演变而来的“七层架构”。

【1】首先,搭建七层结构的框架;

搭建结构可以仿照小编前面的博文<三层实践>来完成哦。

【2】其次,设置好层与层之间的引用关系;

具体的引用关系,请参看<上篇博客>。

【3】再次,添加需要的类;

添加方式与<三层实践>相同哦。

【4】最后,设计UI并进行编码。

这一步骤也与<三层实践>是大抵相同的,这里不再重复赘述。

接下来主要以员工登录功能需求为例,为您分享“七层架构”是如何实现这一功能需求的。探索层与层之间是如何取得联系的、参数是如何传递的、每一层有着哪些更为具体的作用。

❉❉ 首先,在D层下新建的类中封装需要的SqlHelper方法,用于创建数据库的连接。

public  class SQLHelper{//声明对象private SqlConnection conn = null;       //SqlConnection 打开连接private SqlCommand cmd = null;          //SqlCommand对象允许你指定在数据库上执行的操作的类型。比如,你能够对数据库中的行数据执行select,insert,modify以及delete命令。//SqlCommand对象能被用来支持断开连接数据管理的情况,可以只单独使用SqlCommand对象。也可以与SqlDataAdapter一起实现断开数据连接,实现操作数据库的应用程序private SqlDataReader sdr = null;        //读取只进的行流的方式//构造方法public SQLHelper(){string connStr = ConfigurationManager.AppSettings["connStr"];     //定义连接数据库字符串参数。connStr 是配置文件里连接数据库的关键字,引用这一句可以连接数据库conn = new SqlConnection(connStr);   //实例化一个连接,将连接数据库的字符串参数传递给连接对象}// 将数据库连接打开private SqlConnection GetConn(){if (conn.State == ConnectionState.Closed)     //如果连接状态为关闭 {conn.Open();     //则打开}return conn;}/// <summary>/// 执行 不带参数 的 增删改SQL语句 或者 存储过程/// </summary>/// <param name="cmdText">增删改SQL</param>/// <param name="ct">命令类型</param>/// <returns>返回受影响的行数</returns>public int ExecuteNonQuery(string cmdText, CommandType ct)//增删改 SQL   命令类型{int res;try{cmd = new SqlCommand(cmdText, GetConn());     //打开连接cmd.CommandType = ct;res = cmd.ExecuteNonQuery();}catch (Exception ex){throw ex;}finally{if (conn.State == ConnectionState.Open){conn.Close();     //关闭数据库 与上面相对应}}return res;}/// <summary>/// 执行 带参数的的 增删改SQL语句  或者 存储过程/// </summary>/// <param name="cmdText">增删改SQL</param>/// <param name="paras">要查询的参数</param>/// <param name="ct">命令类型</param>/// <returns>返回受影响的行数</returns>public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct){int res;using (cmd = new SqlCommand(cmdText, GetConn()))     //使用using,在三层实践篇中有介绍哦   {cmd.CommandType = ct;cmd.Parameters.AddRange(paras);res = cmd.ExecuteNonQuery();}return res;}/// <summary>///  执行 不带参数的 查询SQL语句 或 存储过程/// </summary>/// <param name="cmdText">查询SQL语句或存储过程</param>/// <param name="ct">命令类型</param>/// <returns></returns>public DataTable ExecuteQuery(string cmdText, CommandType ct){DataTable dt = new DataTable();cmd = new SqlCommand(cmdText, GetConn());cmd.CommandType = ct;using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)){dt.Load(sdr);}return dt;}/// <summary>/// 执行 带参数的   查询SQL语句 或 存储过程/// </summary>/// <param name="cmdText">查询SQL语句或存储过程</param>/// <param name="paras">参数集合</param>/// <param name="ct">命令类型</param>/// <returns></returns>public DataTable ExecuteQuery(string cmdText, SqlParameter[] paras, CommandType ct){DataTable dt = new DataTable();cmd = new SqlCommand(cmdText, GetConn());cmd.CommandType = ct;cmd.Parameters.AddRange(paras);using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)){dt.Load(sdr);}return dt;}#endregion}

❀❀ 在封装的SqlHelper方法中,为什么要把对数据库的 “查”操作与“增删改”操作的方法分开来写呢?

最本质的原因是,Sql Server执行Select语句与Insert、Delete、Update语句时,返回的结果是不一样的。前者返回的结果是一个临时表,而后者返回的结果是受到影响的行数。

❉❉其次,在每一层中编写实现功能的方法。

[1] 实体层:定义字段、属性,用于实现功能过程中的传参。

namespace Entity
{public enum StaffLoginState//采用枚举的方法,列登录时可能出现的情况{OK,//成功NoError,//失败}public  class StaffInfo //StaffInfo类型所需要的字段。字段名称最好与数据库表中字段保持一致,方便区分。{private int adminid;public int adminID{get { return adminid; }set { adminid = value; }}private string adminname;public string adminName{get { return adminname; }set { adminname = value; }}private string password;public string Password{get { return password; }set { password = value; }}private string head;//级别public string Head{get { return head; }set { head = value; }}private string isdelete;//是否已注销public string Isdelete{get { return isdelete; }set { isdelete = value; }}}
}

[2] 接口层:只是用来定义实现功能所需的方法名。这一层只有抽象的方法名,而没有具体实现功能的方法体。

namespace IDAL
{public partial  interface StaffIDAL{StaffInfo SelectByID(int id);//定义一个类型为Staffinfo 名为SelectByID 带参数的方法。这是根据ID查询员工信息的方法,用于员工登录等功能。}
}

[3] 数据访问层:D层实现接口层中定义的方法。该层中的方法名 要与接口层中定义的方法名保持一致,且有具体实现功能的方法体。

namespace DAL
{public partial  class StaffDAL:StaffIDAL  //实现接口的方法{#region 根据员工ID 获取员工信息---用于员工登录public StaffInfo SelectByID(int id){            StaffInfo staff = null ;//声明一个用户SQLHelper sqlHelper = new SQLHelper();        //实例化类  跳转到SQLHelper方法string sql = @"select * from Staff_Info where adminID=@adminID and isdelete='否'";//构造Select查询语句 匹配数据库SqlParameter p = new SqlParameter("@adminID", id);//为语句构造参数DataTable dt = sqlHelper.ExecuteQuery(sql, p,CommandType.Text); //连接数据库 执行查询得到结果if (dt.Rows.Count >0) //判断数据表里是否查到结果{staff = new StaffInfo()//若用户存在{//获取用户信息adminID=Convert.ToInt32(dt.Rows[0][0].ToString()),Password=dt.Rows [0][2].ToString(),adminName=dt.Rows[0][1].ToString(),Head=dt.Rows[0][3].ToString(),};}return staff;//返回一个用户对象}#endregion}
}

[4] 工厂层:设置配置文件信息,选取所需的数据库;创建相应的接口对象来实现接口层中的方法。

在App.config中设置配置文件信息:

上面是从网上查到的配置文件信息的两种方法,用其中的一组(appSettings 或 connectionStrings)就可以实现目前所需的功能。至于这两种有什么更为具体的区别,目前小编还不是很清楚哦。

配置文件的方式不同,就会影响到SQLHelper中连接数据库的方法。以上两种配置文件的形式分别对应下面的SQLHelper中连接数据库所需拼接的字符串:

在工厂层下的类中编写代码:

//需要添加的引用。
using System.Reflection;
using System.Configuration;namespace Factory
{public  class StaffFactory{private string StrDB = ConfigurationManager.AppSettings["DB"];    //接收来自配置文件的数据public IDAL.StaffIDAL CreateUser(){string ClassName = StrDB + "." + "StaffDAL";   //这里的StaffDAL是D层的类名         return (IDAL.StaffIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);   //反射加工厂的应用}}
}

这里在添加引用时,需要先在工厂层的引用下 添加该程序集的引用。

 

工厂+反射的应用,是为在大型项目开发过程中方便更换数据库。

[5] 业务逻辑层:进行逻辑判断。

namespace BLL
{public partial  class StaffBLL{private StaffIDAL  idal;StaffFactory fact = new StaffFactory();//实例化工厂对象public StaffBLL () //构造方法{idal = fact.CreateUser();}public StaffLoginState Login(int id,string pwd,out string head,out string adminame){//使用out传值 需要给参数定义初值head = null;//定义head为空值adminame = null;//根据用户名进行对象查询StaffIDAL idal = fact.CreateUser();//调用工厂方法创建接口StaffInfo staff = idal.SelectByID(id);//接收D层的返回值if (staff ==null) //判断是否存在用户对象{//用户不存在//用户名或密码错误return StaffLoginState.NoError;}else{//用户存在                head = staff.Head;//返回用户头衔 及姓名adminame = staff.adminName;return StaffLoginState.OK;                              }}}
}

[6] 外观层:解耦U层和B层,接收和传递参数。

namespace Facade
{public  class StaffFacade{StaffBLL staffBll = new StaffBLL();//实例化B层对象//用户登录public StaffLoginState Login(int id,string pwd,out string head,out string username){return staffBll.Login(id, pwd, out head, out username);//接收B层返回的值,并将其传给U层}}
}

[7] 显示层:与用户直接关联,接收用户输入的信息,并返回结果。

namespace UI
{public partial class frmLoginStaff : Form{public frmLoginStaff(){InitializeComponent();}//声明静态变量 用于其他功能获取登录的用户名 传值// 登录的方法private void Login(){if (txtUserID.Text.Trim ()==""||txtPWD .Text==""){MessageBox.Show("请将登录信息填写完整");return;//停止后面代码的执行 返回到if之前}//声明变量,接收返回的值string head;string adminame;//获取用户输入的信息int ID = Convert.ToInt32(txtUserID.Text.Trim());string pwd = txtUserID.Text;StaffFacade staffFacade = new StaffFacade();StaffLoginState state = staffFacade.Login(ID, pwd, out head, out adminame);switch (state){//登录成功case StaffLoginState.OK:staff.Head = head;staff.Adminid = ID;staff.adminName = adminame;this.Hide();MessageBox.Show("登录成功");frmMainStaff main = new frmMainStaff();main.Tag = head;//判断用户级别,用于给主窗体传值                   main.Show();                     break;//登录失败case StaffLoginState.NoError:MessageBox.Show("用户不存在或输入信息错误");txtPWD.Text = "";txtUserID.Text = "";break;default:break;}}}
}

到此为止,基本的编码工作就完成啦。点击登录,迫切的希望看到“登录成功”弹出框,然后并没有。经过不断调试,出现的最大问题就是依赖项,找不到文件。解决这问题可是花费了小编不少精力呢。

❀❀按照三层架构的基本理论,UI层只需引用与其最直接关联的BLL层即可,而没有引用DAL层。之前在用三层架构做项目时就出现了缺少依赖项,找不到文件的问题。当时解决办法就是简单的上网查查,通过复制DAL层文件到UI层Debug文件夹下来解决的。这次用七层做项目又遇到了这个问题,这一次在解决这个问题的时候真是花费了不少时间呢。这次的解决办法没有采用复制文件的方式,而是在UI层中增加对DAL层引用。

❀❀为什么UI层还需要引用与其间接相关的DAL层呢?

【在此之前也尝试过BLL层、Facade层等凡是没有引用DAL层的都引用了一遍,但又会出现新Bug】

最本质的原因就是DAL层中的方法才是真正实现业务功能的最底层、最元(元:不可再分)始的方法,它包含与数据库直接关联的信息。按照理论点的话,只有直接依赖的层需要引用,没有间接引用。但实际上U层需要的文件应该是产生在U层debug下,在没有添加D层的引用时,生成的U层文件中没有D层真正实现功能的文件。虽然U层最直接依赖的是Facade层,但D层dll文件包含真正实现功能的方法。换句话说,Facade层中封装的方法 是对与其直接关联的层中方法的封装,是可拆分的方法;每层中的方法拆分后,最小单位的方法便是DAL层中的方法,它是不可再分的封装的方法。所以实际做项目过程中还是间接引用了D层,在生成解决方案时,D层中的文件也同时放在了U层中。这样程序在运行过程中就可以直接从UI层的Debug文件路径下找到DAL层中实现功能需求的.dll文件了。或者复制D层文件、更改输出路径到U层下。但个人还是倾向将U层添加D层引用。

到此为止,小编为您分享的“七层架构”就要告一段落啦。实践出真知,实践能让我们对理论知识有进一步的认识与理解,丰富知识的内涵。

感谢您的浏览,希望能对您有所帮助哦!

“七层架构”-----实践篇-登录小实例相关推荐

  1. 三层架构-----实践篇-登录小实例

    上一篇博客小编简单介绍了一下我们在软件开发过程中应用到的三层架构基本理论.光有理论还是远远不够的,只有真正的 在项目中实践过,才能更好地理解它的精髓所在.接下来小编以一个实现登录功能的小例子来展现三层 ...

  2. C#七层架构 ----【登录】

    学习完三层之后对于三层有了大概的了解,结束了三层的学习便带着好奇来到了机房重构的学习当中. 在机房重构中第一问题就是要做"登录功能",这个登录功能用到了七层的架构. 今天我们就来学 ...

  3. “七层架构”---理论篇

    前段时间在做项目的过程中运用到了三层架构.最近在做项目过程中,又将三层架构进行扩充至七层.下面小编为您分享这延伸出来的"七层". "七层"包括哪些层? &quo ...

  4. 开放式系统互联模型(网络的七层架构)

    文章目录 前言 开放式系统互联模型(网络的七层架构) 1.物理层 2.数据链路层: 3.网络层: 4.传输层: 5.会话层: 6.表示层: 7.应用层 : 前言   如果您觉得有用的话,记得给博主点个 ...

  5. 一句口诀记忆计算机网络七层架构模型和TCP/IP五层模型(记不住你打我)

    文章目录 前言 一. 1.1 OSI七层网络模型(口诀:物联网叔会使用) 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 二. TCP/IP 五层模型(记忆口诀:物联网,叔应用) 物理层 ...

  6. 浅谈计算机网络七层架构

    计算机网络结构 国际标准化组织ISO 于1981年正式推荐了一个网络系统结构--七层参考模型,叫做开放系统互连模型(Open System Interconnection,OSI).由于这个标准模型的 ...

  7. C# 三层架构与七层架构

    前言 学习三层的时候对于这三层有了大致的了解,但是还是说不出个一二,今天试着总结一下,将自己的知识重新梳理一遍. 三层架构 概念 三层架构通常意义上讲的就是将整个业务应用划分为:表现层(UI).业务逻 ...

  8. asp.net七层架构是指什么

    三层 Domain(实体层),Dao( 数据访问层 ),Srv( 业务逻辑层 ) 面向接口编程 (5层) Doamin(实体层),IDao( 数据访问层 接口),Dao( 数据访问层 ),ISrv( ...

  9. VB.NET版机房收费系统---七仙女之系统登录

    VB.NET第一版机房收费系统,告一段落,验收的时候,问题也是大大的存在,没有用上设计模式,什么触发器,存储过程,都没有用上,看看其她小伙伴的,七层实现登录?那是什么东东,相比较我的三层而言,多了两倍 ...

最新文章

  1. [PHP]常量的一些特性
  2. 【转】Windows8不联网直接安装.Net 3.5 Framework的方法
  3. Mobile first 设计思路在 SAP 电商云 Spartacus UI 中的设计体现一例
  4. 程序员效率:如何合理的分解任务
  5. 2018怎么更换图框_2018 乐博睿 全年回顾
  6. 支付宝兑换的扫地机器人_支付宝里这笔钱赶紧用掉!年底过期作废
  7. JQUERY--图片轮换superslide(
  8. 相信很多人心里都有着一个自媒体的梦想
  9. 曾惨遭 Google、Tesla 淘汰,辗转 8 个月,他是如何成为一名顶尖的 AI 工程师?...
  10. 机器人启示录 百度影音_斯皮尔伯格筹备新作 《机器人启示录》有望启动
  11. 微信扫码免密登陆第三方应用平台
  12. 系统监视器(Sysmon)工具的使用
  13. efs+pro+for+三星android设备,【极光ROM】-【三星S8/S8+ G9550/G9500】-【V30.0 Android-PIE-TL2】...
  14. “应用程序无法正常启动 0xc0150002”如何解决?
  15. java解四元一次方程
  16. Tomcat启动异常:A child container failed during start 与 ClassNotFoundException解决方法
  17. 【机器视觉】Halcon 19安装教程详解
  18. 全球最受欢迎电商平台有哪些?这些平台怎么快速增加销量?
  19. 怎么把中文用户名改成英文?
  20. 总投资460亿!陈十一院士任校长,东方理工大学年薪40-60万招人

热门文章

  1. dbms_metadata.get_ddl的使用总结
  2. 利用互斥体阻断想哭蠕虫,实现联网升级
  3. linux下tomcat部署
  4. 单机PC手动更改windows update 地址
  5. 先序、中序确定二叉树
  6. oracle学习--循环语句
  7. 语音交互编程语言了解一下?
  8. Research Fellow、Research Assistant、predoc等的区别
  9. 如何具备无坚不摧的意志力
  10. datagrip导入csv数据配合ajax+mysql+Flask实验