asp.net - net - microsoft application architecture guide español
3 Tier Arquitectura-En la necesidad de un ejemplo (9)
Esto es lo que tengo en mi proyecto. Más que solo una arquitectura tradicional de 3 niveles.
1.) Aplicación.Infraestructura
- Clases base para todos los objetos busines, colección de objetos busines, clases de acceso a datos y mis atributos y utilidades personalizadas como métodos de extensión, marco de validación genérico. Esto determina la organización del comportamiento general de mi aplicación .net final.
2.) Application.DataModel
- Typed Dataset para la base de datos.
- TableAdapters se extendió para incorporar Transacciones y otras características que pueda necesitar.
3.) Application.DataAccess
- Clases de acceso a datos
- Lugar real donde se consultan las acciones de la Base de datos utilizando el Dataset tipificado subyacente.
4.) Application.DomainObjects
- Objetos comerciales y colecciones de objetos comerciales.
- Enums.
5.) Aplicación . BusinessLayer
- Proporciona clases de administrador accesibles desde la capa de presentación.
- HttpHandlers.
- Mi propia clase base de página.
- Más cosas van aquí ..
6.) Application.WebClient o Application.WindowsClient
- Mi capa de presentación
- Toma referencias de Application.BusinessLayer y Application.BusinessObjects.
Application.BusinessObjects se utilizan en toda la aplicación y viajan a través de todas las capas siempre que sea necesario [excepto Application.DataModel y Application.Infrastructure]
Todas mis consultas están definidas solo Application.DataModel.
Application.DataAccess devuelve o toma Business Objects como parte de cualquier operación de acceso a datos. Los objetos comerciales se crean con la ayuda de atributos de reflexión. Cada objeto comercial se marca con un mapeo de atributos a la tabla de destino en la base de datos y las propiedades dentro del objeto comercial se marcan con asignación de atributos a columna de destino en la tabla de base de datos respectiva.
Mi marco de validación me permite validar cada campo con la ayuda de ValidationAttribute designado.
Mi trabajo de framr utiliza mucho Atributos para automatizar la mayoría de las tediosas tareas como el mapeo y la validación. También puedo nueva característica como nuevo aspecto en el marco.
Un objeto comercial de muestra se vería así en mi aplicación.
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)
{
}
}
Actualmente estoy trabajando con una arquitectura de nivel único. Ahora quiero aprender a escribir código usando la arquitectura de 3 niveles. ¿Puedes darme un ejemplo simple?
La arquitectura de 3 niveles puede tener diferentes significados dependiendo del contexto. En general, significa que las responsabilidades en la aplicación se dividen entre diferentes niveles. Por lo general, 3 niveles se refiere a:
- nivel de presentación "(interfaz de usuario real)
- nivel lógico (aplicación / lógica comercial)
- nivel de datos (base de datos, almacenamiento de datos)
Los detalles varían según la aplicación.
Wikipedia, como de costumbre, tiene una buena descripción general: http://en.wikipedia.org/wiki/Multitier_architecture
Un ejemplo simple sería una aplicación comercial típica:
- presentación: navegador o cliente gordo
- nivel lógico: lógica de negocios, generalmente en un servidor de aplicaciones (basado en J2EE, ASP.NET o lo que sea)
- nivel de datos: una base de datos, típicamente un RDBMS como MySQL u Oracle
Por "nivel" ¿te refieres a una "capa" en tu pila de software? La palabra "nivel" se usa mejor para describir los componentes físicos de su sistema. Si está utilizando ASP.NET, probablemente ya tenga un sistema de "3 niveles":
- Navegador mostrando páginas web
- Servidor IIS que aloja tu aplicación
- Servidor de base de datos con su base
Pero posiblemente esté poniendo todo su código en una sola "capa" de software, específicamente, el código detrás del archivo de sus páginas aspx. Desea pasar de una capa única a un enfoque de 3 capas. La clásica arquitectura de software de "3 capas" consiste en lo siguiente:
Capa de presentación
Capa lógica empresarial (BLL)
Capa de acceso a datos (DAL)
Para una aplicación ASP.NET típica, puede aplicar esto de la siguiente manera. Primero, crea un archivo LINQ2SQL (.dbml) que contiene los objetos para su acceso a la base de datos. Esta es su capa de acceso a datos (DAL).
A continuación, puede crear una DLL para contener su Business Logic Layer (BLL). Esta capa accederá a la base de datos a través del DAL, la manipulará según sea necesario y luego la expondrá a través de una interfaz simple. Por ejemplo, si su aplicación muestra una lista de clientes, su BLL podría tener una función pública llamada GetClientList () que devolvió una lista de clientes.
Finalmente, configuraría su código detrás de los archivos para instanciar el BLL y conectarlo a los componentes de la interfaz. Esta es su capa de presentación . Por ejemplo, podría tomar los datos devueltos por su función GetClientList () y vincularlos a una cuadrícula de datos en el formulario web. La idea es tener la capa de presentación lo más delgada posible.
Esto parece un poco largo de describir, pero es bastante simple una vez que lo has hecho un par de veces. Descubrirá que separar su aplicación de este modo facilitará su mantenimiento, ya que la separación de las preocupaciones lleva a un código más limpio. También le resultará mucho más fácil actualizar o incluso reemplazar su capa de presentación, ya que contiene muy poca inteligencia. Finalmente, llegará a un punto en el que tendrá varias bibliotecas BLL muy útiles que podrá consumir fácilmente en nuevas aplicaciones, lo que mejorará enormemente la productividad.
Un buen tutorial, con descarga completa de control de código fuente de una aplicación por niveles bien escrita, estaría aquí:
http://nerddinnerbook.s3.amazonaws.com/Intro.htm
Este no es un tutorial sobre arquitectura por niveles, pero es una aplicación bien escrita y brinda una idea de por qué podría considerar esta arquitectura.
Además, como se ha mencionado brevemente anteriormente, se trata de mantener separado el código de lógica / almacenamiento / presentación, por lo que si tiene que cambiar uno de ellos (por ejemplo, cambiar de la interfaz de asp.net a una aplicación de escritorio), no es tan difícil de hacer
Una arquitectura de 3 niveles generalmente tiene los siguientes componentes:
- Navegador del cliente
- Servidor web que aloja la aplicación ASP.NET
- Algún almacenamiento de back-end como la base de datos a la que accede la aplicación ASP.NET
Entonces, para responder a su pregunta sobre cómo escribir código para una arquitectura de 3 niveles, desarrolla una aplicación ASP.NET que se comunica con un almacenamiento de datos.
Capa de presentación : poner todo lo que está relacionado con la interfaz de usuario. (Lo que el usuario ve)
Business layer : todo lo relacionado con la lógica de la aplicación (cómo se trata la información proveniente de la capa de presentación)
Capa de datos : proporciona una abstracción de la (s) fuente (s) de datos subyacentes (dónde y cómo se almacena la información proveniente de / en la capa de negocios)
Cada capa debe saber lo menos posible sobre la otra y debe ser un enfoque de arriba hacia abajo:
- la capa de datos no debe saber nada sobre negocios y presentación
- la capa empresarial debe conocer los datos pero no sobre la presentación
- la presentación debe saber sobre negocios pero no sobre datos
Ejemplo simple:
Sitio web:
- Presentación: todas las cosas gráficas, campos donde el usuario inserta datos, menús, imágenes, etc.
- Negocio: todas las restricciones sobre los datos (nombre único, nombre sin símbolos, fecha válida, etc.), métodos para manipular objetos comerciales (crear nuevo usuario, agregar nuevo orden, etc.)
- Datos: métodos que acceden a la base de datos subyacente.
Three-tier (layer) es una arquitectura cliente-servidor en la que la interfaz de usuario, el proceso de negocio (reglas de negocio) y el almacenamiento de datos y el acceso a datos se desarrollan y mantienen como módulos independientes o, con mayor frecuencia, en plataformas separadas.
Básicamente, hay 3 capas:
- nivel 1 (nivel de presentación, nivel GUI)
- nivel 2 (objetos comerciales, nivel de lógica de negocios)
- nivel 3 (nivel de acceso a datos). Estos niveles se pueden desarrollar y probar por separado.
¿Cuál es la necesidad de dividir el código en 3 niveles? La separación de la interfaz de usuario de la lógica comercial y el acceso a la base de datos tiene muchas ventajas. Algunas de las ventajas son las siguientes:
La reutilización del componente de lógica de negocios resulta en un desarrollo rápido. Digamos que tenemos un módulo que maneja la adición, actualización, eliminación y búsqueda de clientes en el sistema. A medida que este componente se desarrolla y prueba, podemos usarlo en cualquier otro proyecto que implique mantener clientes.
La transformación del sistema es fácil. Dado que la lógica comercial es independiente de la capa de acceso a datos, cambiar la capa de acceso a datos no afectará mucho al módulo de lógica de negocios. Digamos que si nos movemos del almacenamiento de datos de SQL Server a Oracle, no debería haber ningún cambio requerido en el componente de la capa de negocios y en el componente de la GUI.
La gestión del cambio del sistema es fácil. Digamos que si hay un cambio menor en la lógica de negocios, no tenemos que instalar todo el sistema en las computadoras de los usuarios individuales. Por ejemplo, si se cambia GST (TAX) de 10% a 15%, solo debemos actualizar el componente de lógica de negocios sin afectar a los usuarios y sin tiempo de inactividad.
Tener servidores de funcionalidad separados permite el desarrollo paralelo de niveles individuales por parte de los especialistas en aplicaciones.
Proporciona una asignación de recursos más flexible. Puede reducir el tráfico de red haciendo que los servidores de funcionalidad desformen los datos a la estructura precisa necesaria antes de enviarlos a los clientes.
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>");
}
}
}
Wikipedia tiene una buena explicación: arquitectura Multitier :
''Tres niveles'' es una arquitectura cliente-servidor en la cual la interfaz de usuario, la lógica de proceso funcional ("reglas comerciales"), el almacenamiento de datos informáticos y el acceso a datos se desarrollan y mantienen como módulos independientes, la mayoría de las veces en plataformas separadas.
Uso de desarrollo web
En el campo de desarrollo web, el nivel tres se usa a menudo para referirse a sitios web, comúnmente sitios web de comercio electrónico, que se crean utilizando tres niveles:
- Un servidor web front-end que sirve contenido estático y, potencialmente, algo de contenido dinámico en caché.
- Un servidor de aplicaciones de nivel medio de procesamiento de contenido dinámico y generación, por ejemplo Java EE, ASP.net, plataforma PHP.
- Una base de datos back-end, que comprende tanto conjuntos de datos como el sistema de gestión de bases de datos o el software RDBMS que gestiona y proporciona acceso a los datos.