三层架构学习

1.三层之间的关系:
三层是指:界面显示层(UI),业务逻辑层(Business),数据操作层(Data Access)
文字描述
Clients对UI进行操作,UI调用Business进行相应的运算和处理,Business通过Data Access对Data Base进行操作。
优点
l          增加了代码的重用。Data Access可在多个项目中公用;Business可在同一项目的不同地方使用(如某个软件B/S和C/S部分可以共用一系列的Business组件)。
l          使得软件的分层更加明晰,便于开发和维护。美工人员可以很方便地设计UI设计,并在其中调用Business给出的接口,而程序开发人员则可以专注的进行代码的编写和功能的实现。
2.Data Access 的具体实现:
DataAgent类型中变量和方法的说明:
private string m_strConnectionString; //连接字符串
private OleDbConnection m_objConnection; //数据库连接
public DataAgent(string strConnection) //构造方法,传入的参数为连接字符串
private void OpenDataBase() //打开数据库连接
private void #region CloseDataBase() //关闭数据库连接
public DataView GetDataView(string strSqlStat) //根据传入的连接字符串返回DataView
具体实现代码如下:
public class DataAgent
{
    private string m_strConnectionString;
   private OleDbConnection m_objConnection;
    #region DataAgend
    ///<summary>
    /// Initial Function
    ///</summary>
    ///<param name="strConnection"></param>
    public DataAgent(string strConnection)
    {
        this.m_strConnectionString = strConnection;
    }
    #endregion
    #region OpenDataBase
    ///<summary>
    /// Open Database
    ///</summary>
    private void OpenDataBase()
    {
        try
        {
            this.m_objConnection = new OleDbConnection();
            this.m_objConnection.ConnectionString = this.m_strConnectionString;
            if (this.m_objConnection.State != ConnectionState.Open)
            {
                this.m_objConnection.Open();
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }
    #endregion
    #region CloseDataBase
    ///<summary>
    /// Close Database
    ///</summary>
    private void CloseDataBase()
    {
        if (this.m_objConnection != null)
        {
            if (this.m_objConnection.State == ConnectionState.Open)
            {
                this.m_objConnection.Close();
            }
        }
    }
    #endregion
    #region GetDataView
    ///<summary>
    /// Execute the sql and return the default table view
    ///</summary>
    ///<param name="strSelectString">Select String</param>
    ///<returns>DataView of the DataTable</returns>
    public DataView GetDataView(string strSqlStat)
    {
        try
        {
            this.OpenDataBase();
            OleDbDataAdapter objDataAdapter = new OleDbDataAdapter(strSqlStat.Trim(), this.m_objConnection);
            DataSet objDataSet = new DataSet();
            objDataAdapter.Fill(objDataSet);
            return objDataSet.Tables[0].DefaultView;
        }
        catch (Exception e)
        {
            throw e;
        }
        finally
        {
            this.CloseDataBase();
        }
    }
    #endregion
}
3.Business 的具体实现:
建立名为Base的类,此类作为其他事务类的基类,其中定义了一个DataAgent的实例。其他所有的Business类都从该改类派生。
在该类中添加对DataAgent的引用,使所有的事务类都能使用DataAgent中的方法。
Base.cs源代码:
public abstract class Base
{
    protected DataAgent OleDBAgent = new DataAgent("Provider=SQLOLEDB;Data Source=(local);DataBase=test;User ID=sa;PWD=");
}
准备好了数据操作层和事务层的基类,底下就可以正式地开始业务逻辑类的开发了,如有一个显示新闻的类News,其中包含了一个GetNewsList()的方法,该方法用来获取所有的新闻标题列表,代码如下:
public class News : Base
{
    public DataView GetNewsList()
    {
        string strSql;
        strSql = "";
         strSql += " SELECT Top 10 NewsId,NewsTitle ";
        strSql += " FROM Tb_News";
        strSql += " WHERE NewsEnable = 1";
        strSql += " ORDER BY NewsId ";
        return OleDBAgent.GetDataView(strSql);
    }
}
由于数据库结构比较简单,在此就不再给出详细的表结构。
4.UI 层对Business 中接口的调用
首先,在窗体Form1中添加对News类的引用。
然后,在窗体Form1中添加一个(DataGridView)dgNews用来显示新闻列表。
在窗体的 Form1_Load方法中添加如下代码:
private void Form1_Load(object sender, EventArgs e)
{
    News objNews = new News();
    this.dgNews.DataSource = objNews.GetNewsList();
}

posted on 2008-01-09 10:18 3stones 阅读(1695) 评论(7)  编辑 收藏 网摘

评论

#1楼 [楼主] 2008-01-09 10:19 3stones      

其实不用多说,大家都知道网络上软件系统大致可以分为B/S和C/S结构的。对于C/S结构小可认识不足,只是就个人接触,谈谈项目中实际用到的C/S系统架构。

一般的小型系统:使用的C/S系统,个人觉得谈不上什么架构方面的问题。只是简单的读取数据库,显示到前台而已。一般也就分为两层:服务器端、客户端,所实现的也是胖客户端。服务器上也就是run个数据库。

而当系统规模够大,不谈架构我想就不可能了。个人接触B/S方面的架构也算有一些小小见识,因此觉得其实大型C/S架构也多少在参考着B/S方面的架构,而万变不离“祖宗”的道理。

一个大型C/S架构我想大致可以划分为:实体层/业务逻辑层/用户控件层/前台界面层。

下面逐一分析一下一各个层之间的作用:

实体层(ENTITY):用于直接与数据库进行交流,其中这些一般会用到代码生成器。直接将数据库中的表名、字段映射到实体层。实体层作用,一般用到批量增、修时候用实体会比较好,因为不用将数据直接与数据库打交道。而当只是一个简单的sql select的时候,我想还是避开实体层的好,要不会得到相反的结果。

业务逻辑层(LOGICAL CONTROL):如果真正到了仔细考虑架构方面问题的时候,我想此软件系统的业务逻辑也应该不会轻松。必定会让设计人员和开发人员头疼。最好的办法就是把业务逻辑层单拉出来。作为承接作用,定义好接口,供外界调用。我想这和B/S结构的j2ee里的struts的action非常相似。

用户控件层(USER CONTROL):这一层主要是用来减少开发量,把多处用到的控件抽象出来。以供重复使用。例如把datagrid包装成自己系统需要的,并加一些其他如combo、button等控件,以供开发人员拖拽,大大减少开发量。当然这一部需要在前期工作时候,把设计工作完成好。需要哪一部分抽象出来,可以被多开发用户批量使用的,一定事先弄清楚。

前台界面层(USER FACADE):这一层就不多说了,相信大家都可以理解,就是form。

最后说一点:把层次之间的依赖关系限定好,如entity不可以调用业务逻辑层…………,以此类推。

热烈欢迎各位拍砖!有说的不恰当地方请指教!谢谢。接下来会写一些B/S方面架构,以及data warehouse的ETL 方面的文章!

  回复  引用  查看    

#2楼 202.158.178.* 2008-04-11 13:59 tellov [未注册用户]

楼主在误人子弟,逻辑层应该包含业务逻辑,而不包含任何SQL代码,SQL代码的完成部分全由数据层完成.建议楼主去多看看microsoft的实例,或者进一个大公司学习一下   回复  引用    

#3楼 202.158.178.* 2008-04-11 14:02 tellov [未注册用户]

三层的好处在于扩展和迁移方便,你这个三层根本没有体现出任何一点实用价值!我问你,如果你现在用的是MS SQL,现在老板要你换MY SQL了,你怎么办?业务逻辑层重写??一般情况下是把数据层反射过去,那么有一天要换数据库或者其他方面,只需要改动一点点代码而已.   回复  引用    

#4楼 121.16.96.* 2008-05-10 09:13 ybober [未注册用户]

用SQL Client 能否替代OLEDB实现三层架构?如何实现?@tellov
  回复  引用    

#5楼 125.34.20.* 2008-08-07 10:12 hellomoto [未注册用户]

你理解的是狭义的C/S三层结构   回复  引用    

#6楼 125.78.106.* 2008-08-26 14:49 啊啊 [未注册用户]

物理三层增么弄?   回复  引用    

#7楼 116.24.113.* 2008-10-04 16:34 康哥 [未注册用户]

三层是活的不是死的,难道你今天用ACCESS,明天用MSSQL,后天用ORACLE?你实现真正的三层,你还不是要重写SQL语句吗?所以最好的方法的是把SQL封装到包里面!
  回复  引用    

0
0
(请您对文章做出评价)
 
 
.net 三成架构之三(代码实例)(自编,自导,自演)
2009-11-19 11:34

如果是是学习的介意别直接“复制”“粘贴”,代码看懂了跟会写完全是两码事(貌似我也是菜鸟,挖哈哈)

1.Model数据模型下的admin.cs类中的代码:

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

namespace Model
{
    public class admin
    {
        private int _id;
        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _adminname;
        public string Adminname
        {
            get { return _adminname; }
            set { _adminname = value; }
        }

        private int _adminpwd;
        public int Adminpwd
        {
            get { return _adminpwd; }
            set { _adminpwd = value; }
        }
    }
}

2.DAL层下的admin.cs类中的代码:

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

using Model;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace DAL
{
    public class admin
    {
        SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["add_usersConn"].ConnectionString);

        public DataSet GetAllRow()
        {
            string str = "select id,adminname,adminpwd from admin";
            SqlDataAdapter da = new SqlDataAdapter(str,sqlcon);
            DataSet ds = new DataSet();
            da.Fill(ds);

            return ds;
        }

        public bool update(Model.admin model)
        {
            string str = "update admin set adminname = @adminname,adminpwd = @adminpwd where id = @id";
            sqlcon.Open();
            SqlCommand com = new SqlCommand(str,sqlcon);
            com.Parameters.AddWithValue("@adminname", model.Adminname);
            com.Parameters.AddWithValue("@adminpwd", model.Adminpwd);
            com.Parameters.AddWithValue("@id", model.Id);
            int flag = com.ExecuteNonQuery();
            sqlcon.Close();
            if (flag > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool del(Model.admin model)
        {
            string str = "delete from admin where
id=@id";
            sqlcon.Open();
            SqlCommand com = new SqlCommand(str,sqlcon);
            com.Parameters.AddWithValue("@id",model.Id);
            int flag = com.ExecuteNonQuery();
            sqlcon.Close();
            if (flag > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool insert(Model.admin model)
        {
            string str = "insert into admin(adminname,adminpwd) values(@adminname,@adminpwd)";
            sqlcon.Open();
            SqlCommand com = new SqlCommand(str,sqlcon);
            com.Parameters.AddWithValue("@adminname",model.Adminname);
            com.Parameters.AddWithValue("@adminpwd",model.Adminpwd);
            int flag = com.ExecuteNonQuery();
            sqlcon.Close();
            if (flag > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

3.BLL层中admin.cs

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

using Model;
using DAL;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace BLL
{
    public class admin
    {
        Model.admin model = new Model.admin();
        DAL.admin dal = new DAL.admin();

        public DataSet GetAllRow()
        {
            return dal.GetAllRow();
        }

        public bool update(Model.admin model)
        {
            return dal.update(model);
        }

        public bool del(Model.admin model)
        {
            return dal.del(model);
        }

        public bool insert(Model.admin model)
        {
            return dal.insert(model);
        }
    }
}

4.UI层,即Web层下的后代文件Default.aspx.cs代码(赠送一个DataList分页,挖哈哈):

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Model;
using BLL;

public partial class _Default : System.Web.UI.Page
{
    Model.admin model = new Model.admin();
    BLL.admin bll = new BLL.admin();

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            bind();
            page_bind();
        }
    }
    public void bind()
    {
        DataSet ds = bll.GetAllRow();
        GridView1.DataSource = ds.Tables[0].DefaultView;
        GridView1.DataKeyNames = new string[] { "id" };
        GridView1.DataBind();
    }
    protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
    {
        GridView1.EditIndex = e.NewEditIndex;
        bind();
    }
    protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        GridView1.EditIndex = -1;
        bind();
    }
    protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text.ToString();
        string pwd = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text.ToString();
        string id = GridView1.DataKeys[e.RowIndex].Value.ToString();
        model.Id = Convert.ToInt32(id);
        model.Adminpwd = Convert.ToInt32(pwd);
        model.Adminname = name;

        bool flag = bll.update(model);
        if (flag == true)
        {
            Response.Write("<script>alert('修改成功!');</script>");
            GridView1.EditIndex = -1;
            bind();
        }
        else
        {
            Response.Write("<script>alert('修改失败!');</script>");
            bind();
        }
    }
    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        int id = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value.ToString());
        model.Id = id;

        bool flag = bll.del(model);
        if (flag == true)
        {
            Response.Write("<script>alert('删除成功!');</script>");
            bind();
        }
        else
        {
            Response.Write("<script>alert(删除失败!');</script>");
            bind();
        }
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        model.Adminname = Txtname.Text.ToString();
        model.Adminpwd = Convert.ToInt32(Txtpwd.Text.ToString());

        bool flag = bll.insert(model);
        if (flag == true)
        {
            Response.Write("<script>alert('添加成功!');</script>");
            bind();
        }
        else
        {
            Response.Write("<script>alert('添加失败!');</script>");
            bind();
        }
    }

    public void page_bind()
    {
        int curpage = Convert.ToInt32(Lbcurpage.Text.ToString());
        PagedDataSource ps = new PagedDataSource();
        DataSet ds = bll.GetAllRow();
        ps.DataSource = ds.Tables[0].DefaultView;
        ps.AllowPaging=true;
        ps.PageSize = 5;
        ps.CurrentPageIndex = curpage - 1;
        Lbpagecount.Text = ps.PageCount.ToString();

        LinkBtnFirst.Enabled = true;
        LinkBtnPrev.Enabled = true;
        LinkBtnNext.Enabled = true;
        LinkBtnLast.Enabled = true;

        if (curpage == 1)
        {
            LinkBtnFirst.Enabled = false;
            LinkBtnPrev.Enabled = false;
        }

        if (curpage == ps.PageCount)
        {
            LinkBtnNext.Enabled = false;
            LinkBtnLast.Enabled = false;
        }

        DataList1.DataSource = ps;
        DataList1.DataKeyField = "id";
        DataList1.DataBind();
    }
    protected void LinkBtnFirst_Click(object sender, EventArgs e)
    {
        Lbcurpage.Text = "1";
        page_bind();
    }
    protected void LinkBtnPrev_Click(object sender, EventArgs e)
    {
        Lbcurpage.Text = Convert.ToString(Convert.ToInt32(Lbcurpage.Text)-1);
        page_bind();
    }
    protected void LinkBtnNext_Click(object sender, EventArgs e)
    {
        Lbcurpage.Text = Convert.ToString(Convert.ToInt32(Lbcurpage.Text) + 1);
        page_bind();
    }
    protected void LinkBtnLast_Click(object sender, EventArgs e)
    {
        Lbcurpage.Text = Lbpagecount.Text;
        page_bind();
    }
}

5.UI层,即Web层下的前台文件Default.aspx代码(赠送一个DataList分页,挖哈哈):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>无标题页</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="GridView1" runat="server" BackColor="White" BorderColor="#CCCCCC"
                BorderStyle="None" BorderWidth="1px" CellPadding="3" AutoGenerateColumns="False"
                OnRowCancelingEdit="GridView1_RowCancelingEdit" OnRowDeleting="GridView1_RowDeleting"
                OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating">
                <RowStyle ForeColor="#000066" />
                <FooterStyle BackColor="White" ForeColor="#000066" />
                <PagerStyle BackColor="White" ForeColor="#000066" HorizontalAlign="Left" />
                <SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
                <HeaderStyle BackColor="#006699" Font-Bold="True" ForeColor="White" />
                <Columns>
                    <asp:BoundField DataField="id" HeaderText="ID" />
                    <asp:BoundField DataField="adminname" HeaderText="用户名" />
                    <asp:BoundField DataField="adminpwd" HeaderText="密码" />
                    <asp:CommandField HeaderText="更新" ShowEditButton="True" />
                    <asp:CommandField HeaderText="删除" ShowDeleteButton="True" />
                </Columns>
            </asp:GridView>
            &nbsp; 用户名:<asp:TextBox ID="Txtname" runat="server"></asp:TextBox><br />
            密码:<asp:TextBox ID="Txtpwd" runat="server"></asp:TextBox><br />
            <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="添加" /><br />
            <asp:DataList ID="DataList1" runat="server" BackColor="White" BorderColor="#3366CC"
                BorderStyle="None" BorderWidth="1px" CellPadding="4" GridLines="Both">
                <FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
                <ItemStyle BackColor="White" ForeColor="#003399" />
                <SelectedItemStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
                <HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" />
                <ItemTemplate>
                    <table style="width: 221px">
                        <tr>
                            <td style="height: 21px" align="left">
                                用户名:
                            </td>
                            <td style="height: 21px">
                            <%# Eval("adminname") %>
                            </td>
                            <td style="height: 21px" align="left">
                                密码:
                            </td>
                            <td style="height: 21px">
                            <%# Eval("adminpwd") %>
                            </td>
                        </tr>
                    </table>
                </ItemTemplate>
                <FooterTemplate>
                </FooterTemplate>
            </asp:DataList><br />
            总<asp:Label ID="Lbpagecount" runat="server" Text="Label"></asp:Label>页,当前第<asp:Label ID="Lbcurpage" runat="server"
                    Text="1"></asp:Label>页
            <asp:LinkButton ID="LinkBtnFirst" runat="server" OnClick="LinkBtnFirst_Click">首页</asp:LinkButton>
            <asp:LinkButton ID="LinkBtnPrev" runat="server" OnClick="LinkBtnPrev_Click">上一页</asp:LinkButton>
            <asp:LinkButton ID="LinkBtnNext" runat="server" OnClick="LinkBtnNext_Click">下一页</asp:LinkButton>
            <asp:LinkButton ID="LinkBtnLast" runat="server" OnClick="LinkBtnLast_Click">末页</asp:LinkButton>
        </div>
    </form>
</body>
</html>

6.额,别忘了在配置文件web.config中添加一个名为add_usersConn的数据库链接

例如:

    <connectionStrings>
        <add name="add_usersConn" connectionString="Data Source=PC-200906201516;Initial Catalog=add_users;Integrated Security=True"
            providerName="System.Data.SqlClient" />
    </connectionStrings>

 

附录:

数据库名:add_users

表名:admin

字段名          |      数据类型

id                  |      int

adminname   |     nvarchar(50)

adminpwd      |     int

你可能感兴趣的:(架构)