3层架构 - 需要一个例子
Posted
技术标签:
【中文标题】3层架构 - 需要一个例子【英文标题】:3 Tier Architecture - In need of an example 【发布时间】:2011-01-01 23:21:08 【问题描述】:目前我正在使用单层架构。现在我想学习如何使用 3 层架构编写代码。请你给我一个简单的例子吗?
【问题讨论】:
你可以在其他问题***.com/questions/7510396/…看到我的回答 youtube.com/watch?v=4n3xzK1Cfh0 【参考方案1】:您所说的“层”是指软件堆栈中的“层”吗? “层”这个词更适合用来描述系统的物理组件。如果你使用的是 ASP.NET,你可能已经有了一个“3 tiered”系统——
-
浏览器显示网页
IIS 服务器托管您的应用程序
带有您的数据库的数据库服务器
但您可能会将所有代码放入单个软件“层”——具体来说,就是您的 aspx 页面的代码隐藏文件。您想从单层方法转变为 3 层方法。经典的“3 层”软件架构由以下部分组成——
表示层
业务逻辑层 (BLL)
数据访问层 (DAL)
(来源:asp.net)
对于典型的 ASP.NET 应用程序,您可以按如下方式应用它。首先,创建一个 LINQ2SQL 文件 (.dbml),其中包含用于数据库访问的对象。这是您的数据访问层 (DAL)。
接下来,您可能会创建一个 DLL 来包含您的 业务逻辑层 (BLL)。该层将通过 DAL 访问数据库,根据需要对其进行操作,然后通过简单的接口将其公开。例如,如果您的应用程序显示一个客户列表,您的 BLL 可能有一个名为 GetClientList() 的公共函数,它返回一个客户列表。
最后,您将设置代码隐藏文件以实例化 BLL 并将其连接到接口组件。这是您的表示层。例如,它可能会获取从 GetClientList() 函数返回的数据并将其绑定到 Web 表单上的数据网格。这个想法是让表示层尽可能薄。
这似乎有点冗长,但一旦你完成了几次,它就会非常简单。你会发现像这样分离你的应用程序会让它更容易维护,因为关注点分离会导致代码更简洁。您还会发现升级甚至替换表示层要容易得多,因为它包含的智能很少。最后,您将拥有许多非常有用的 BLL 库,您可以在新应用程序中轻松使用这些库,从而大大提高生产力。
【讨论】:
【参考方案2】: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>");
【讨论】:
【参考方案3】:三层(层)是一种客户端-服务器架构,其中用户界面、业务流程(业务规则)以及数据存储和数据访问作为独立模块开发和维护,或者通常在单独的平台上进行。
基本上有3层:
第 1 层(表示层、GUI 层) 第 2 层(业务对象、业务逻辑层) 第 3 层(数据访问层)。这些层可以单独开发和测试。将代码分成 3 层需要什么?将用户界面与业务逻辑和数据库访问分开有很多优点。部分优势如下:
业务逻辑组件的可重用性导致快速 发展。假设我们有一个模块来处理添加、更新、 在系统中删除和查找客户。由于该组件是 开发和测试,我们可以在任何其他项目中使用它 涉及维护客户。
系统的转换很容易。由于业务逻辑是 与数据访问层分离,改变数据访问层 不会对业务逻辑模块产生太大影响。假设我们是 从 SQL Server 数据存储迁移到 Oracle 不应该有任何 业务层组件和 GUI 中所需的更改 组件。
系统的变更管理很容易。假设有未成年人 业务逻辑的变化,我们不必安装整个 个人用户 PC 中的系统。例如。如果 GST (TAX) 从 10% 更改 到 15% 我们只需要更新业务逻辑组件 影响用户并且没有任何停机时间。
拥有独立的功能服务器允许并行开发 由应用专家划分的各个层级。
提供更灵活的资源分配。可以减少网络 通过让功能服务器将数据剥离到精确的流量 发送给客户之前需要的结构。
【讨论】:
【参考方案4】:这就是我在我的项目中所拥有的。不仅仅是传统的 3 层架构。
1.) Application.Infrastructure
所有业务对象的基类、业务对象集合、数据访问类以及我的自定义属性和实用程序作为扩展方法,通用验证框架。这决定了我最终的 .net 应用程序的整体行为组织。2.) Application.DataModel
数据库的类型化数据集。 TableAdapters 已扩展以包含我可能需要的事务和其他功能。3.) Application.DataAccess
数据访问类。 使用底层类型化数据集查询数据库操作的实际位置。4.) Application.DomainObjects
业务对象和业务对象集合。 枚举。5.) Application.BusinessLayer
提供可从表示层访问的管理器类。 HttpHandlers。 我自己的 Page 基类。 这里有更多内容..6.) Application.WebClient 或 Application.WindowsClient
我的表示层 从 Application.BusinessLayer 和 Application.BusinessObjects 获取引用。Application.BusinessObjects 在整个应用程序中使用,并在需要时跨越所有层 [Application.DataModel 和 Application.Infrastructure 除外]
我所有的查询都只定义了 Application.DataModel。
Application.DataAccess 作为任何数据访问操作的一部分返回或获取业务对象。业务对象是在反射属性的帮助下创建的。每个业务对象都标有到数据库中目标表的属性映射,业务对象中的属性标有与相应数据库表中目标列的属性映射。
我的验证框架允许我在指定的 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)
【讨论】:
【参考方案5】:这里有一个很好的教程,其中包含一个编写良好的分层应用程序的完整源代码控制下载:
http://nerddinnerbook.s3.amazonaws.com/Intro.htm
这不是关于分层架构的教程,但它是一个编写良好的应用程序,并让您深入了解为什么您可能会考虑这种架构。
此外,正如上面仅简要介绍的那样,这是关于保持您的逻辑/存储/表示代码分开,因此如果您必须更改其中之一(例如从 asp.net 前端更改为桌面应用程序) ,做起来并不难。
【讨论】:
【参考方案6】:***有一个很好的解释:Multitier architecture:
“三层”是一种客户端-服务器架构,其中用户界面、功能流程逻辑(“业务规则”)、计算机数据存储和数据访问作为独立的模块进行开发和维护,通常在不同的平台上进行。
Web 开发使用
在web开发领域,三层常用于指网站,一般是电子商务网站,使用三层构建:
提供静态内容和可能缓存的一些动态内容的前端 Web 服务器。 中间动态内容处理和生成级应用服务器,例如Java EE、ASP.net、php平台。 后端数据库,由数据集和数据库管理系统或 RDBMS 软件组成,用于管理和提供对数据的访问。
【讨论】:
我正在使用visual studio dot net 2005。我可以使用visual sourcesafe Mr. Rubens Farias @Surya,虽然这与您的原始问题无关(它不算作一个等级),是的,您应该使用某种源代码控制工具,例如 SourceSafe 或 TFS跨度> 最好不是 sourcesafe,更新的 scm 工具会是个好主意,特别是如果您刚刚开始。【参考方案7】:三层架构可以根据上下文有不同的含义。通常,这意味着应用程序中的职责在不同的层之间划分。通常,3 层是指:
表示层”(实际用户界面) 逻辑层(应用程序/业务逻辑) 数据层(数据库、数据存储)详细信息因应用程序而异。
像往常一样,***有一个很好的概述:http://en.wikipedia.org/wiki/Multitier_architecture
一个简单的例子是一个典型的商业应用:
演示文稿:浏览器或胖客户端 逻辑层:业务逻辑,通常在应用服务器中(基于 J2EE、ASP.NET 或其他) 数据层:数据库,通常是 RDBMS,例如 mysql 或 Oracle【讨论】:
【参考方案8】:表示层:放置与用户界面相关的所有内容。 (用户所见)
业务层:与应用程序逻辑相关的一切(来自表示层的信息如何处理)
数据层:提供底层数据源的抽象(来自/去往业务层的信息的存储位置和方式)
每一层都应该尽可能少地了解另一层,并且应该是自上而下的方法:
数据层应该对业务和表示一无所知 业务层应该知道数据而不是表示 演示文稿应该了解业务而不是数据简单示例:
网站:
Presentation:所有图形事物、用户插入数据的字段、菜单、图片等。 业务:有关数据的所有约束(唯一名称、不带符号的名称、有效日期等)、操作业务对象的方法(创建新用户、添加新订单等) 数据:访问底层数据库的方法。【讨论】:
【参考方案9】:三层架构通常包含以下组件:
-
客户端浏览器
托管 ASP.NET 应用程序的 Web 服务器
一些后端存储,例如 ASP.NET 应用程序正在访问的数据库
因此,要回答有关如何为 3 层架构编写代码的问题,您需要开发一个与数据存储进行通信的 ASP.NET 应用程序。
【讨论】:
如果您的网站前面有防火墙/负载均衡器,您甚至可以争辩说您拥有 4 层架构。 ;^) 通常不考虑物理网络设备。您可以将客户端浏览器、托管应用程序的 Web 服务器和数据库都放在同一台物理机器上,它仍然是一个 3 层架构。 您会考虑架构中的浏览器部分吗?... 为什么不: 1. Web 服务器提供静态内容或呈现模板; 2、服务器端业务逻辑和动态内容生成; 3. 数据库。 实际上,在经典模型中,拆分会有所不同。客户端浏览器和 Web 服务器都是表示层的一部分(因为 Web 服务器创建 html 和 CSS)。所以web服务器上的app其实既是业务也是表现层的一部分。但当然,你总是可以对术语提出异议...... 如果我在业务层编写连接类,如何获取用户接口层 web.config 文件中的连接字符串。以上是关于3层架构 - 需要一个例子的主要内容,如果未能解决你的问题,请参考以下文章
一个JDBC访问oracle数据库表的例子,让你搞清三层架构与MVC框架模式之间的关系,以及满足设计原则的类的结构和各类的职责