zoukankan      html  css  js  c++  java
  • 深入浅出三层架构

    这几天看了不少三层架构的资料,整理整理

    ——故写篇博文谈谈自己的看法。

    三层架构概念:

    三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合” 的思想,复杂项目不能把SQL语句直接写到程序里,不模块话,难以维护。应该采取三层架构。

    1、表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。

    2、业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。

    3、数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、查找等。
     
    简单的说,UI层调用BLL,BLL调用DAL,数据用Model进行传递,Model为各层之间架起了数据传输的桥梁。
    参考模型:UI<-->Model<-->BLL<-->Model<-->DAL

    传统的两层结构和三层架构之间的区别:

     
    下面我以一个简单的例子来细数三层架构:

    代码剖析:

    • 新建一个项目(Windows 窗体应用程序),再在根目录下新建3个文件夹,分别是Model,DAL,BLL。
    • 在Model下添加一个Person类
    • 在DAL下添加一个SQLHelper类和一个PersonDAL类。
    • 在BLL下添加PersonBLL类

    Person.cs代码如下:

     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace 三层架构Demo.Model
    {
    class Person
    {
    public int Id { get;set;}
    public int Age { get; set; }
    public string Name { get; set; }

    }
    }
     



    SQLHelper类,封装了数据库操作的方法:

    SQLHelper.cs代码入下:

     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.SqlClient;
    using System.Configuration;
    using System.Data;

    namespace 三层架构Demo.DAL
    {
    class SQLHelper
    {
    //public static readonly string connStr = System.Configuration.ConfigurationSettings.AppSettings["dbconnstr"];
    //获得连接字符串
    public static readonly string connStr =
    ConfigurationManager.ConnectionStrings["dbconnstr"].ConnectionString;

    /// <summary>
    /// 执行方法ExecuteNonQuery
    /// </summary>
    /// <param name="cmdText">要执行的sql语句</param>
    /// <param name="parameters">参数数组</param>
    /// <returns>受影响的行数</returns>
    public static int ExecuteNonQuery(string cmdText,
    params SqlParameter[] parameters)
    {
    using (SqlConnection conn=new SqlConnection (connStr))
    {
    conn.Open();
    using (SqlCommand cmd= conn.CreateCommand())
    {
    cmd.CommandText = cmdText;
    cmd.Parameters.AddRange(parameters);
    int i=cmd.ExecuteNonQuery();
    return i;
    }
    }
    }

    /// <summary>
    /// 执行ExecuteScalar() 返回第一行第一列数据
    /// </summary>
    /// <param name="cmdText">要执行的sql语句</param>
    /// <param name="parameters">参数数组</param>
    /// <returns>返回第一行第一列数据</returns>
    public static object ExecuteScalar(string cmdText,
    params SqlParameter[] parameters)
    {
    using (SqlConnection conn=new SqlConnection(connStr))
    {
    conn.Open();
    using (SqlCommand cmd=conn.CreateCommand())
    {
    cmd.CommandText = cmdText;
    cmd.Parameters.AddRange(parameters);
    return cmd.ExecuteScalar();
    }
    }
    }

    /// <summary>
    /// 执行ExecuteDataTable()方法
    /// </summary>
    /// <param name="cmdText">要执行的Sql语句</param>
    /// <param name="parameters">参数数组</param>
    /// <returns>返回一个DataTable</returns>
    public static DataTable ExecuteDataTable(string cmdText,
    params SqlParameter[] parameters)
    {
    using (SqlConnection conn=new SqlConnection (connStr))
    {
    conn.Open();
    using (SqlCommand cmd=conn.CreateCommand())
    {
    cmd.CommandText = cmdText;
    cmd.Parameters.AddRange(parameters);
    using ( SqlDataAdapter adapter=new SqlDataAdapter (cmd))
    {
    DataTable dt = new DataTable();
    adapter.Fill(dt);
    return dt;
    }
    }
    }
    }

    /// <summary>
    /// 执行ExecuteSqlDataReader()方法
    /// </summary>
    /// <param name="cmdText">要执行的Sql语句</param>
    /// <param name="parameters">参数数组</param>
    /// <returns>返回一个SqlDataReader</returns>

    public static SqlDataReader ExecuteSqlDataReader(string cmdText,
    params SqlParameter[] parameters)
    {
    using (SqlConnection conn=new SqlConnection (connStr))
    {
    conn.Open();
    using (SqlCommand cmd=conn.CreateCommand())
    {
    cmd.CommandText = cmdText;
    cmd.Parameters.AddRange(parameters);
    return cmd.ExecuteReader();
    }
    }
    }
    }
    }
     

    PersonDAL.cs代码如下:

     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using 三层架构Demo.Model;
    using System.Data.SqlClient;
    using System.Data;

    namespace 三层架构Demo.DAL
    {
    class PersonDAL
    {
    /// <summary>
    /// 返回一个新增对象的主键,设为自动增长
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public int Addnew(Person model)
    {
    string sql = "insert into T_person(Age,Name) output inserted.id values(@Age,@Name)";

    object obj=
    SQLHelper.ExecuteScalar(sql,new SqlParameter("Age",model.Age),new SqlParameter("Name",model.Name));
    //Convert : 与 value 等效的 32 位有符号整数,如果 value 为 null,则为零。
    return Convert.ToInt32(obj);
    }
    /// <summary>
    /// 删除数据
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public int Delete(int id)
    {
    string sql = "delete form T_Person where Id=@Id";
    return SQLHelper.ExecuteNonQuery(sql,new SqlParameter("Id",id));
    }
    /// <summary>
    /// 修改数据
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public int Update(Person model)
    {
    string sql = "update T_Person set Age=@Age,Name=@Name where Id=@Id";
    return SQLHelper.ExecuteNonQuery(sql,new SqlParameter("Age",model.Age),new SqlParameter("Name",model.Name),
    new SqlParameter("Id",model.Id));
    }

    /// <summary>
    /// 查询数据
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public Person Get(int id)
    {
    string sql="select * from T_Person where Id=@Id";
    DataTable dt=SQLHelper.ExecuteDataTable(sql,new SqlParameter("Id",id));
    if (dt.Rows.Count<=0)
    {
    return null;
    }
    else if (dt.Rows.Count==1)
    {
    Person model1 = new Person();
    model1.Id = Convert.ToInt32(dt.Rows[0]["Id"]);
    model1.Name = Convert.ToString(dt.Rows[0]["Name"]);
    model1.Age = Convert.ToInt32(dt.Rows[0]["Age"]);
    return model1;
    }
    else//以防意外情况
    {
    throw new Exception("数据库中有两条及以上重复数据");
    }
    }
    /// <summary>
    /// 获取全部数据
    /// </summary>
    /// <returns></returns>
    public IEnumerable<Person> GetAll()
    {
    string sql = "select * from T_Person";
    DataTable dt = SQLHelper.ExecuteDataTable(sql);
    List<Person> list = new List<Person>();
    foreach (DataRow row in dt.Rows)
    {
    Person model = new Person();
    model.Id = Convert.ToInt32(row["Id"]);
    model.Name =Convert.ToString(row["Name"]);
    model.Age = Convert.ToInt32(row["Age"]);
    list.Add(model);
    }
    return list;
    }
    }
    }
     

    进行逻辑判断的BLL层代码看似是这样的:

    PersonBLL.cs代码如下:

     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using 三层架构Demo.Model;
    using 三层架构Demo.DAL;
    using System.Data.SqlClient;
    using System.Data;

    namespace 三层架构Demo.BLL
    {
    class PersonBLL
    {
    public int Addnew(Person model)
    {
    return new PersonDAL().Addnew(model);
    }

    public int Delete(int id)
    {
    return new PersonDAL().Delete(id);
    }

    public int Update(Person model)
    {
    return new PersonDAL().Update(model);
    }

    public Person Get(int id)
    {
    return new PersonDAL().Get(id);
    }

    public IEnumerable<Person> GetAll()
    {
    return new PersonDAL().GetAll();
    }


    }
    }
     

    UI层进行测试:

    Form1.cs代码如下:

     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using 三层架构Demo.Model;
    using 三层架构Demo.DAL;
    using 三层架构Demo.BLL;

    namespace 三层架构Demo
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    //Person p1 = new Person();
    //p1.Age = 22;
    //p1.Name = "Eyes";
    //int id=new PersonDAL().Addnew(p1);
    //MessageBox.Show(id.ToString());

    //PersonDAL p = new PersonDAL();
    //Person a = p.Get(1);
    //a.Name = "jack";
    //MessageBox.Show(a.Name + "," + a.Age);
    //p.Update(a);


    //PersonBLL bll = new PersonBLL();
    //Person p = bll.Get(1);
    //p.Name = "Admin";
    //MessageBox.Show(p.Name + "," + p.Age);
    //bll.Update(p);

    PersonBLL b = new PersonBLL();
    List<Person> list = (List<Person>)b.GetAll();
    foreach (Person item in list)
    {
    MessageBox.Show(item.Id+","+item.Name+","+item.Age);
    }

    }

    private void Form1_Load(object sender, EventArgs e)
    {
    dataGridView1.DataSource = new PersonBLL().GetAll();
    }
    }
    }
     

    总结:

     

    优点

      1、开发人员可以只关注整个结构中的其中某一层;

      2、可以很容易的用新的实现来替换原有层次的实现;

      3、可以降低层与层之间的依赖;

      4、有利于标准化;

      5、利于各层逻辑的复用。

    缺点

      1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

      2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

      3、增加了开发成本。

  • 相关阅读:
    获取其他线程的数据用 queue, 多进程Q
    self: 限制并发量asyncio
    asyncio 中给running 的loop 动态添加 Future Task
    雾里看花之 Python Asyncio
    python协程之动态添加任务
    异步IO( asyncio) 协程
    加快phpstorm、rubymine、pycharm系列IDE运行速度的方法
    scrapy 'fcntl' has no attribute 'F_GETFD
    sitemap index
    Django模板系统 运算
  • 原文地址:https://www.cnblogs.com/shixunle/p/3340902.html
Copyright © 2011-2022 走看看