2010-01-06 120 views
12

目前我正在使用单层架构。现在我想学习如何使用3层架构编写代码。请你能给我一个简单的例子吗?3层架构 - 需要示例

+0

你可以看到我在其他问题http://stackoverflow.com/questions/7510396/business-layer-in-3-tier-architecture/7510526#7510526 – balexandre 2012-02-23 16:59:27

+0

HTTP答案:// WWW。 youtube.com/watch?v=4n3xzK1Cfh0 – 2012-11-12 18:40:45

回答

15

这就是我的项目。不仅仅是传统的三层架构。

1)Application.Infrastructure

  • 基类所有的BusinessObjects,业务内容对象集合,数据访问类和我的自定义属性和公用事业扩展方法,通用验证框架。这决定了我的最终.net应用程序的整体行为组织。

2.)Application.DataModel

  • 类型化数据集的数据库。
  • TableAdapters扩展到合并交易和我可能需要的其他功能。

3.)Application.DataAccess

  • 数据访问类。
  • 使用底层的Typed Dataset查询数据库操作的实际位置。

4)Application.DomainObjects

  • 业务对象和业务对象的集合。
  • 枚举。

5.)Application.BusinessLayer

  • 提供从表示层访问管理器类。
  • HttpHandlers。
  • 我自己的页面基类。
  • 更多的事情在这里..

6)Application.WebClientApplication.WindowsClient

  • 我的表现层
  • 从Application.BusinessLayer和应用程序需要引用。的BusinessObjects。

Application.BusinessObjects跨应用程序使用,他们在所有层行进时neeeded [除Application.DataModel和Application.Infrastructure]

我所有的查询仅定义Application.DataModel。

申请。DataAccess返回或将Business对象作为任何数据访问操作的一部分。业务对象是在反射属性的帮助下创建的。每个业务对象都标有映射到数据库中目标表的属性,业务对象内的属性标有映射到相应数据库表中的目标列的属性。

我的验证框架让我可以在指定的ValidationAttribute的帮助下验证每个字段。

我的框架大量使用属性来自动化大部分繁琐的任务,如映射和验证。我也可以将新功能作为框架中的新功能。

示例业务对象在我的应用程序中看起来像这样。

User.cs

[TableMapping("Users")] 
public class User : EntityBase 
{ 
    #region Constructor(s) 
    public AppUser() 
    { 
     BookCollection = new BookCollection(); 
    } 
    #endregion 

    #region Properties 

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute 

    private System.Int32 _UserId; 

    private System.String _FirstName; 
    private System.String _LastName; 
    private System.String _UserName; 
    private System.Boolean _IsActive; 

    [DataFieldMapping("UserID")] 
    [DataObjectFieldAttribute(true, true, false)] 
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")] 
    public override int Id 
    { 
     get 
     { 
      return _UserId; 
     } 
     set 
     { 
      _UserId = value; 
     } 
    } 

    [DataFieldMapping("UserName")] 
    [Searchable] 
    [NotNullOrEmpty(Message = "Username Is Required.")] 
    public string UserName 
    { 
     get 
     { 
      return _UserName; 
     } 
     set 
     { 
      _UserName = value; 
     } 
    } 

    [DataFieldMapping("FirstName")] 
    [Searchable] 
    public string FirstName 
    { 
     get 
     { 
      return _FirstName; 
     } 
     set 
     { 
      _FirstName = value; 
     } 
    } 

    [DataFieldMapping("LastName")] 
    [Searchable] 
    public string LastName 
    { 
     get 
     { 
      return _LastName; 
     } 
     set 
     { 
      _LastName = value; 
     } 
    } 

    [DataFieldMapping("IsActive")] 
    public bool IsActive 
    { 
     get 
     { 
      return _IsActive; 
     } 
     set 
     { 
      _IsActive = value; 
     } 
    } 

    #region One-To-Many Mappings 
    public BookCollection Books { get; set; } 

    #endregion 

    #region Derived Properties 
    public string FullName { get { return this.FirstName + " " + this.LastName; } } 

    #endregion 

    #endregion 

    public override bool Validate() 
    { 
     bool baseValid = base.Validate(); 
     bool localValid = Books.Validate(); 
     return baseValid && localValid; 
    } 
} 

BookCollection.cs

/// <summary> 
/// The BookCollection class is designed to work with lists of instances of Book. 
/// </summary> 
public class BookCollection : EntityCollectionBase<Book> 
{ 
    /// <summary> 
    /// Initializes a new instance of the BookCollection class. 
    /// </summary> 
    public BookCollection() 
    { 
    } 

    /// <summary> 
    /// Initializes a new instance of the BookCollection class. 
    /// </summary> 
    public BookCollection (IList<Book> initialList) 
     : base(initialList) 
    { 
    } 
} 
2

A 3层架构通常具有以下组件:

  1. 客户端浏览器
  2. Web服务器托管的ASP.NET应用程序是由ASP访问
  3. 一些后端存储如数据库.NET应用程序

因此,要回答有关如何编写3层体系结构代码的问题,请开发一个与数据存储库进行通信的ASP.NET应用程序即

+0

如果您的网站前有防火墙/负载平衡器,那么您甚至可以争辩说您有4层架构。 ; ^) – Toad 2010-01-06 08:39:53

+0

通常不考虑物理网络设备。您可以将客户端浏览器,托管应用程序的Web服务器和数据库全部放在同一台物理机器上,但仍然是三层架构。 – 2010-01-06 08:42:45

+1

您会考虑体系结构的浏览器部分吗?...为什么不能:1.提供静态内容或呈现模板的Web服务器; 2.服务器端业务逻辑和动态内容生成; 3.数据库。 – 2010-01-06 08:43:19

3

表示层:把与用户界面有关的所有东西都放入。 (用户看到什么)

业务层:这是关系到应用程序的逻辑一切

数据层(如何的信息,从处理过的表示层来):提供的一个抽象底层数据源(S)(在哪里,如何将信息化从到来/离去的业务层存储)

每一层都应该知道尽可能少有关其他,它应该是一个自上而下的方法:

  • 数据层竟然一无所知业务和表示
  • 业务层应该知道的数据,但没有关于介绍
  • 介绍应该知道的业务,但没有有关数据

简单的例子:

网站:

  • 介绍:所有图形的东西,我们的领域er插入数据,菜单,图片等
  • 业务:关于数据的所有约束(唯一名称,无符号名称,有效日期等),操作业务对象的方法(创建新用户,添加新订单等)
  • 数据:访问底层数据库的方法。
3

3层体系结构根据上下文可以有不同的含义。一般来说,这意味着应用程序中的职责分为不同的层次。典型地,3层是指:

  • 表示层”(实际用户界面)
  • 逻辑层(应用/业务逻辑)
  • 数据层(数据库,数据存储)

细节随应用而

维基百科,像往常一样,有一个很好的概述:http://en.wikipedia.org/wiki/Multitier_architecture

一个简单的例子是一个典型的业务应用程序:

  • 演示:浏览器,或胖客户端
  • 逻辑层:业务逻辑,通常在应用服务器(基于J2EE,ASP.NET或其他)
  • 数据层:数据库,通常是RDBMS如MySQL或Oracle
21

维基百科有一个很好的解释:Multitier architecture

'三层'是一种客户端 - 服务器架构,其中用户界面,功能处理逻辑(“业务规则”),计算机数据存储和数据访问作为独立模块开发和维护,通常在独立平台上进行。

alt text

Web开发使用

在Web开发领域,三层通常用来指网站,一般的电子商务网站,它使用的是三层建:

  • 前面的e nd提供静态内容的Web服务器,以及可能缓存的一些动态内容。
  • 一个中间动态内容处理和生成级应用服务器,例如Java EE,ASP.net,PHP平台。
  • 后端数据库,包括数据集和数据库管理系统或RDBMS软件,用于管理和提供对数据的访问。
+0

我正在使用visual studio dot net 2005.我可以使用visual sourcesafe Rubens Farias先生 – 2010-01-06 08:55:11

+0

@Surya,虽然这与您的原始问题无关(不算作层),但您应该使用SourceSafe或TFS等源代码控制工具 – 2010-01-06 09:04:48

+0

最好不要sourceafe,一个更新的scm工具将是一个好主意,特别是如果你刚刚开始。 – Paddy 2010-01-06 09:24:15

9

通过“梯队”你的意思是在你的软件堆栈“层”? “层”这个词最好用来描述系统的物理组件。如果你正在使用ASP。NET,你可能已经有一个“3分层”系统 -

  1. 浏览器显示网页
  2. IIS服务器托管你的应用程序
  3. 数据库服务器与数据库

但你可能把所有的代码都放到一个单独的软件“层”中 - 具体来说就是你的aspx页面文件的代码。你想从单层移动到3层方法。经典的 “3层” 的软件体系结构包括以下 -

  1. 表示层

  2. 业务逻辑层(BLL)

  3. 数据访问层(DAL)

alt text http://weblogs.asp.net/blogs/fredriknormen/WindowsLiveWriter/UsingWebServicesina3tierarchitecture_134F6/3tier_2.jpg

For ty ty pical ASP.NET应用程序,你可以按如下方式应用。首先,创建一个包含数据库访问对象的LINQ2SQL文件(.dbml)。这是您的数据访问层(DAL)。

接下来,您可能会创建一个DLL来包含您的业务逻辑层(BLL)。该层将通过DAL访问数据库,根据需要对其进行操作,然后通过简单的界面对其进行公开。例如,如果您的应用程序显示客户端列表,则BLL可能会有一个名为GetClientList()的公共函数,该函数返回客户端列​​表。

最后,您将在文件后面设置代码以实例化BLL并将其连接到接口组件。这是您的表示层。例如,它可能需要从GetClientList()函数返回的数据,并将其绑定到Web表单上的数据网格。这个想法是让表示层尽可能薄。

这似乎有点啰嗦描述,但是一旦你做了几次,它就非常直截了当。您会发现将这样的应用程序分离出来将使维护变得更容易,因为问题分离会导致更简洁的代码。您还会发现升级甚至替换您的表示层要容易得多,因为它包含非常小的智能。最后,您将得到一个您有许多非常有用的BLL库的地方,您可以在新应用程序中轻松使用它们,从而大大提高生产力。

0

一个很好的教程,有写得很好的分层应用程序的完整源代码控制下载会在这里:

http://nerddinnerbook.s3.amazonaws.com/Intro.htm

这不是一个关于分层体系结构的教程,但它是一个写得很好的应用,并给出一些洞察你为什么可以考虑这个架构。如上所述,这是关于保持你的逻辑/存储/表示代码分开的,所以如果你必须改变其中的一个(例如,从asp.net前端更改为桌面应用程序),这并不难。

0

三层(层)是客户端 - 服务器体系结构,其中所述用户界面,业务流程(业务规则),数据存储和数据访问作为独立模块进行开发和维护,或者通常在独立的平台上进行。

基本上,有3层:

  • 层1(表示层,GUI层)
  • 层2(业务对象,业务逻辑层)
  • 第3层(数据访问层)。这些层可以单独开发和测试。

需要将代码分成三层吗?用户界面与业务逻辑和数据库访问的分离具有许多优点。其中一些优点如下:

业务逻辑组件的可重用性导致快速开发 。假设我们有一个模块来处理添加,更新,删除和查找系统中的客户。由于这个组件是 开发和测试,我们可以在任何其他项目,可能 涉及维护客户使用它。

该系统的转换很容易。由于与数据访问层分离的业务逻辑是 ,因此更改数据访问层 不会太多地影响业务逻辑模块。假设我们是从SQL Server数据存储移动到Oracle的 ,那么在业务层组件和GUI 组件中不应该有任何 更改。

系统的变更管理非常简单。比方说,如果商业逻辑有一个小的 更改,我们不必将整个 系统安装在个人用户的PC中。例如。如果GST(TAX)从10% 更改为15%,我们只需更新业务逻辑组件,而不影响用户且不会造成任何停机时间。

拥有单独的功能服务器允许应用专家对各个层次的并行开发 。

提供更灵活的资源分配。通过使功能服务器将数据发送到客户端之前所需的精确 结构,可以减少网络流量。

0
connection class 
----------------------- 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Web .UI.WebControls ; 
/// <summary> 
/// Summary description for conn 
/// </summary> 
namespace apm_conn 
{ 
    public class conn 
    { 
     public SqlConnection getcon() 
     { 
      SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connect"].ConnectionString); 
      if (con.State == ConnectionState.Closed) 
      { 
       con.Open(); 
      } 
      return con; 
     } 
     #region execute command 
     public string Executecommand(SqlParameter []sqlparm,string sp) 
     { 
      string r_val = ""; 
      try 
      { 

       SqlConnection con = new SqlConnection(); 
       con = getcon(); 
       SqlCommand cmd = new SqlCommand(); 
       cmd.Connection = con; 
       cmd.CommandText = sp; 
       cmd.CommandType = CommandType.StoredProcedure; 
       foreach (SqlParameter loopvar_parm in sqlparm) 
       { 
        cmd.Parameters.Add(loopvar_parm); 

       } 
       cmd.Parameters.Add("@Var_Output", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output; 
       cmd.ExecuteNonQuery(); 
       r_val = (string)cmd.Parameters["@Var_Output"].Value; 
       con.Close(); 
      } 
      catch { } 
      return r_val; 

     } 

     #endregion 
     #region Execute Dataset 
     public DataSet ExeccuteDataset(SqlParameter[] sqlParm, string sp) 
    { 
     DataSet ds = new DataSet(); 
     try 
     { 
      SqlConnection con = new SqlConnection(); 
      con = getConn(); 
      SqlCommand cmd = new SqlCommand(); 
      cmd.Connection = con; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.CommandText = sp; 
      foreach (SqlParameter LoopVar_param in sqlParm) 
      { 
       cmd.Parameters.Add(LoopVar_param); 
      } 
      cmd.ExecuteNonQuery(); 
      SqlDataAdapter da = new SqlDataAdapter(cmd); 
      da.Fill(ds); 

     } 
     catch 
     { } 
     return ds; 
    } 
     #endregion 
     #region grid 
     public void Bindgrid(DataSet ds,GridView g) 
     { 
      try 
      { 
       g.DataSource = ds.Tables[0]; 
       g.DataBind(); 

      } 
      catch { } 
     } 
     #endregion 
     #region Dropdownlist 
     public void Binddropdown(DropDownList dl,DataSet ds,string text,string value) 
     { 
      try 
      { 
       dl.DataSource = ds.Tables[0]; 
       dl.DataTextField = text; 
       dl.DataValueField = value; 
       dl.DataBind(); 
      } 
      catch 
      {} 

     } 
     #endregion 
     public conn() 
     { 
      // 
      // TODO: Add constructor logic here 
      // 
     } 
    } 
} 




dal 
--------------- 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using apm_conn; 
using System.Data.SqlClient; 
using apm_ent; 

/// <summary> 
/// Summary description for Class1 
/// </summary> 
namespace apm_dal 
{ 
    public class dal 
    { 
     conn ob_conn = new conn(); 
     public dal() 
     { 
      // 
      // TODO: Add constructor logic here 
      // 
     } 
     public string insert(ent obj_ent) 
     { 
      SqlParameter[] sqlparm = 
     { 
      new SqlParameter ("@Var_Action",obj_ent.Var_Action), 
      new SqlParameter ("@Int_Id",obj_ent.Int_Id), 
      new SqlParameter ("@Var_Product",obj_ent.Var_Product), 
       new SqlParameter ("@Dc_Price",obj_ent.Var_Price), 
       new SqlParameter ("@Int_Stat",obj_ent.Int_Stat), 

           }; 
      return ob_conn.Executecommand(sqlparm, "Proc_product"); 
     } 
     public string ins(ent obj_ent) 
     { 
      SqlParameter[] parm = 
     { 
      new SqlParameter ("@Var_Action",obj_ent .Var_Action), 
      new SqlParameter ("@Int_Id",obj_ent .Int_Id), 
          }; 
      return ob_conn.Executecommand(parm, "Proc_product"); 
     } 
    } 

} 

bal 
------------- 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using apm_ent; 
using apm_dal; 

/// <summary> 
/// Summary description for bal 
/// </summary> 
namespace apm_Bal 
{ 

    public class bal 
    { 
     dal ob_dal = new dal(); 
     string r_val = ""; 
     public bal() 
     { 
      // 
      // TODO: Add constructor logic here 
      // 
     } 
     public string insert(ent obj_ent) 
     { 
      return ob_dal.insert(obj_ent); 
     } 
    } 
} 



Ent 
------------ 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

/// <summary> 
/// Summary description for ent 
/// </summary> 
namespace apm_ent 
{ 
    public class ent 
    { 
     public ent() 
     { 
      // 
      // TODO: Add constructor logic here 
      // 
     } 
     #region Ent 
     public int Int_Id { get; set; } 
     public string Var_Action { get; set; } 
     public string Var_Product { get; set; } 
     public decimal Var_Price { get; set; } 
     public int Int_Stat { get; set; } 
     #endregion 
    } 
} 



page code 
-------------- 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using apm_conn; 
using apm_ent; 
using apm_Bal; 
using apm_conn; 
public partial class _Default : System.Web.UI.Page 
{ 
    conn obj_conn = new conn(); 
    ent obj_ent = new ent(); 
    bal obj_bal = new bal(); 
    string r_val = ""; 
    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 
    protected void btnsub_Click(object sender, EventArgs e) 
    { 
     obj_ent.Var_Action = "INS"; 
     obj_ent.Var_Product = txtproduct.Text; 
     obj_ent.Var_Price = Convert.ToDecimal (txtprice.Text); 
     r_val = obj_bal.insert(obj_ent); 
     if (r_val == "1") 
     { 
      Response.Write("<script>alert('Inserted Sucessfully')</script>"); 
     } 
    } 
}