【ASP.NET开发】.NET三层架构简单解析

这篇文章原本应该很早就写出来的,可是一直苦于本身的精神能力有限,并且已经到了咱们学校的考试周,因此时间上仍是有点紧迫。关键的一点就是,找不到合理的思路来写,思路没有的话,就算是再好的素材,也写不来你们喜欢的文章。程序员

以前已经写过关于.NET三层架的两篇文章了,一篇是《【ASP.NET开发】ASP.NET(MVC)三层架构知识的学习总结》《【ASP.NET开发】ASP.NET对SQLServer的通用数据库访问类》。若是你们有兴趣的话,能够去读一读。固然了,这两篇文章的内容,大部分都不是本身的,本身也是看了别人的博文,而后本身总结一下,拿过来本身用罢了。此次的文章主要是本身亲自使用这些知识作了一个项目(咱们学校资环学院的院网站),而后拿出来跟你们分享一下。也不要指望博主可以写出多么有水平的文章,我仍是学生(大三),我也是在学习的过程当中,写博客之不过是想记录本身学习过程当中的点滴和记录本身的进步,若是可以顺便的帮助别人学习就更好了。同时也但愿你们可以多给我提意见。web

很是感谢博客园博友 @ 守护晴天,@Adming,@ Qlin等博友给我提出的宝贵的修改意见。也但愿你们在阅读本博文的时候,若是有什么问题,或者疑问及时的给我留言沟通,你们一块儿探讨。sql

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------数据库

对于三层架构来讲,主要是使用设计模式的思想,对于项目的各个模块实现"高内聚,低耦合"的思想。这里就不作详细的介绍了,若是你们有兴趣,能够阅读软件工程和设计模式相关文章。设计模式

咱们能够先来看一个图,来大概的了解一下,三层架构所要表达的思想。数组

我之前本身作的图,被你们指出了不少的错误。因此,我就引用了网络上的一个图片来解释(若是侵害了您的版权,请您联系我网络


对于三层架构来讲,就是使用类,把咱们在作项目的过程当中,可能须要反复操做数据库,反复的使用某个方法等等,可能就是操做的参数不一样。若是咱们若是在每次使用的时候,都去编写相应的代码,无疑会增长程序员的负担。因此,为了增长方法的重用,就把这些可以重用的方法抽象成类,以供程序员在其它地方能够调用。架构

固然了,这也是面向对象的一部分。其中的三层所指的就是:①视图层(UI)②数据库访问层(DAL)③业务逻辑层(BLL)。固然了,还有所谓的第四层-实体层(model),这一层主要是在这三个层之间进行流动传递。可是为何不叫四层架构。。。缘由我也不知道,多是由于实体层是外在的能够根据须要会随时变化的(如:项目后续模块的添加等)。而其它三个层,若是搭建完后,能够做为框架来使用的。。。框架

1)首先仍是先来介绍一下实体层吧,就是咱们一般所说的modelide

实体就是咱们在开发项目过程当中所要涉及的一些对象。把这些所要涉及的对象(如:新闻名称,新闻上传时间,供稿人,上传文件的名称等),都抽象成一个类。使用封装字段方法,咱们能够在视图层通(主要是视图层)过实例化对象的方法,来给咱们的对象的属性赋值。

简单的看一段代码吧,可能会可以更加的清楚,明白


  
  
  
  
  1. publicclass NewsModel

  2. {

  3. //新闻编号

  4. privateint nNewsId;

  5. publicint NNewsId

  6.    {

  7. get { return nNewsId; }

  8. set { nNewsId = value; }

  9.    }

  10. //新闻名称

  11. privatestring strNewsName;

  12. publicstring StrNewsName

  13.    {

  14. get { return strNewsName; }

  15. set { strNewsName = value; }

  16.    }

  17. }

这里的NewsModel就是一个关于新闻的实体类,其中声明了两个private的属性字段(必定要是private,防止非法赋值),使用public的构造函数,能够在外部给字段赋值。


下面的就是在视图层来实例化对象,根据须要来给字段赋值,看下面的一段代码:


  
  
  
  
  1. NewsModel newModel = new NewsModel();

  2.       newModel.StrNewsName = this.TextBox1.Text;

固然了,这仅仅是一段代码,其中并无给字段nNewsId赋值,由于我把它做为数据库的id地段,已经设置成自动增加。这样,就完成了视图层对实体层的调用。


2)数据库访问层

数据库库访问层,顾名思义,就是主要来完成对数据库的访问,等一系类的对数据库操做的类。为何要单独的把对数据库的操做抽象成一个单独的类,我我的理解是由于在整个项目的开发过程当中,不只仅须要一次访问数据库,而是须要屡次,若是每次都编写数据库访问代码的话,会增长程序员的我的工做量,并且对于代码的易用性和简洁性来讲确定是很是糟糕的。固然来可能还有其它的一些优势,我暂时尚未发现。

既然是对数据库的操做类,并且对数据库的操做,无非就是四种:增删改查。因此一个能提供增删改查的通用类是必不可少的。这就是咱们常常所说的,通用数据库访问类(不少的程序员都喜欢把这个类命名为SqlHelper,既然是名字,都是能够随意起的,只要不违反C#语法命名规范,固然这样命名也是有好处,就是可使其余程序员根据类的名称,大概判断出这个类是要干什么的)。

固然了,我此次作本身项目的时候,所写的数据库访问类就没有我上次看周金桥老师的书,而后模仿写的数据库访问类那么的复杂了(《【ASP.NET开发】ASP.NET对SQLServer的通用数据库访问类》)。固然了,我这里的数据库访问类,主要仍是为了简介,和易用,只要知足我本身当前项目的须要就能够了,不是每作一个项目,都要写一个功能全面的数据库访问类。

代码以下,请你们参考,更喜欢哪一个访问类,本身能够根据本身口味,或者须要,直接用也能够:


  
  
  
  
  1. /// <summary>

  2. ///建立一个SqlHelper的数据库访问通用类,完成对数据库的全部操做

  3. /// </summary>

  4. publicclass SqlHelper

  5. {

  6. //定义数据库的链接字符串

  7. privatestaticreadonlystring connectionString = ConfigurationManager.ConnectionStrings["strConnectionString"].ConnectionString;

  8. /// <summary>

  9. /// 建立方法,完成对数据库的非查询的操做

  10. /// </summary>

  11. /// <param name="sql">sql语句</param>

  12. /// <param name="parameters">传入的参数</param>

  13. /// <returns></returns>

  14. publicstaticint ExecuteNonQuery(string sql, params SqlParameter[] parameters)

  15.    {

  16. if (string.IsNullOrEmpty(sql))
           {

  17. using (SqlConnection con = new SqlConnection(connectionString))

  18.        {

  19.            con.Open();

  20. using (SqlCommand cmd = con.CreateCommand())

  21.            {

  22. try{

  23.                cmd.CommandText = sql;

  24.                cmd.Parameters.AddRange(parameters);

  25. string str = sql;

  26. return cmd.ExecuteNonQuery();

  27. }

  28. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  29.            }

  30.        }

  31. else
           {
               return -1;
           }

  32.    }

  33. /// <summary>

  34. /// 完成查询的结果值

  35. /// </summary>

  36. /// <param name="sql">sql语句</param>

  37. /// <param name="parameters">传入的参数数组</param>

  38. /// <returns></returns>

  39. publicstaticint ExecuteScalar(string sql, params SqlParameter[] parameters)

  40.    {

  41. if (string.IsNullOrEmpty(sql))
           {


  42. using (SqlConnection con = new SqlConnection(connectionString))

  43.        {

  44.            con.Open();

  45. using (SqlCommand cmd = con.CreateCommand())

  46.            {

  47. try{

  48.                cmd.CommandText = sql;

  49.                cmd.Parameters.AddRange(parameters);

  50. return Convert.ToInt32( cmd.ExecuteScalar());

  51. }

  52. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  53. }

  54.        }

  55. else
           {
               return -1;
           }

  56.    }

  57. /// <summary>

  58. /// 主要执行查询操做

  59. /// </summary>

  60. /// <param name="sql">执行的sql语句</param>

  61. /// <param name="parameters">参数数组</param>

  62. /// <returns></returns>

  63. publicstatic DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters)

  64.    {

  65. if (string.IsNullOrEmpty(sql))
           {


  66. using (SqlConnection con = new SqlConnection(connectionString))

  67.        {

  68.            con.Open();

  69. using (SqlCommand cmd = con.CreateCommand())

  70.            {

  71. try{

  72.                cmd.CommandText = sql;

  73.                cmd.Parameters.AddRange(parameters);

  74.                SqlDataAdapter adapter = new SqlDataAdapter(cmd);

  75.                DataTable dt = new DataTable();

  76.                adapter.Fill(dt);

  77. return dt;

  78. }

  79. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  80.            }

  81.        }

  82.    }

  83. else
           {
               return -1;
           }

  84. }

这样的类建立好之后,其余的须要访问数据库的类,就能够根据本身的须要,完成相应的增删改查的操做了。仍是用一段代码来演示吧:


  
  
  
  
  1. /// <summary>

  2. ///NewsDALL 的摘要说明

  3. /// </summary>

  4. publicclass NewsDALL

  5. {

  6. //向数据库中插入新闻

  7. publicint AddNews(NewsModel model)

  8.    {

  9. string sql = "insert into News (name,author,time,content,sort,isdelete) values(@name,@author,@time,@content,@sort,@isdelete)";

  10. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@name", model.StrNewsName), new SqlParameter("@author",model.StrNewsAuthor),new SqlParameter("@time", model.StrAddTime), new SqlParameter("@content", model.StrNewsContent), new SqlParameter("@sort", model.Sort), new SqlParameter("@isdelete", model.IsDelete1));

  11. return nResult;

  12.    }

  13. //执行数据库的删除操做

  14. publicint DeleteNew(int id)

  15.    {

  16. string sql = "delete from News where id=@id";

  17. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@id", id));

  18. return nResult;

  19.    }

  20. //执行数据库的更新操做

  21. publicint UpdateNew(NewsModel model, int nID)

  22.    {

  23. string sql = "update News set name=@name,time=@time,content=@content where id=" + nID;

  24. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@name", model.StrNewsName), new SqlParameter("@time", model.StrAddTime), new SqlParameter("@content", model.StrNewsContent));

  25. return nResult;

  26.    }

  27. //执行数据库的查询操做

  28. public NewsModel GetNewsModel(int id)//声明一次从数据库中读取新闻的条数

  29.    {

  30. string sql = "select * from News where id=@id";

  31.        DataTable dt = SqlHelper.ExecuteDataTable(sql, new SqlParameter("@id", id));

  32. if (dt.Rows.Count <= 0)

  33.        {

  34. returnnull;

  35.        }

  36. elseif (dt.Rows.Count == 1)

  37.        {

  38.            NewsModel newModel = new NewsModel();

  39.            DataRow dr = dt.Rows[0];

  40.            newModel.StrNewsName = dr["name"].ToString();

  41.            newModel.StrNewsAuthor = dr["author"].ToString();

  42.            newModel.StrAddTime = dr["time"].ToString();

  43.            newModel.StrNewsContent = dr["content"].ToString();

  44.            newModel.Sort = (int)dr["sort"];

  45. return newModel;

  46.        }

  47. else

  48.        {

  49. thrownew Exception("出现异常!");

  50.        }

  51.    }

  52. }


这里的这个NewsDALL类,主要是来完成有关新闻须要对数据库的各类操做,固然了,这只是这个类的一部分,主要是来演示NewsDALL类怎样调用SqlHelper类中的方法,来完成对数据库的操做的。

3)接下来就是最后一层,业务逻辑层了。

业务逻辑层的话主要来处理视图层和数据库访问层之间的关系的。固然了,也能够直接在视图层调用数据库访问层,可是对于关系来讲可能会增长复杂性,因此前辈们就专门的抽象出来一个业务逻辑层,把全部的业务逻辑关系都在这一层处理清楚以后再,访问数据库访问层,进行对数据的操做。(固然这是我本身的理解,若是有什么不对的话,请你们指正)

在我此次的项目中,貌似个人这一层彻底是多余的,由于不须要什么太多的业务逻辑的处理,能够彻底在视图层直接访问数据库访问层的。

仍是使用代码说话吧,固然这个仍然是NewsBLL类代码的一部分:


  
  
  
  
  1. /// <summary>

  2. ///业务逻辑层主要处理视图层和数据库访问直接的关系

  3. /// </summary>

  4. publicclass NewsBLL

  5. {

  6. //完成对数据库的添加

  7. public int AddNew(NewsModel model)

  8.    {

  9.        NewsDALL newDALL = new NewsDALL();

  10. return newDALL.AddNews(model);

  11.    }

  12. //完成对数据的删除

  13. public int DeleteNew(int i)

  14.    {

  15.        NewsDALL newDALL = new NewsDALL();

  16. return newDALL.DeleteNew(i);

  17.    }

  18. //返回一个新闻分类的对象

  19. public NewsModel GetModel(int intSort)

  20.    {

  21.        NewsModel model = new NewsModel();

  22. if (intSort == 1)

  23.        {

  24.            model.StrNewSort1 = "学院新闻";

  25.            model.StrNewSort2 = "";

  26.            model.StrNewSort3 = "";

  27.        }

  28. elseif (intSort == 2)

  29.        {

  30.            model.StrNewSort1 = "公告通知";

  31.            model.StrNewSort2 = "";

  32.            model.StrNewSort3 = "";

  33.        }

  34.        ..........

  35. return model;

  36.    }

  37. }


接下来就是在视图层来经过访问,业务逻辑层来和实体层,来玩成所须要的数据操做了。


仍是使用代码来描述吧,这个代码主要来完成对数据进行添加:


  
  
  
  
  1. publicvoid InsertData()

  2.   {

  3.       NewsModel newModel = new NewsModel();

  4.       newModel.StrNewsName = this.TextBox1.Text;

  5.       newModel.StrNewsAuthor = this.TxtBoxAuthor.Text;

  6.       newModel.StrAddTime = this.TxtDate.Text;

  7.       newModel.StrNewsContent = Server.HtmlDecode(FCKeditor1.Value);

  8.       newModel.Sort =Convert.ToInt32( this.DropDownList2.SelectedValue.ToString());

  9. //NewsBLL newBLL = new NewsBLL();

  10. int nResult= NewsBLL.AddNew(newModel);

  11. if (nResult != 0)

  12.       {

  13.           Response.Write("<script>alert('添加成功!')</script>");

  14.       }

  15. else

  16.       {

  17.           Response.Write("<script>alert('添加失败!')</script>");

  18.       }

  19.   }


据我本身的理解,三层架构能够算是一个团队项目开发的基本框架,在这个框架的基础上能够知足一些设计模式的须要。固然能够知足模块开发的须要。

总结:

对于我此次的开发项目来讲,收获仍是不少的,之前仅仅是知道有三层架构这个东西,也看书,照着别人的代码写过,可是却不能体会到这其中的真正意义。

优势:①使代码的重用更加的高了,不须要像之前作项目,每次在一个页面反复的编写操做数据库的代码,而使用三层架构的话,只须要把注意力放在业务逻辑层     的业务逻辑的处理和数据库访问层的sql语句的编写。

②代码的整洁性,和易用性更加的高了。由于不一样的操做都分别放在了不一样的层,因此代码逻辑更加清晰,若是作好注释的话,别人可以更加清楚的理解    编写者的意图。

③可扩展型更加的高了,根据须要在不一样的层编写代码,而后调用就能够了。

④很是利于团队开发。

固然了,三层架构的有点不只仅有这些,否则也不会成为如今企业开发的基本框架,这只不过是我在开发中明显的发现的优势,拿出来跟你们分享一下。

缺点:①就是性能上确定比之前直接在相应的页面编写数据库操做代码上有点下降。可是这个彻底是能够接受的,何况,对于我如今的水平就是代码质量上可定还     有待提升,有更大的优化空间。

 ②就是在个人项目中,我以为最大的浪费就是能够在视图层直接访问数据库访问层,由于要处理的业务逻辑实在是很少,因此仍是有点代码冗余吧。因此,     之后仍是要跟据本身项目的须要,来灵活的使用,不必定要按照规定必须这样作。

这仅仅是个人一点拙见,有什么地方错误,请你们积极指正。也欢迎你们跟我交流。




原创做品,容许转载,转载时请务必以超连接形式标明文章 原始出处 、做者信息和本声明。

相关文章
相关标签/搜索