Creación de una Aplicación Multicapas con ASPNET 2005

Slides:



Advertisements
Presentaciones similares
Support.ebsco.com Administrador de Colección Adquisición Guiada por el Cliente Tutorial.
Advertisements

INSTRUCTOR: LI Ramiro Robles Villanueva
Programación orientada a objetos en Visual Basic .NET
ALMACENAMIENTO Y OBTENCIÓN DE DATOS CON ADO.NET. ACCEDER A DATOS CON ADO.NET Tres niveles: Tres niveles: El almacenamiento físico de datos. Puede ser.
Support.ebsco.com Como crear una Colección Local Tutorial.
Mejoras del.NET Framework 2.0 Haaron González, MCP, MVP, MCAD PlexIT Consulting
Red Social: “Un millón de Amigos”.
integridad referencial
Se necesita un PA que muestre la información de todos los clientes registrados de la siguiente forma: Nombre1 Nombre2, Apellido1 Apellido2 bajo el título.
BASE DE DATOS OBJETO RELACIONAL
Introducción a Windows Forms
Implementación de funciones definidas por el usuario
Manejo de errores y excepciones
Creación de controles de usuario
Configurar, optimizar e implementar una aplicación Web Microsoft ASP
Agregar código a un formulario Web Form con Microsoft ASP.NET
Acceso a datos con ADO.NET
Desarrollo de una Aplicación Web sobre tecnología Microsoft .NET
Modelando aplicaciones
COLEGIO DE BACHILLERES PLANTEL 13 XOCHIMILCO-TEPEPAN MATERIA:TIC EQUIPO:23 PRESENTACION: BASE DE DATOS ALUMNAS: Velazquez Corona Elsa Ponciano Antonio.
Desarrollo de Aplicaciones para Internet
Presentación Asignatura POF030 Semana 1. Contenido En forma general, los conceptos que se estudiarán en la asignatura son: – Procedures – Functions –
Arquitectura de la Aplicación
Teoría de los lenguajes Proyecto SIGU Equipo Nº3 Universidad Argentina J. F. Kennedy Sede: Don Bosco Integrantes: Irene Arias Fernández Mariana Pacheco.
Facilitando la vida del desarrollador con Visual Studio 2005 Daniel A. Seara
Introducción ADO .Net.
Tema 3 J2EE Java Database Connectivity Temas Selectos de Cómputo Grupo 912.
TALLER DE PROGRAMACIÓN III
1 Procedimientos Es un conjunto de sentencias incluidas entre las declaraciones Sub o Function y End Sub/Function VB utiliza varios tipos de procedimientos:
PL/SQL Francisco Moreno Universidad Nacional.
Clase 9 Curso Microsoft.NETCurso Microsoft.NET I.S.F.T. N° 182I.S.F.T. N° 182.
Acceso a datos con ADO.NET
Tema 6: Clases Antonio J. Sierra.
Igor Santos Grueiro. Ahora tenemos datos y datos …
Bases de Datos Relacionales
SIA Sistema Integrado de Admisión
16/04/ Sesión 11 Funciones y procedimientos Ing. Ricardo Inquilla.
SQL SERVER Reporting Services
Bases de datos en la Web n Las bases de datos permiten almacenar de una forma estructurada y eficiente toda la información de un sitio web n Ventajas –Proporcionar.
InfoPath Ventajas y Uso.
Colegio de Bachilleres Xochimilco Tepepan Plantel No. 13 Stone Chávez Mayra Fernanda Gabriela Pichardo Grupo: 308 Equipo: 22 1Stone Chávez Mayra Fernanda.
Colegio de Bachilleres Plantel 13 Xochimilco-Tepepan Integrantes: Karen Elizabeth González Monroy Elizabeth De Jesús Vergara Grupo:308.
Control de errores visual basic
Módulo 8: Manejo de Errores y Excepciones
Publicación de bases de datos Access en la web
APLICACIÓN EN VISUAL BASIC
Módulo 7: Programación Orientada a Objetos en Visual Basic 2005.
APROBADADIA.TXT AS400 Plataforma BANFOANDES
Daniel Correa Botero.  Esta capa contiene todo el código sql de la base de datos, contiene la contraseña y datos de conexión a la base de datos, la función.
Introducción al Lenguaje. ¿ Qué es PHP ? O Hypertext Pre-processoes (PHP) es un lenguaje de "código abierto" interpretado, de alto nivel, embebido en.
COLEGIO DE BACHILLERES PLANTEL 13 XOCHIMILCO-TEPEPAN MATERIA:TIC EQUIPO:21 PRESENTACION: BASE DE DATOS ALUMNAS: Adán Millán Sánchez.
C OLEGIO DE B ACHILLERES N O.13 X OCHIMILCO, T EPEPAN C ARRASCO G ARCÍA L ORENA T ORRES H EREDIA C ARLA P ALMIRA G RUPO : 308 M ATUTINO E QUIPO : 12.
Manual Desarrollo Flex – J2EE. Contenidos Análisis y Diseño 1 Implementación 2 J2EE 3 Pruebas 4.
CONTRATOS DE CLIENTES Orlando Sedamano Cornejo Marco Bustinza
Tema 11 Bases de Datos y el Lenguaje SQL
SQL (Structured Query Language) Lenguaje orientado a bases de datos y sobre todo, al manejo de consultas; el objetivo principal de SQL es la realización.
Colegio de Bachilleres Plantel 13 Xochimilco - Tepepan
MSSQL SERVER CURSO BÁSICO 1. DESCRIPCIÓN DEL CURSO. Sesión 4: Sentencia Insert,Transacciones,Insert general, Insert Select * From, Sentencia Update,Update.
¿Cómo programar un Botón para agregar registros a una base de datos?
Plataformas e- learning Moodle. Instalacion  Descargamos Moodle de su página oficial  Una vez hemos descargado el archivo, lo descomprimimos y copiamos.
Programación en Visual Basic
ACCESO A DATOS EN ASP.NET Controles de origen de datos Controles enlazados a datos.
Factorías e Iterables Introducción del concepto de patrón de diseño Construcción de tipos para recorridos con for extendido Fundamentos de Programación.
LICETH CAJAS 3RO ASI 26/10/2010. Es un lenguaje de programación diseñado para crear una amplia gama de aplicaciones que se ejecutan en.NET Framework,
DML Transact SQL Sesión X Triggers. Duración 2 Horas.
Crear Aplicación Cliente para Conectarse a una Base de Datos.
Definición: Es un estilo de programación, su objetivo primordial es la separación de la capa de presentación, capa de negocio y la capa de datos. ARQUITECTURA.
Ing. Sanchez Castillo Eddye Arturo Escuela Académica Profesional de Ingeniería de Sistemas.
Servicios Web-SOA Aula: Fomento 05/06/2006 a 08/05/2006.
Introducción a programación web Martin Esses. En las presentaciones anteriores, vimos como enviar datos a un controlador usando POST y como generar formularios.
Transcripción de la presentación:

Creación de una Aplicación Multicapas con ASPNET 2005 Miguel Ángel Niño Zambrano Adaptación de: Building Layered Web Applications with Microsoft ASP.NET 2.0 - Part 1-2-3. http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=416

Objetivos Diseñar una aplicación muticapa, separando adecuadamente la presentación, el negocio y los datos. Diseñar, construir e implementar clases orientadas a objetos reusable de fácil mantenimiento. Crear objetos de negocio personalizados. Usar Visual Studio .Net 2005 para desarrollar la aflicción Web con este estilo arquitectónico.

Arquitectura de la Aplicación Presentation layer – PL. Business Logic Layer – BLL. Data Access Layer – DAL. Objetivo primordial es poder cambiar una o mas capas si afectar las otras.

Arquitectura de la Aplicación La PL pregunta al BLL por algún objeto, por ejemplo, el contacto de una persona. La BLL puede opcionalmente desarrollar alguna validación (por ejemplo, ¿Está habilitado el usuario actual para hacer ésta llamada?) y después llama al DAL. El DAL conecta a la base de datos y pregunta por un registro específico. Cuando el registro es encontrado, éste es retornado de la base de datos al DAL. El DAL empaqueta los datos de la base de datos en un objeto personalizado y lo retorna AL BLL. Finalmente, el BLL retorna el objeto al PL, donde podrías ser mostrado en una página Web.

El modelo Espagueti protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { string sql = @"SELECT FirstName, LastName, MiddleName FROM ContactPerson WHERE Id = 1"; using (SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NLayer"].ConnectionString)) using (SqlCommand myCommand = new SqlCommand(sql, myConnection)) myConnection.Open(); using (SqlDataReader myReader = myCommand.ExecuteReader()) if (myReader.Read()) { txtFirstName.Text = myReader.GetString(0); txtLastName.Text = myReader.GetString(1); if (!myReader.IsDBNull(2)) { txtMiddleName.Text = myReader.GetString(2); } myReader.Close(); myConnection.Close(); Dificultad para Escribir y recordar No se puede reutilizar éste código, hay que copiarlo y pegarlo todo.

El modelo Espagueti protected void btnSave_Click(object sender, EventArgs e) { string sqlBase = @"UPDATE ContactPerson SET FirstName='{0}', LastName='{1}', MiddleName ='{2}' WHERE Id = 1"; using (SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NLayer"].ConnectionString)) string sql = String.Format(sqlBase, txtFirstName.Text, txtLastName.Text, txtMiddleName.Text); SqlCommand myCommand = new SqlCommand(sql, myConnection); myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close(); } Abre una conexión por cada operación SQL injection La capa de datos y lógica de negocio están revueltas

Controles SqlDataSource <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NLayer %>" DeleteCommand="DELETE FROM [ContactPerson] WHERE [Id] = @original_Id" InsertCommand="INSERT INTO [ContactPerson] ([FirstName], [MiddleName], [LastName], [DateOfBirth], [ContactPersonType]) VALUES (@FirstName, @MiddleName, @LastName, @DateOfBirth, @ContactPersonType)" SelectCommand="SELECT * FROM [ContactPerson]" UpdateCommand="UPDATE [ContactPerson] SET [FirstName] = @FirstName, [MiddleName] = @MiddleName, [LastName] = @LastName, [DateOfBirth] = @DateOfBirth, [ContactPersonType] = @ContactPersonType WHERE [Id] = @original_Id" OldValuesParameterFormatString="original_{0}" > <DeleteParameters> <asp:Parameter Name="original_Id" Type="Int32" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="FirstName" Type="String" /> <asp:Parameter Name="MiddleName" Type="String" /> <asp:Parameter Name="LastName" Type="String" /> <asp:Parameter Name="DateOfBirth" Type="DateTime" /> <asp:Parameter Name="ContactPersonType" Type="Int32" /> <asp:Parameter Name="original_Id" Type="Int32" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="FirstName" Type="String" /> <asp:Parameter Name="MiddleName" Type="String" /> <asp:Parameter Name="LastName" Type="String" /> <asp:Parameter Name="DateOfBirth" Type="DateTime" /> <asp:Parameter Name="ContactPersonType" Type="Int32" /> </InsertParameters> </asp:SqlDataSource> CRUD Expone la lógica de los datos en la página No se puede reutilizar. Un nuevo campo debe actualizar el control. Opción 2: TableAdapter

Metodología de Desarrollo - DRA Definición de la Arquitectura (Diagrama casos de uso reales, Despliegue, Aplicación, etc.) Análisis de Requerimientos (Ej. Análisis de Datos y Flujos de Datos, Diseño de Interfaces (HCI), story board, Análisis de Procesos) Diseño de la Aplicación Diseño de la Capa de Lógica de Negocio - BLL Diseño Clases Diseño del Modelo de Objetos Diseño de la Capa de Datos – DAL Diseño Separación Lógica de capas. (Namespaces) Diseño de la Base de Datos Implementación de la Aplicación Pruebas y Despliegue

Definición de la Arquitectura del Sistema Estilo Arquitectónico: Capas y Patrones, Casos Reales.

Decisiones de Arquitectura Aplicación Web cliente – Servidor. Estilo arquitectónico Multicapa: Presentación – Negocio – Persistencia. Uso de Patrones MVC y Proxy. Orientado a Objetos y Componentes. Uso de las mejores prácticas.

Introducción a la Aplicación de Ejemplo Casos de Uso Reales

Análisis de Requerimientos Lista de Reglas de Negocio, Informes, Reportes, Restricciones.

Requerimientos de la aplicación Reglas del Negocio La aplicación debe ser capaz de ver una lista de todas las personas de contacto en el sistema. Además, ella debería ser capaz de crear nuevo, y cambiar y suprimir a personas de contacto existentes. La aplicación debe ser capaz de seleccionar a una persona de contacto específica, y luego conseguir una lista de sus direcciones asociadas. Además, ella debería ser capaz de crear nuevo y cambiar y suprimir direcciones existentes para la persona de contacto. La aplicación debe ser capaz de seleccionar a una persona de contacto específica, y luego conseguir una lista de sus direcciones de correo electrónico asociadas. Además, ella debería ser capaz de crear nuevo y cambiar y suprimir direcciones de correo electrónico existentes para la persona de contacto. El usuario del uso debe ser capaz de seleccionar a una persona de contacto específica, y luego conseguir una lista de sus números de teléfono asociados. Además, ella debería ser capaz de crear nuevo y cambiar y suprimir números de teléfono existentes para la persona de contacto.

Requerimientos de la aplicación Consultas Presentar la información de los usuarios que coinciden con un nombre de usuario. Presentar la información de los contactos que están clasificados como amigos Informes Obtener un informe de todos los contactos y clasificado por tipo de contacto. Restricciones Un contacto no puede tener más de dos direcciones.

Diseño de la Aplicación Capa lógica del Negocio BLL y Capa de Datos DAL

Diseño de Clases Del discurso anterior se debe diseñar las siguientes clases: ContactPerson Address EmailAddress PhoneNumber Mejores prácticas de diseño: ¿Qué acciones deberían realizar los objetos del negocio? Como una persona puede tener varios datos de la misma clase (números telefónicos y direcciones) entonces de necesita manejar una colección. Almacenar las clases por separado vs. un solo archivo de clase. Decide por separado con una clase que se encarga de administrar su conexión con los datos. Diseño Borrador

Diseño de Clases Métodos de ContactPerson que se compartirán entre los objetos del negocio: Métodos CRUD GetItem GetList Insert Update Delete Métodos específicos del Negocio Search Desactivate Clone Filter Por facilidad se usarán sólo los CRUD.

Diseño del Modelo de Objetos – Primera Aproximación Usar una herramienta CASE. Existen dos enumeraciones ContactType y PersonType. La clase Address no tiene aún definido el tipo (type). Las clases PhoneNumber y EmailAddress no tienen CRUD. La clase ContactPerson no tiene propiedades para referenciar las clases PhoneNumber y EmailAddress. Es conveniente tener éstos tipos de datos en una colección: Ej. Address (List<Address>), PhoneNumber (List<PhoneNumber>). Para acceder al nombre completo debería crearse una propiedad adecuada FULLNAME. Los métodos Update e Insert se pueden unificar en un implementación UPsert.

Diseño del Modelo de Objetos – Segunda Aproximación La clase ContactPerson tiene propiedades PhoneNumbers y EmailAddresses, con los tipos de su respectiva colección. Para trabajar con una lista de personas se desarrollo un ContactPersonList. Se añadió un valor NotSet a las enumeraciones, diciendo que los valores no están determinados aún.

Diseño del Modelo de Objetos – Tercera Aproximación Además de las clases anteriores se debe crea las clases manejadoras, según la decisión de diseño tomada. Cada una de éstas clases tienen una referencia a los objetos del negocio anterior. La implementación es: GetItem devuelve un caso de la clase, GetList devuelve una lista de los casos de la clase, mientras Save acepta un caso de la clase que debe ser almacenada en la base de datos. Finalmente, el método Delete acepta un caso de la clase también, conteniendo el artículo que debería ser suprimido. GetItem para el ContactPersonManager tiene una sobrecarga que le permite para determinar si usted quiere cargar sólo los datos básicos para un ContactPerson, o todos los datos asociados. Los GetList reciben sólo el id del ContactPerson y con éste ya conoce que desea traer Address, PhoneNumber, etc.

Diseño de la Capa de Datos DAL Opciones TableAdapters Embedded Data Access Code. Separate DAL Classes. (Mejores prácticas) La última es la seleccionada e implica separadas DAL para cada uno de sus objetos de negocio: clase ContactPersonManager tiene a un colega ContactPersonDB, EmailAddressManager tiene una clase EmailAddressDB, etcétera. Las clase *DB interactúan directamente con la base de datos, con sus métodos CRUD. Los parámetros son los objetos del negocio (ContactPerson, EmailAddress, etc) o tipos simples según el caso.

Diseño del DAL En todas las clases el método Delete() retorna un bool para establecer el éxito o fracaso de la operación. El método Save() devuelve un int que sostiene el ID del registro que fue insertado o actualizado por el método. GetItem() y GetList() retornan objetos del negocio.

Diseño Separación lógica de Capas con Namespaces Para separar claramente los objetos de negocio, la lógica de negocio y el acceso de datos, se ponen todos ellos en namespaces separados: Spaanjaars.ContactManager.BO: para los objetos de negocio. Spaanjaars.ContactManager.Bll: para la lógica de negocio. Spaanjaars.ContactManager.Dal: para los datos tienen acceso al código. Tanto la capa lógica de negocio como la capa de acceso de datos consiguen una referencia a los objetos en el BO namespace. Además, la capa de negocio consigue una referencia a la capa de acceso de datos para toda la interacción de datos. Los objetos del negocio se colocan en una capa diferente para evitar referencias circulares entre la capa del negocio y la de datos.

Diseño de la Base de Datos Es conveniente usar una CASE. Seguir los pasos de un diseño adecuado de Base de datos. Las clases del negocio se mapean a tablas con sus respectivas relaciones. Desarrollar Procedimientos Almacenados adecuados a ser llamados por las clases *DB, teniendo en cuenta las interfaces definidas. Opcional: Usar un proyecto de BD.

Diseño Final La PL, por ejemplo una página de ASPX llamada ShowContactPerson.aspx, pide el BLL algún objeto, por ejemplo una persona de contacto. A través de un llamdo a ContactPersonManager. GetItem () obteniendo el ID de la persona de contacto. El BLL opcionalmente puede realizar alguna validación y luego envíar la petición al DAL llamando ContactManagerDB.GetItem (). El DAL se conecta a la base de datos y pide un registro específico. Ejecutando un procedimiento almacenado, como sprocContactPersonSelectSingleItem y pasándolo el ID de la persona de contacto. Cuando el registro es encontrado, es devuelto de la base de datos al DAL en un objeto de SqlDataReader. El DAL empaqueta los datos de base de datos en un ejemplar objeto ContactPerson el del BO y lo devuelve al BLL. Finalmente, el BLL devuelve el objeto de ContactPerson a la capa de Presentación, donde podría ser mostrado sobre una página Web por ejemplo.

Implementación de la Aplicación Clases, propiedades, código de métodos, conexión a la BD, separación física de capas

Creación de Carpetas y Archivos de Clase Separa físicamente las capas: BusinessLogic: Almacena archivos de la capa o namespace BLL. BusinessObject: Archivos de la capa o namespace BO. Contiene las Colecciones. DataAccess: Archivos de la capa o namespace Dal. Enums: Las Enumeraciones.

Crear Clases BO - Mejores Prácticas Utilizar el concepto de #Region, para separar secciones de código. Especialmente establecer variables privadas y públicas. Conjuntos de métodos específicos.

Crear Clases BO - Mejores Prácticas Correcto uso acceso a las variables privadas a través de propiedades. Es importante crear una propiedad type que retorne o asigne valores de los tipo enumerados a las propiedades de clase.

Crear Clases BLL Cada método de esta capa tiene la siguiente forma: Una de la funcionalidades es validar RN: public static EmailAddress GetItem(int id) { return EmailAddressDB.GetItem(id); } public static EmailAddress GetItem(int id, IPrincipal currentUser) { if (!currentUser.IsInRole("EmailAddressManagers")) throw new NotSupportedException(@"You're not allowed to call EmailAddressManager.GetItem when you're not in the EmailAddressManagers role"); } return EmailAddressDB.GetItem(id); Opcionalmente se pueden cachear los objetos devueltos para no acceder nuevamente a la BD. EmailAddress myEmailAddress = EmailAddressManager.GetItem(10, Context.User);

Crear las Clases de DAL Public Shared Function GetItem(ByVal id As Integer) As Address Dim myAddress As Address = Nothing Dim myConnection As SqlConnection = New SqlConnection(AppConfiguration.ConnectionString) Try Dim myCommand As SqlCommand = New SqlCommand("sprocAddressSelectSingleItem", myConnection) myCommand.CommandType = CommandType.StoredProcedure myCommand.Parameters.AddWithValue("@id", id) myConnection.Open Dim myReader As SqlDataReader = myCommand.ExecuteReader If myReader.Read Then myAddress = FillDataRecord(myReader) End If myReader.Close Finally CType(myReader, IDisposable).Dispose() End Try myConnection.Close CType(myConnection, IDisposable).Dispose() Return myAddress End Function

Crear las Clases de DAL Private Shared Function FillDataRecord(ByVal myDataRecord As IDataRecord) As EmailAddress Dim myEmailAddress As EmailAddress = New EmailAddress myEmailAddress.Id = myDataRecord.GetInt32(myDataRecord.GetOrdinal("Id")) myEmailAddress.Email = myDataRecord.GetString(myDataRecord.GetOrdinal("Email")) myEmailAddress.Type = CType(myDataRecord.GetInt32(myDataRecord.GetOrdinal("EmailType")), ContactType) myEmailAddress.ContactPersonId = myDataRecord.GetInt32(myDataRecord.GetOrdinal("ContactPersonId")) Return myEmailAddress End Function ‘la interfaz IDataRecord da un acceso fuertemente tipado a los valores ‘dentro de cada registro. Permite independizar el procedimiento del ‘proveedor de datos Ej. SqlDataReader, OleDbDataReader. Para el manejo de Nulos se aconseja lo siguiente: if (!myDataRecord.IsDBNull(myDataRecord.GetOrdinal("ZipCode"))) { myAddress.ZipCode = myDataRecord.GetString(myDataRecord.GetOrdinal("ZipCode")); }

Crear las Clases de DAL Public Shared Function GetList(ByVal contactPersonId As Integer) As EmailAddressList Dim tempList As EmailAddressList = Nothing Dim myConnection As SqlConnection = New SqlConnection(AppConfiguration.ConnectionString) Try Dim myCommand As SqlCommand = New SqlCommand("sprocEmailAddressSelectList", myConnection) myCommand.CommandType = CommandType.StoredProcedure myCommand.Parameters.AddWithValue("@contactPersonId", contactPersonId) myConnection.Open() Dim myReader As SqlDataReader = myCommand.ExecuteReader If myReader.HasRows Then tempList = New EmailAddressList While myReader.Read tempList.Add(FillDataRecord(myReader)) End While End If myReader.Close() Finally CType(myReader, IDisposable).Dispose() End Try CType(myConnection, IDisposable).Dispose() Return tempList End Function Para el manejo de Nulos se aconseja lo siguiente: if (!myDataRecord.IsDBNull(myDataRecord.GetOrdinal("ZipCode"))) { myAddress.ZipCode = myDataRecord.GetString(myDataRecord.GetOrdinal("ZipCode")); }

Creación de Clases de Listas de Objetos de Negocio Imports System Imports System.Collections.Generic namespace Spaanjaars.ContactManager.BO ''' <summary> ''' The EmailAddressList class is designed to work with lists of instances of EmailAddress, hacer su uso tipado y mas fácil de usar. ''' </summary> Public Class EmailAddressList Inherits List(Of EmailAddress) Public Sub New() End Sub End Class End Namespace ‘El llamado en la funcion GetList seria: ‘Dim tempList As EmailAddressList = Nothing

Creación de Procedimientos Almacenados en la BD CREATE PROCEDURE sprocEmailAddressSelectSingleItem @id int AS SELECT Id, Email, EmailType, ContactPersonId FROM EmailAddress WHERE Id = @id

Clases DAL Método Save() Public Shared Function Save(ByVal myEmailAddress As EmailAddress) As Integer Dim result As Integer = 0 Dim myConnection As SqlConnection = New SqlConnection(AppConfiguration.ConnectionString) Try Dim myCommand As SqlCommand = New SqlCommand("sprocEmailAddressInsertUpdateSingleItem", myConnection) myCommand.CommandType = CommandType.StoredProcedure If myEmailAddress.Id = -1 Then myCommand.Parameters.AddWithValue("@id", DBNull.Value) Else myCommand.Parameters.AddWithValue("@id", myEmailAddress.Id) End If myCommand.Parameters.AddWithValue("@email", myEmailAddress.Email) myCommand.Parameters.AddWithValue("@emailType", myEmailAddress.Type) myCommand.Parameters.AddWithValue("@contactPersonId", myEmailAddress.ContactPersonId) Dim returnValue As DbParameter returnValue = myCommand.CreateParameter returnValue.Direction = ParameterDirection.ReturnValue myCommand.Parameters.Add(returnValue) myConnection.Open() myCommand.ExecuteNonQuery() result = Convert.ToInt32(returnValue.Value) myConnection.Close() Finally CType(myConnection, IDisposable).Dispose() End Try Return result End Function

Creación de Procedimientos Almacenados en la BD CREATE PROCEDURE sprocEmailAddressInsertUpdateSingleItem @id int, @email nvarchar (100), @emailType int, @contactPersonId int AS DECLARE @ReturnValue int IF (@id IS NULL) -- New Item BEGIN INSERT INTO EmailAddress ( Email, EmailType, ContactPersonId ) VALUES @email, @emailType, @contactPersonId SELECT @ReturnValue = SCOPE_IDENTITY() END ELSE BEGIN UPDATE EmailAddress SET Email = @email, EmailType = @emailType, ContactPersonId = @contactPersonId WHERE Id = @id SELECT @ReturnValue = @id IF (@@ERROR != 0) RETURN -1 RETURN @ReturnValue GO

Elementos de Implementación de la clase ContactPerson Private _strAddresses As AddressList = New AddressList Private _phoneNumbers As PhoneNumberList = New PhoneNumberList Private _emailAddresses As EmailAddressList = New EmailAddressList Public ReadOnly Property FullName() As String Get Dim tempValue As String = _strFirstName If Not String.IsNullOrEmpty(_stMiddleName) Then tempValue += " " + MiddleName End If tempValue += " " + _strLastName Return tempValue End Get End Property

Elementos de Implementación de la clase ContactPerson Public Shared Function GetItem(ByVal id As Integer) As ContactPerson Return GetItem(id, False) End Function Public Shared Function GetItem(ByVal id As Integer, ByVal getContactRecords As Boolean) As ContactPerson Dim myContactPerson As ContactPerson = ContactPersonDB.GetItem(id) If Not (myContactPerson Is Nothing) AndAlso getContactRecords Then myContactPerson.Addresses = AddressDB.GetList(id) myContactPerson.EmailAddresses = EmailAddressDB.GetList(id) myContactPerson.PhoneNumbers = PhoneNumberDB.GetList(id) End If Return myContactPerson

Elementos de Implementación de la clase ContactPerson Public Shared Function Save(ByVal myContactPerson As ContactPerson) As Integer Dim myTransactionScope As TransactionScope = New TransactionScope Try Dim contactPersonId As Integer = ContactPersonDB.Save(myContactPerson) For Each myAddress As Address In myContactPerson.Addresses myAddress.ContactPersonId = contactPersonId AddressDB.Save(myAddress) Next For Each myEmailAddress As EmailAddress In myContactPerson.EmailAddresses myEmailAddress.ContactPersonId = contactPersonId EmailAddressDB.Save(myEmailAddress) For Each myPhoneNumber As PhoneNumber In myContactPerson.PhoneNumbers myPhoneNumber.ContactPersonId = contactPersonId PhoneNumberDB.Save(myPhoneNumber) myContactPerson.Id = contactPersonId myTransactionScope.Complete Return contactPersonId Finally CType(myTransactionScope, IDisposable).Dispose() End Try End Function

Elementos de Implementación de la clase ContactPerson CREATE PROCEDURE sprocContactPersonDeleteSingleItem @id int AS BEGIN TRAN DELETE FROM Address WHERE ContactPersonId = @id IF @@ERROR <> 0 BEGIN ROLLBACK TRAN RETURN -1 END EmailAddress DELETE FROM PhoneNumber WHERE ContactPersonId = @id IF @@ERROR <> 0 BEGIN ROLLBACK TRAN RETURN -1 END ContactPerson Id = @id COMMIT TRAN

Uso de la clase ContactPerson ContactPerson myContactPerson = new ContactPerson(); myContactPerson.FirstName = "Imar"; myContactPerson.LastName = "Spaanjaars"; myContactPerson.DateOfBirth = new DateTime(1971, 8, 9); myContactPerson.Type = PersonType.Family; Address myAdress = new Address(); myAdress.Street = "Some Street"; myAdress.HouseNumber = "Some Number"; myAdress.ZipCode = "Some Zip"; myAdress.City = "Some City"; myAdress.Country = "Some Country"; myContactPerson.Addresses.Add(myAdress); EmailAddress myEmailAdress = new EmailAddress(); myEmailAdress.Email = "Imar@DoNotSpam.com"; myEmailAdress.Type = ContactType.Personal; myContactPerson.EmailAddresses.Add(myEmailAdress); PhoneNumber myPhoneNumber = new PhoneNumber(); myPhoneNumber.Number = "555 - 2368"; myPhoneNumber.Type = ContactType.Personal; myContactPerson.PhoneNumbers.Add(myPhoneNumber); ContactPersonManager.Save(myContactPerson);

Implementación de la Aplicación Web - DAL Web Forms y controles, Web Config.

Resumen de la Capas

Archivos de la Aplicación Web App_Data and NLayer.mdf: BD Usada en la aplicación. App_Themes and Css\Styles.css: Contirne un tema para el gridView. Y el archivo de estilos. Web.config: Configuraciones de la aplicación.

Formulario Default.aspx Cree una nueva página e intercambie a la vista de diseño. Añada un GridView a la página. Abra el panel de Tareas del GridView y Escoge la Fuente de Datos select <New data source>. En el asistente de configuración del DataSource, Seleccione el Objeto y click OK. Escoja un Objeto De negocio, asegúrese muestre sólo los componentes de datos esten chequeados y luego escoger el objeto apropiado de negocio de la lista. En el caso, escoger: Spaanjaars. ContactManager. Bll. ContactPersonManager: Define Data Methods window asegúrese que sobre la etiqueta escogida sea el GetList(). Después, limpie la selección sobre la etiqueta de Update, esta página no necesita un método de Update. Dejar las demás etiquetas como están.

Atributos para el Diseñador <DataObjectMethod> establece el método por defecto para traer datos del AddressList. <DataObjectFieldAttribute(True, True, False)> Permite que la propiedad la use el asistente. <DataObjectMethod(DataObjectMethodType.Select, True)> _ Public Shared Function GetList(ByVal contactPersonId As Integer) As AddressList Return AddressDB.GetList(contactPersonId) End Function <DataObjectFieldAttribute(True, True, False)> _ Public Property Id() As Integer Get Return _intId End Get Set(ByVal value As Integer) _intId = Value End Set End Property

Vista de Presentación Todos los contactos

Añadir botones para permitir al usuario nuevo, editar, borrar <asp:ButtonField CommandName="Edit" Text="Edit"/> <asp:TemplateField ShowHeader="False"> <ItemTemplate> <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete" OnClientClick="return confirm('Are you sure you want to delete this contact person?');"> </asp:LinkButton> </ItemTemplate> </asp:TemplateField>

Establecer un método que captura el comando seleccionado <asp:GridView ID="gvContactPersons" runat="server" AutoGenerateColumns="False" DataSourceID="odsContactPersons" DataKeyNames="Id" OnRowCommand="gvContactPersons_RowCommand" AllowPaging="True" CellPadding="4" GridLines="None"><Columns> ....</Columns></asp:GridView>

Vista de Edición de Datos