unidad de aprendizaje ii

44
INTRODUCCIÓN a) Presentación y contextualización Los temas que se tratan en la presente Unidad, tienen por finalidad que el estudiante conozca la arquitectura del ADO.NET como un conjunto de componentes del software para acceder a datos y a servicios de datos, con el fin de proporcionar una escalabilidad mejor para sus aplicaciones, a medida que el procesamiento de datos utiliza cada vez más arquitecturas de varios niveles. b) Competencia Conoce la arquitectura, aplicaciones y herramientas básicas de la programación estableciendo una estructura jerárquica para los programas. c) Capacidades 1. Reconoce a la POO como una programación de objetos para diseñar aplicaciones y programas informáticos. 2. Analiza los eventos del manejo de las excepciones en la ejecución del programa. 3. Identifica los bloques protegidos cuando se produce una excepción en el programa. 4. Conoce la utilización de Ado.net y aplicaciones desconectadas para la manipulación de datos. d) Actitudes Promueve el desarrollo de la POO. Muestra interés ante el manejo de excepciones. Proporciona métodos al programa para protegerlos de los errores. Asume el desarrollo de la utilización de ADO.NET. e) Presentación de Ideas básicas y contenido esenciales de la Unidad: La Unidad de Aprendizaje 02: Arquitectura del ADO.NET, comprende el desarrollo de los siguientes temas: TEMA 01: Programación Orientada a Objetos. TEMA 02: Manejo de Excepciones. TEMA 03: Manejo de Excepciones (Continuación) TEMA 04: Utilización de ADO.NET y aplicaciones Desconectadas.

Upload: francisco-jaimes-espinoza

Post on 22-Dec-2015

230 views

Category:

Documents


4 download

DESCRIPTION

desarrollo de aplicaciones

TRANSCRIPT

INTRODUCCIÓN

a) Presentación y contextualización Los temas que se tratan en la presente Unidad, tienen por finalidad que el estudiante conozca la arquitectura del ADO.NET como un conjunto de componentes del software para acceder a datos y a servicios de datos, con el fin de proporcionar una escalabilidad mejor para sus aplicaciones, a medida que el procesamiento de datos utiliza cada vez más arquitecturas de varios niveles.

b) Competencia Conoce la arquitectura, aplicaciones y herramientas básicas de la programación estableciendo una estructura jerárquica para los programas.

c) Capacidades 1. Reconoce a la POO como una programación de objetos para diseñar

aplicaciones y programas informáticos. 2. Analiza los eventos del manejo de las excepciones en la ejecución del

programa. 3. Identifica los bloques protegidos cuando se produce una excepción

en el programa. 4. Conoce la utilización de Ado.net y aplicaciones desconectadas para la

manipulación de datos. d) Actitudes

  Promueve el desarrollo de la POO.   Muestra interés ante el manejo de excepciones.   Proporciona métodos al programa para protegerlos de los errores.   Asume el desarrollo de la utilización de ADO.NET.

e) Presentación de Ideas básicas y contenido esenciales de la Unidad: La Unidad de Aprendizaje 02: Arquitectura del ADO.NET, comprende el desarrollo de los siguientes temas: TEMA 01: Programación Orientada a Objetos. TEMA 02: Manejo de Excepciones. TEMA 03: Manejo de Excepciones (Continuación) TEMA 04: Utilización de ADO.NET y aplicaciones Desconectadas.

 Tema 01: Programación Orientada a Objetos

 PROGRAMACIÓN ORIENTADA A OBJETOS.  

La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa objetos y sus interacciones, para diseñar aplicaciones y programas informáticos. Está basado en varias técnicas, incluyendo herencia, abstracción, polimorfismo y encapsulamiento. Su uso se popularizó a principios de la década de los años 1990. En la actualidad, existe variedad de lenguajes de programación que soportan la orientación a objetos.La programación orientada a objetos, intenta simular el mundo real a través del significado de objetos que contiene características y funciones. Los lenguajes orientados a objetos se clasifican como lenguajes de quinta generación.Como su mismo nombre indica, la programación orientada a objetos se basa en la idea de un objeto, que es una combinación de variables locales y procedimientos llamados métodos que juntos conforman una entidad de programación.

 

Origen de la POO.

Los conceptos de la programación orientada a objetos tienen origen en Simula 67, un lenguaje diseñado para hacer simulaciones, creado por Ole-Johan Dahl y Kristen Nygaard del Centro de Cómputo Noruego en Oslo. En este centro, se trabajaba en simulaciones de naves, que

fueron confundidas por la explosión combinatoria de cómo las diversas cualidades de diferentes naves podían afectar unas a las otras. La idea ocurrió para agrupar los diversos tipos de naves en diversas clases de objetos, siendo responsable cada clase de objetos de definir sus propios datos y comportamientos. Fueron refinados más tarde en Smalltalk, que fue desarrollado en Simula en Xerox PARC (cuya primera versión fue escrita sobre Basic)

pero diseñado para ser un sistema completamente dinámico en el cual los objetos se podrían crear y modificar "en marcha" (en tiempo de ejecución) en lugar de tener un sistema basado en programas estáticos.

 

La programación orientada a objetos tomó posición como el estilo de programación dominante a mediados de los años ochenta, en gran parte debido a la influencia de C++, una extensión del lenguaje de programación C. Su dominación fue consolidada gracias al auge de las Interfaces gráficas de usuario, para las cuales la programación orientada a objetos está particularmente bien adaptada. En este caso, se habla también de programación dirigida por eventos.

 

Las características de orientación a objetos fueron agregadas a muchos lenguajes existentes durante ese tiempo, incluyendo Ada, BASIC, Lisp, Pascal, entre otros. La adición de estas características a los lenguajes que no fueron diseñados inicialmente para ellas condujo

a menudo a problemas de compatibilidad y en la capacidad de mantenimiento del código. Los lenguajes orientados a objetos "puros", por su parte, carecían de las características de las cuales muchos programadores habían venido a depender. Para saltar este obstáculo, se hicieron muchas tentativas para crear nuevos lenguajes basados en métodos orientados a objetos, pero permitiendo algunas características imperativas de maneras "seguras". El Eiffel de Bertrand

Meyer fue un temprano y moderadamente acertado lenguaje con esos objetivos pero ahora ha sido esencialmente reemplazado por Java, en gran parte debido a la aparición de Internet, y a la implementación de la máquina virtual de Java en la mayoría de navegadores. PHP en su versión 5 se ha modificado, soporta una orientación completa a objetos, cumpliendo todas las características propias de la orientación a objetos.

 

1. Ventajas de la POO.

Fomenta la reutilización y extensión del código. Permite crear sistemas más complejos. Relacionar el sistema al mundo real. Facilita la creación de programas visuales. Construcción de prototipos

Agiliza el desarrollo de software Facilita el trabajo en equipo Facilita el mantenimiento del software

 

Lo interesante de la POO es que proporciona conceptos y herramientas

con las cuales se modela y representa el mundo real tan fielmente

como sea posible.

Modelos: La POO permite realizar un modelo de sistema casi independientemente de los requisitos del proyecto. La razón es que en la POO, la jerarquía la establecen los datos, en cambio en la programación estructurada la jerarquía viene definida por los programas. Este cambio hace que los modelos se establezcan de forma similar al razonamiento humano y, por lo tanto, resulte más natural.Modularidad: Un programa es modular si se compone de módulos independientes y robustos. Esto permite la reutilización y facilita la verificación y depuración de los mismos. En POO, los módulos están directamente relacionados con los objetos. Los objetos son módulos naturales ya que corresponden a una imagen lógica de la realidad.Extensibilidad: Durante el desarrollo de sistemas, ocurre la aparición de nuevos requisitos, por eso es deseable que las herramientas de desarrollo permitan añadirlos sin modificar la estructura básica del Diseño. En POO es posible lograr esto siempre y cuando se hayan definido de forma adecuada la jerarquía de clases, los atributos y métodos.Eliminación de redundancia: En el desarrollo de sistemas se desea evitar la definición múltiple de datos y funciones comunes. En POO esto se logra mediante la herencia (evita la definición múltiple de propiedades comunes a muchos objetos) y el polimorfismo (permite la modificación de métodos heredados). Solo hay que definir los atributos y los métodos en el antepasado más lejano que los comparte.Reutilización: La POO proporciona un marco perfecto para la reutilización de las clases. El encapsulamiento y la modularidad nos permiten utilizar una y otra vez las mismas clases en aplicaciones distintas. En efecto, el aislamiento entre distintas clases significa que es posible añadir una nueva clase o un modulo nuevo (extensibilidad) sin afectar al resto de la aplicación.

 2.Conceptos Fundamentales.

 La programación orientada a objetos es una forma de programar que

trata de encontrar una solución a estos problemas. Introduce nuevos

conceptos, que superan y amplían conceptos antiguos ya conocidos.

Entre ellos destacan los siguientes:

2.1. Objeto.

Entender que es un objeto es la clave para entender cualquier lenguaje orientado a objetos. Existen muchas definiciones que se le ha dado al Objeto. Primero empecemos entendiendo que es un objeto del mundo real. Un objeto del mundo real es cualquier cosa que vemos a nuestro alrededor. Digamos que para leer este artículo lo hacemos a través del monitor y una computadora, ambos son objetos, al igual que nuestro teléfono celular, un árbol o un automóvil.

 

Analicemos un poco más a un objeto del mundo real, como la computadora. No necesitamos ser expertos en hardware para saber que una computadora está compuesta internamente por varios componentes: la tarjeta madre, el chip del procesador, un disco duro, una tarjeta de video, y otras partes más. El trabajo en conjunto de todos estos componentes hace operar a una computadora.

 

Internamente, cada uno de estos componentes puede ser sumamente complicado y puede ser fabricado por diversas compañías con diversos métodos de diseño. Pero nosotros no necesitamos saber cómo trabajan cada uno de estos componentes, como saber qué hace cada uno de los chips de la tarjeta madre, o cómo funciona internamente el procesador. Cada componente es una unidad autónoma, y todo lo que necesitamos saber de adentro es cómo interactúan entre sí los componentes, saber por ejemplo si el procesador y las memorias son compatibles con la tarjeta madre, o conocer donde se coloca la tarjeta de video. Cuando conocemos como interaccionan los componentes entre sí, podremos armar fácilmente una computadora.¿Qué tiene que ver esto con la programación? La programación orientada a objetos trabaja de esta manera. Todo el programa está construido en base a diferentes componentes (Objetos), cada uno tiene un rol específico en el programa y todos los componentes pueden comunicarse entre ellos de formas predefinidas.Todo objeto del mundo real tiene 2 componentes: características y

comportamiento.Por ejemplo, los automóviles tienen características (marca, modelo, color, velocidad máxima, etc.) y comportamiento (frenar, acelerar, retroceder, llenar combustible, cambiar llantas, etc.).

 

Los Objetos de Software, al igual que los objetos del mundo real, también tienen características y comportamientos. Un objeto de software mantiene sus características en una o más "variables", e implementa su comportamiento con "métodos". Un método es una función o subrutina asociada a un objeto.Para redondear estas ideas, imaginemos que tenemos estacionado en nuestra cochera un Ford Focus color azul que corre hasta 260 km/h. Si pasamos ese objeto del mundo real al mundo del software, tendremos un objeto Automóvil con sus características predeterminadas:

                               Marca = Ford                                Modelo = Focus                                Color = Azul                                Velocidad Máxima = 260 km/h

Cuando a las características del objeto le ponemos valores decimos que el objeto tiene estados. Las variables almacenan los estados de un objeto en un determinado momento.Definición teórica: Un objeto es una unidad de código compuesto de variables y métodos relacionados. Entidad provista de un conjunto de propiedades o atributos (datos) y de comportamiento o funcionalidad (métodos) los mismos que consecuentemente reaccionan a eventos. Se corresponde con los objetos reales del mundo que nos rodea, o a objetos internos del sistema (del programa). Es una instancia a una clase.

2.2. Clases

En el mundo real, normalmente tenemos muchos objetos del mismo tipo. Por ejemplo, nuestro teléfono celular es sólo uno de los miles que hay en el mundo. Si hablamos en términos de la programación orientada a objetos, podemos decir que nuestro objeto celular es una instancia de una clase conocida como "celular". Los celulares tienen

características (marca, modelo, sistema operativo, pantalla, teclado, etc.) y comportamientos (hacer y recibir llamadas, enviar mensajes multimedia, transmisión de datos, etc.).

Cuando se fabrican los celulares, los fabricantes aprovechan el hecho

de que los celulares comparten esas características comunes y construyen modelos o plantillas comunes, para que a partir de esas se puedan crear muchos equipos celulares del mismo modelo. A ese modelo o plantilla le llamamos CLASE, y a los equipos que sacamos a partir de ella la llamamos OBJETOS.

Esto mismo se aplica a los objetos de software, se puede tener muchos objetos del mismo tipo y mismas características.Definición teórica: La clase es un modelo o prototipo que define las variables y métodos comunes a todos los objetos de cierta clase. También se puede decir que una clase es una plantilla genérica para un conjunto de objetos de similares características.

Por otro lado, una instancia de una clase es otra forma de llamar a un objeto. En realidad no existe diferencia entre un objeto y una instancia. Sólo que el objeto es un término más general, pero los objetos y las instancias son ambas representación de una clase.Definición Teórica: Una instancia es un objeto de una clase en particular. Definiciones de las propiedades y comportamiento de un tipo de objeto concreto. La instanciación es la lectura de estas definiciones y la creación de un objeto a partir de ellas.

2.3. Herencia

Por ejemplo, herencia de la clase C a la clase D; es la facilidad mediante la cual la clase D hereda en ella cada uno de los atributos y operaciones de C, como si esos atributos y operaciones hubiesen sido definidos por la misma D. Por lo tanto, puede usar los mismos métodos y variables públicas declaradas en C. Los componentes registrados como "privados" (private) también se heredan, pero como no pertenecen a la clase, se mantienen escondidos al programador y sólo pueden ser accedidos a través de otros métodos públicos. Esto es así para mantener hegemónico el ideal de OOP.

2.4. Método

Algoritmo asociado a un objeto (o a una clase de objetos), cuya ejecución se desencadena tras la recepción de un "mensaje". Desde el punto de vista del comportamiento, es lo que el objeto puede hacer. Un método puede producir un cambio en las propiedades del objeto, o la generación de un "evento" con un nuevo mensaje para otro objeto del sistema.

2.5. Evento

Es un suceso en el sistema (tal como una interacción

del usuario con la máquina, o un mensaje enviado por un objeto). El sistema maneja el evento enviando el mensaje adecuado al objeto pertinente. También se puede definir como evento, a la reacción que puede desencadenar un objeto, es decir la acción que genera.

2.6. Mensaje

Una comunicación dirigida a un objeto, que le ordena que ejecute uno de sus métodos con ciertos parámetros asociados al evento que lo generó. Un objeto es inútil si está aislado. El medio empleado para que un objeto interactúe con otro son los mensajes. Hablando en términos un poco más técnicos, los mensajes son invocaciones a los métodos de los objetos.

2.7. Propiedad o atributo

Contenedor de un tipo de datos asociados a un objeto (o a una clase de objetos), que hace los datos visibles desde fuera del objeto y esto se define como sus características predeterminadas, y cuyo valor puede ser alterado por la ejecución de algún método.

2.8. Estado interno

Es una variable que se declara privada, que puede ser únicamente accedida y alterada por un método del objeto, y que se utiliza para indicar distintas situaciones posibles para el objeto (o clase de objetos). No es visible al programador que maneja una instancia de la clase.

2.9. Componentes de un objeto

Atributos, identidad, relaciones y métodos.Identificación de un objeto: un objeto se representa por medio de una tabla o entidad que esté compuesta por sus atributos y funciones correspondientes.

3. Características de la POO

Existe un acuerdo acerca de qué características contempla la "orientación a objetos", las características siguientes son las más importantes:

3.1. Abstracción.

Denota las características esenciales de un objeto, donde se capturan sus comportamientos. Cada objeto en el sistema sirve como modelo de un "agente" abstracto que puede realizar trabajo, informar y cambiar su estado, y "comunicarse" con otros objetos en el sistema sin revelar cómo

se implementan estas características. Los procesos, las funciones o los

métodos pueden también ser abstraídos y cuando lo están, una variedad de técnicas son requeridas para ampliar una abstracción. El proceso de abstracción permite seleccionar las características relevantes dentro de un conjunto e identificar comportamientos comunes para definir nuevos tipos de entidades en el mundo real. La abstracción es clave en el proceso de análisis y diseño orientado a objetos, ya que mediante ella podemos llegar a armar un conjunto de clases que permitan modelar la realidad o el problema que se quiere atacar.

Por ejemplo, volvamos al ejemplo de los automóviles, ¿Qué características podemos abstraer de los automóviles? O lo que es lo mismo ¿Qué características semejantes tienen todos los automóviles? Todos tendrán una marca, un modelo, número de chasis, peso, llantas, puertas, ventanas, etc. Y en cuanto a su comportamiento todos los automóviles podrán acelerar, frenar, retroceder, etc.

Tema 02: Manejo de Excepciones

 MANEJO DE EXCEPCIONES

Las excepciones son eventos que ocurren por un error del programa en tiempo de ejecución, las cuales son generadas para indicarle al programador que ha ocurrido un error que impide la normal ejecución del programa.

Para controlar estos errores es necesario tener en cuenta una gran cantidad de situaciones, dependiendo del caso que se esté tratando. Por ejemplo, para manipular un archivo el programador debería tomar en cuenta: la existencia del archivo, una ruta de acceso válida, la integridad del archivo, entre otras cosas si el archivo está en una red tendría que verificar que la conexión esté activa. Aunque el código para utilizar el archivo sea pequeño todas las verificaciones retardarían la ejecución del programa.

El manejo de las excepciones permite independizar el código de uso de un recurso del manejo de los errores, lo cual no retrasaría la ejecución del programa porque el código de acceso al recurso se ejecuta siempre, pero el código de manejo de errores se ejecuta sólo cuando estos suceden.

El método que proporciona Delphi para protegerse de los errores son las excepciones. Cuando ocurre un error en tiempo de ejecución Delphi genera una excepción; crea una instancia de una clase especial denominada Exception o algún descendiente, el flujo del programa se altera y únicamente se ejecuta el código de respuesta a excepción. Este código puede tratar el error (procesarlo y responder si corresponde) o no, en cuyo caso se genera un evento OnException en la aplicación.

Detección y procesamiento de excepciones

Una excepción se mantiene hasta que se atiende o termina el programa. Normalmente procesaremos las excepciones que se produzcan en nuestro código para recuperarnos sin problemas de los errores. Delphi nos da una vía para escapar airosos de las situaciones no previstas, cuando se producen errores inesperados que harían caer nuestro sistema sin remedio, tal vez dejando archivos abiertos y con pérdida de datos.

Para ver el tratamiento por defecto de los errores en Delphi se utilizará un programa que calcule el cuadrado de un número entero.

procedure TForm1.Button1Click(Sender: TObject);vari : integer;begini := StrToInt (edit1.text);label1.caption := format (‘El cuadrado es: %d’, [ i * i ]);end;

Fig. 1: Programa para calcular el cuadrado de un entero.

Cuando se presiona el botón, el texto escrito en el editor se convierte en un número entero, se eleva al cuadrado y se muestra el resultado. Pero si se escribe algo que no sea un número entero o se deja vacío el editor se producirá un error de conversión. Delphi procesa este error mostrando un pequeño mensaje indicativo.

El resultado es que no ocurre nada grave. La respuesta por defecto de Delphi a las excepciones es sólo mostrar el mensaje correspondiente en una caja de diálogo como la anterior. En una aplicación simple no es necesario mucho más, pero sería agradable para el usuario que se le explique un poco mejor que ha sucedido. Además, no hay nada más frustrante que un mensaje donde se nos dice que “Se ha producido un error”. La única opción que tiene es presionar un único botón que puede ver, para hacer desaparecer este mensaje.

Cambio de la respuesta por defecto de las excepciones Para modificar la respuesta estándar de Delphi ante un error hay que escribir un procedimiento de respuesta al evento OnException, que se produce en el objeto Application.

El objeto Application no es un componente visible. Se crea automáticamente cada vez que se ejecuta una aplicación y se referencia con la variable global Application. Para indicar que se ejecute un método al producirse el evento OnException, se puede utilizar el hecho que los eventos son propiedades. Como tales, se les puede asignar un valor (en el caso de los eventos, un procedimiento que se ejecutará al producirse el evento). La definición de la propiedad OnException indica al programador qué tipo de método se le puede asignar. En el caso de OnException:

property OnException: TExceptionEvent;El tipo TExceptionEvent es un tipo procedural:TExceptionEvent = procedure (Sender: TObject; E: Exception) of object;

Por lo tanto, el procedimiento debe esperar dos parámetros, uno de tipo tObject y otro de tipo Exception, y debe ser un método de un objeto (el método puede pertenecer a cualquiera de los forms (ventana en Delphi) que componen el proyecto). Se escribe un método nuevo al form principal:procedure tForm1.TratarExcepciones (sender: tObject; e:Exception);beginMessageDlg (‘Se ha producido un error. Por favor intente de nuevo’, mtError, [mbOk],0);end;

La declaración de este método debe ser escrita en la definición del tipo Tform1 (cuando se asigna un método a un evento a través del Inspector de Objetos, Delphi escribe esta declaración por nosotros).

Definición de la clase entera (declaración del nuevo método):TForm1 = class (TForm) Button1: TButton; Edit1: TEdit;Label1: TLabel; Label2: TLabel;procedure Button1Click (Sender: TObject);privateprocedure TratarExcepciones (sender: tObject; e : Exception);public{ Public declarationes }end;

Se realiza la asignación al crear el form principal, en el evento OnCreate:

procedure TForm1.FormCreate (sender: TObject);beginApplication.OnException := TratarExcepciones;end;

Ahora el programa presenta un mensaje de error distinto del predeterminado cuando se produce un error de cualquier tipo. El siguiente paso es filtrar los errores, respondiendo de distinta manera a cada uno de ellos.Es posible ver de qué tipo es una excepción mirando la clase a la que pertenece el parámetro E.

Categorías y clases de Excepciones Las excepciones en Delphi se pueden dividir en las siguientes categorías:

Conversión de tipo: Se producen cuando tratamos de convertir un tipo de dato en otro, por ejemplo utilizando las funciones IntToStr, StrToInt o StrToFloat. Delphi dispara una excepción EConvertError.

Tipo forzado (typecast): Se producen cuando tratamos de forzar el reconocimiento de una excepción de un tipo como si fuera de otro usando el operador as. Si no son compatibles, se dispara la excepción EInvalidCast.

Aritmética de punto flotante: Se produce al hacer operaciones con expresiones de tipo real. Existe una clase general para este tipo de excepciones (EmathError) pero Delphi utiliza sólo los descendientes de ésta:

2. EinvalidOp: El procesador encontró una instrucción inválida.

3. EzeroDivide: División por cero.

4. Eoverflow: Se excede en más la capacidad aritmética (número demasiado grandes).

5. Eunderflow: Se excede en menos la capacidad aritmética (números demasiado pequeños).

Aritmética entera: Se producen al hacer operaciones con expresiones de tipo entero. Existe una clase general definida para este tipo de excepciones llamada EintError, pero Delphi sólo utiliza los descendientes:

1. EDivByZero: División por cero.2. ERangeError: Número fuera del rango disponible según el tipo de

dato. La comprobación de rango debe estar activada (indicador $R).

3. EIntOverflow: Se excede en más la capacidad aritmética (números demasiado grandes). La comprobación de sobre pasamiento debe estar activada (indicador $O).

Falta de memoria: Se produce cuando hay un problema al acceder o reservar memoria. Se definen dos clases:

1. EOutOfMemory: No hay suficiente memoria disponible para completar la operación.

2. EInvalidPointer: La aplicación trata de disponer de la información referenciada por un puntero que indica una dirección inválida (fuera del rango de direcciones permitido a la aplicación). Generalmente significa que la memoria ya ha sido liberada.

Entrada/Salida: Se produce cuando hay un error al acceder a dispositivos de entrada/salida o archivos. Se define una clase genérica (EInOutError) con ua propiedad que contiene el código de error (ErrorCode).

Hardware: Se producen cuando el procesador detecta un error que no puede manejar o cuando la aplicación genera intencionalmente una interrupción para detener la ejecución. El código para manejar estas excepciones no se incluye en las DLL complicadas, sólo en las aplicaciones. Se define una clase base que no es directamente utilizada (EProcessorException). Las clases útiles son los descendientes:

1. EFault: Es una clase base para todas las excepciones de faltas del procesador.

2. EGPFault: Error de Protección General, cuando un puntero trata de acceder a posiciones de memoria protegidas.

3. EStackFault: Acceso ilegal al segmento de pila del procesador.

4. EPageFault: El manejador de memoria de Windows tuvo problemas al utilizae el archivo de intercambio.

5. EInvalidOpcode: El procesador trata de ejecutar una instrucción inválida.

6. EBreakpoint: La aplicación ha generado una interrupción de ejecución (punto de ruptura, utilizado por el debugger de Delphi para inspeccionar las variables en un punto).

7. ESingleStep: La aplicación ha generado una interrupción de ejecución paso a paso. Después de cada paso de programa se produce la interrupción. Es utilizada también por el debugger de Delphi.

Excepciones silenciosas: Se disparan intencionalmente por la aplicación para interrumpir el flujo de ejecución; no generan mensajes de error. Se define una clase: EAbort. Esta excepción es automáticamente generado cuando invocamos el procedimiento global Abort. La excepción silenciosa provocada por el procedimiento Abort se puede utilizar para interrumpir la ejecución del programa en cualquier punto.

Manejadores de excepciones Delphi tiene dos tipos de manejadores de excepciones:

El primero es sólo para el manejo de errores, su representación es la siguiente:

El segundo es para liberar recursos y se puede representar así:

                           

El código llamado "bloque protegido" es el que se coloca entre el try y el finally o entre try y el except, este código es el que va a quedar protegido por el manejador de errores o excepciones.

La diferencia entre estos dos tipos de manejadores es que el primero sólo ejecuta el bloque entre el except y el end si ocurre un error en el bloque protegido y el segundo ejecuta el bloque entre el finally y el end siempre, tanto si ocurre un error como si finaliza exitosamente.

Para manejar los errores Delphi define un objeto llamado Exception del cual derivan todos los objetos manejadores de excepciones. Estos objetos son los que se colocan entre las palabras reservadas on y do con el fin de manejar el tipo de excepción que se desee. Se pueden declarar tantas expresiones on y do como excepciones se quieran manejar, o también se pueden declarar manejadores genéricos de excepciones omitiendo las declaraciones on y do.

Hay casos en que una excepción no puede ser manejada, para esto se utiliza la palabra reservada raise con el fin de levantar la excepción de nuevo; de esta forma la excepción salta al manejador de excepciones anterior, si no encuentra un manejador sigue recursivamente cayendo en los contextos de excepción definidos, si no existe quien la maneje primero despliega un mensaje de error y en muchos casos puede abortar el programa.

El uso de los manejadores de excepciones de cualquiera de las formas expuestas anteriormente ayuda a proteger los recursos que utilice el programa, haciendo éste más seguro.

Los recursos que necesitan protección en Delphi son los siguientes:

Archivos: Solicitud, liberación de archivos y además controlar cualquier tipo de error que pueda provocar que este quede abierto.

Memoria: Se controla que la memoria sea liberada una vez que se ha solicitado y ocurra un error de ejecución.

Recursos de Windows: Por ejemplo, poder finalizar conexiones con otros sistemas si ocurre un error en la ejecución del programa.

Objetos: Poder liberar los recursos o memoria asignada a cada uno de los objetos.

Tema 03: Manejo de Excepciones (Continuación)

TRY...EXCEPT

Para proteger una porción de código se debe encerrar en un bloque try...except. Entre estas dos palabras reservadas se ubica el código que está expuesto a errores; después de except se procesan estos últimos, cerrando todo el bloque con end.

Los bloques protegidos forman como capas al resto del programa; cuando se produce una excepción en un lugar del código la ejecución salta directamente a la capa de protección donde se está ejecutando. Si el error no se procesa en esta capa se pasa a la siguiente, y así sucesivamente. Las aplicaciones de Delphi corren dentro de un bloque protegido, por lo que todas las excepciones no tratadas especialmente se procesan en el objeto de Application.

Esquema de una aplicación con varios bloques protegidos que muestra cómo se redirige la ejecución cuando se produce un error:

Fig. 3: Bloques de protección anidados.

Como se puede ver en el gráfico, los errores que se producen fuera de las estructuras try...except son tratadas en la parte correspondiente al bloque anterior; en última instancia se procesan en el evento OnException de la aplicación; es como si toda la aplicación estuviera encerrada en un gran bloque try...except.

Este método de declarar como clases a las excepciones permite tratarlas de modo jerárquico. Por tanto un manejador de una clase de excepciones trata también las clases descendientes, podría usarse un código como el siguiente:try{Código}Excepton <clase de la excepción> do{manejar la excepción o sus descendientes}on <otra clase > do:end;

Por ejemplo para atrapar un error aritmético que se pueda producir en una operación, se podría escribir:try{operación}excepton eMathError doShowMessage(‘Error de punto flotante’);on eIntError doShowMessage (‘Error aritmético entero’);end;

Algunas situaciones comunes donde es necesario un control de errores y la corrección de los mismos son: División por cero

Cada vez que se realiza una división hay que tener en cuenta el error que puede producirse si el divisor es cero. Según se trate de una división entera (div) o de una de punto flotante, se dispara una excepción eDivByZero o eZeroDivide, respectivamente.Las siguientes funciones permiten probar un método de recuperación del error de división por cero. En este caso no se presenta ningún mensaje al usuario, sólo se devuelve un valor

por defecto.

function DivisionEntera (a, b: integer) : integer;begintryResult := a div b;excepton eDivByZero doResult := 0;end;end;

function DivisionReal (a,b :

real): real;

begin

try

Result := a/b;

except

end;

end;

Acceso a un fichero Abrir un archivo y leer datos.

El siguiente fragmento de código abre un archivo y lee 50 bytes en un array, mostrando un mensaje si se produce cualquier error en el proceso.varf: file;b: array [0..49 of byte];begin

tryAssignFile ( f , ’nombre’ );

ResetFile ( f , 1 );BlockRead ( f , b , 50 );CloseFIle ( f );Excepton eInOutError doShowMessage ( ‘Error al trabajar con el archivo’ );end;end;

Abrir un archivo. Bloques anidados El procedimiento siguiente se puede usar cuando necesitamos utilizar un archivo; si existe, se abre y si no existe se crea.

Se tienen dos bloques anidados, uno dentro del otro. El interior captura un error al abrir ( por ejemplo, cuando no existe el archivo); mientras que el exterior intercepta un posible error de creación, presentando un mensaje al usuario y abandonando inmediatamente el procedimiento. Si todo va bien, se puede utilizar el archivo abierto (con posible comprobación de errores al leer o escribir) y finalmente se debe cerrar el archivo.

Varf: file;begintryAssignFile ( f , ‘ARCH.TXT’ ); Reset ( f , 1 );exceptOn eInOutError doRewrite ( f , 1 );end;except on InOutError do beginShowMessage ( ‘No se puede crear el archivo’ ); Exit;end;{ utilizar el archivo }CloseFile ( f );end;

Se puede ver que de producirse un error al abrir o leer el archivo, la instrucción de cierre no se ejecutará. En el caso de una lectura no hay mayores problemas, pero cuando se modifica el contenido del archivo es indispensable cerrarlo correctamente.

TRY...FINALLY

A veces es necesario ejecutar una porción de código suceda un error o no. Para esto, existe en Delphi la estructura try...finally. Cuando se produce un error dentro de este bloque se suspende el tratamiento de la excepción para ejecutar el código que sigue a finally. Y cuando ha terminado, se sigue con el proceso normal de proceso de error.

Ejemplo:

Cuando se realiza una tarea que puede extenderse en el tiempo, es bueno indicarlo al usuario mediante el cursor de espera (el reloj de arena, en DelphicrHourglass); al terminar la operación se debe sustituir el cursor anterior. Pero si ocurre un error

durante el proceso, la instrucción de restitución del cursor no se ejecutará nunca y el usuario puede quedarse horas esperando a que el cursor le indique que puede seguir trabajando. Se puede evitar esto con el siguiente código:

tryscreen.cursor := crHourglass; { se pone el cursor de espera }

{ aquí se hace el proceso }finallyscreen.cursor := crDefault; { se restituye el cursor por defecto }end;

Si en la sección finally se produce un error, la ejecución saltará inmediatamente a la siguiente capa de protección (sección except correspondiente o al manejador por defecto de la aplicación). Por lo tanto, se debe evitar en esta sección utilizar código propenso a errores, o desactivar la detección de los mismos.

Algunos de los casos más comunes que necesitan código de ejecución obligatoria son:Cerrar un archivo

Si se produce un error mientras se accede al archivo o se procesan sus datos, no se ejecutará la orden CloseFile y el archivo permanecerá abierto. Esto puede ocasionar pérdida de datos ya que el sistema de directorios se vuelve inestable.

Para arreglar esto puede usarse un código como éste:

varf: file;b: array [0..49 of byte];begin try tryAssignFile ( f , ‘nombre’ );ResetFile ( f , 1 );BlockRead ( f , b , 50 );excepton eInOutError doShowMessage ( ‘Error al trabajar con el

archivo’ );end;finallyCloseFile ( f );end;end;

Liberar memoria

Si se crea una estructura dinámica, es responsabilidad del programador devolver la memoria utilizada al sistema.Ejemplo utilizando GetMem y FreeMem:typeaInt = array [0..0] of integer;paInt = ^aInt; vara: paInt; beginGetMem ( a , SiezOf (integer) * 10000 );{ se solicita memoria para 10000 enteros }try{Utilización de la memoria}

finallyif assigned (a) then FreeMem ( a , SizeOf (integer) * 10000 );end;end;

Devolver Recursos gráficos

En Windows, los recursos deben ser compartidos entre todas las aplicaciones que corren en un determinado momento. Esto es especialmente crítico para los recursos gráficos, ya que el sistema posee pocos y siempre son solicitados. Por lo que es indispensable devolverlos después de usarlos.

Ejemplo que utiliza un Device Context para acceder a la pantalla:

varMiDC: hDC;begintry GetDC (0); {se pide un manejador para la pantalla entera }{ código dibuja en la pantalla usando la API }

ReleaseDC (0); { libera el DC al sistema }finallyend;end;

Utilizar el objeto de la excepción

Cuando se dispara una excepción se crea una instancia de la clase correspondiente. Por lo tanto, se puede, en principio, tener acceso a las propiedades y métodos de la misma.La definición de la clase Exception es la siguiente:Exception = class (TObject)privateFMessage: PString; FHelpContext: Longint;function GetMessage: string;procedure SetMessage (const Value: string);publicconstructor Create (const Msg: string);constructor CreateFmt (const Msg: string; const Args: array of const);constructor CreateRes (Ident: Word);constructor CreateResFmt (Ident: Word; const Args: array of const);constructor CreateHelp (const Msg: string; AHelpContext: Longint);constructor CreateFmtHelp (const Msg: string; const Args: array of const; AHelpContect: Longint);constructor CreateResHelp (Ident: Word; AHelpContext: Longint);constructor CreateResFmtHelp (Ident: Word; const Args: array of const; AHelpContext: Longint);destructor Destroy; overrride;property HelpContext: Longint read FHelpContext write FHelpContext;property Message: string read GetMessage write SetMessage;property MessagePtr: PString read FMessage;end;

Hay disponibles tres propiedades: una indica el contexto de ayuda y las otras dos dan acceso al mensaje de error en los dos formatos utilizados en Windows.Para acceder al objeto de la excepción se debe utilizar una variable temporal. La forma de hacerlo es:try{ Algún proceso }expecton e: eDivByZero doShowMessage (‘Error!’ #13+e.Message);end;

Con este código no se está creando una nueva instancia de la excepción. Únicamente se define una variable que apunta al objeto

creado por Delphi. La clase Exception (y la mayoría de los descendientes directos) tiene pocas propiedades de utilidad, pero nada impide en los descendientes creados por el programador agregar otras nuevas.

Esto es precisamente lo que hace Delphi con la clase eInOutError, definiendo una propiedad que almacena el código de error devuelto por el sistema:

EInOutError = class(Exception)publicerrorCode: Integer;end;

Por la tanto, se puede saber cual fue el error que provocó la excepción. El siguiente fragmento indica cómo mostrar este código al usuario, a la vez que muestra una forma de asegurar el cierre del archivo:

var f: file;

st: array[0..50] of charbegin try tryAssignFile ( f , ‘PRUEBA.TXT’ ); Reset ( f , 1 );BlockRead ( f , st , SizeOf(st) );excepton e: eInOutError doShowMessage( format ( ‘Error %d al acceder al archivoPRUEBA.TXT’, [e.ErrorCode] ) );end; finally

{$I-} { descativa la detección de errores }CloseFile ( f ); { puede dar error si f no está abierto }

{$I+} { activa la detección de errores de nuevo }end;end;

Se utilizan {$I-} y {$I+} en la parte finally. Si el archivo no se pudo abrir se produce el error, se muestra el mensaje y se ejecuta CloseFile sobre un archivo que no está abierto, lo que genera otro código de error.

Para evitar que la ejecución salte al bloque protegido superior con este último error, se desactiva la detección de los mismos cuanto se intenta cerrar el archivo. De esta forma, si el archivo está abierto se

cierra normalmente, y si no está abierto no pasa nada. Una aplicación más elaborada podría mantener una lista con los mensajes de error correspondientes y utilizar el código de error como índice.

Provocar una excepción

Hay ocasiones en las que es conveniente llamar a una capa de tratamiento de errores superior. Por ejemplo, se podría mostrar un mensaje en un bloque local y después dejar que la capa superior libere recursos. Pero una vez que se ha tratado una excepción, ésta se da por terminada y el código de los bloques protegidos superiores no se ejecuta. Se debe indicar a Delphi que se quiere

mantener la excepción para que pueda tratarla el bloque superior: algo así como llamar a un método heredado desde una clase descendiente. Para lograrlo, el lenguaje contempla la opción de re-lanzar la excepción, como si se volviera a producir. Sólo hay que insertar en el código la palabra reservada raise:

tryStrToInt (‘a45’);excepton exception dobeginShowMessage (‘Se ha producido un error’);raise; end;end;

En el ejemplo anterior se utiliza raise para disparar la misma excepción que estábamos procesando. La ejecución salta inmediatamente al bloque protegido anterior. También se utiliza raise para disparar las propias excepciones del programador.

Definir nuevas excepciones

Cuando se produce un error en un procedimiento del programador (ya sea de un objeto o no), éste puede tratar de recuperarse en el lugar o bien lanzar una excepción indicando que algo anduvo mal. Esta segunda alternativa es la preferida, porque le permite al programador tratar todos los errores del mismo modo.

Para definir una nueva excepción se debe crear un descendiente de Exception o alguna clase más especializada. en este descendiente se pueden definir nuevas propiedades o métodos de la manera usual, lo cual permitirá al programador un mejor tratamiento

del error.

Si se implementa una función que transforma un número entero en una cadena de unos y ceros que conforman su representación binaria, pero no se desea tratar los números negativos, se puede definir una excepción nueva y dispararla cuando se detecte que el número es incorrecto. No es necesaria ninguna propiedad ni método nuevo, por lo que la excepción puede ser un descendiente directo de Exception. No obstante, como se trata en realidad de un error durante una conversión, se hará que descienda de eConvertError:

typeeSoloPosit = class (eConvertError)end;y ahora se escribe el procedimiento de conversión:

function DecToBin (v: integer): string;vartemps: string;beginif v < 0 thenraise eSoloPosit.Create (‘No se permiten números negativos’);if v > 0 then temps := ‘ ’else temps := ‘0’;while v > 0 do begintemps := Chr (v Mod 2+48 ) + temps;v := v div 2;end;result := temps;end;

La llamada a esta función se realiza desde un bloque protegido, en una aplicación simple de conversión:

procedure TForm1.Button1Clic (Sender: TObject);begintryLabel3.caption := DecToBin (StrToBin (StrToInt (edit1.text) );excepton e: eConvertError doShowMessage (‘Error! ‘ +e.Message);end;end;

Tema 04: Utilización de ADO.NET y Aplicaciones Desconectadas

                      ¿QUÉ ES ADO.NET?

     Tecnología .Net para el acceso y manipulación de datos.     Es especialmente diseñado para trabajar sobre ambientes

desconectados.     El espacio de nombres es System.Data.

OBJETOS DE ADO. NET (I)

  ConnectionPermite que se establezca un canal de comunicación con la fuente de datos.

  CommandPermite que se ejecuten las instrucciones sobre la fuente de datos.

Las clases exactas de CONNECTION y COMMAND dependerán del proveedor de datos que se utilice y éste a su vez depende del tipo de fuente de datos a la que se quiera conectar, sin importar cuál sea los pasos para utilizarlo siempre son los mismos:  Abrir la conexión.  Ejecutas los comandos.  Cerrar la conexión.

OBJETOS DE ADO. NET (II)Para leer los datos hay dos modos:1. Data Reader

  Es un objeto ligero y rápido que permite leer UN registro a la vez, de modo secuencial.

  Es un objeto de solo lectura.  No da información del tipo de dato que está leyendo, el

desarrollador debe conocerlos y también el orden de las columnas.

2. Data Set  Es un objeto que a su vez contiene otros sub‐

objetos que lo hacen más lento que el DataReader pero que tiene más flexibilidad para el uso de los datos.

  El papel del DataAdapter es el de “sincronizador de datos” por medio de sus dos métodos principales, Fill() y Update().

La forma de trabajar seria:1. Llenar el DataSet.2. Realizar las acciones.3. Actualizar al fuente de datos.

Mejor rendimiento con el proveedor adecuado

MODELO DESCONECTADO¿Qué es un DataSet?

  Es una representación de datos que se residen memoria

  Un modelo de programación relacional coherente, independiente del origen de datos al que se encuentra asociado.

  Representa un conjunto completo de datos, incluyendo las tablas, relaciones y restricciones.

  Los cambios hechos en el DataSet no afectan inmediatamente la base de datos.

  Los datos pueden seguir siendo manipulados sin necesidad de tener

  la conexión establecida con la fuente de datos  Permite el ordenamiento, búsqueda y filtrado de datos de una

forma sencilla.  Permite trabajar con estructuras XML

Representación gráfica

La Colección DataTable

  Cero o más tablas representadas por objetos DataTable.  Cada DataTable contiene:

Una colección de columnas representadas por una DataColumnCollection.

  Un conjunto de constraints representado en la ConstraintCollection.

  Un conjunto de filas en la DataRowCollection, que representa los datos de la tabla.

DataColumns

Otras propiedades:

  AllowDBNull– Si acepta o no valores nulos.

  MaxLength– Tamaño de la columna.

  Unique – Si se duplican datos, se lanza

ConstraintException.

La colección de Constraints

(Restricciones)

  PrimaryKey – Llave primaria.

  ForeignKeyConstraint – Llave foránea: Se crea cuando se agrega una relación entre dos tablas

La colección DataRelationCollection

  Objetos DataRelation que asocian las filas de un DataTable con las de otro DataTable.

  Cada DataRelation consta de el nombre de la relación, el nombre de las tablas relacionadas y las columnas relacionadas de cada tabla.

  Pueden existir relaciones con más de una columna por tabla.

  Las relaciones pueden tener restricciones de integridad:

  UniqueKeyConstraint y ForeignKeyConstraint.

Refrescando datos a través de un DataSet

  Se utiliza el método DataAdapter.Fill.  Si el DataTable tiene llaves primarias

definidas se refrescan las filas teniendo en cuenta la restricción de pk.

  A través de la propiedad RowState de las filas pueden identificarse aquellas que cambiaron.

  Si se quiere refrescar conservando lo nuevo del servidor y lo nuevo en memoria:  En una nueva tabla recuperar los

datos con el método fill del DataAdapter.  Luego ejecutar un Merge con la propiedad

PreserveChanges en true.

Buscando datos en el DataSet

  La idea es hacerlo de forma óptima utilizando los índice de las tablas en caso de que se tengan.

  Los índices son creados cuando se crea una llave primaria o una vista asociada a una tabla.

  Si la consulta se hace sobre el PK de la tabla:  Usar el método

DataTable.Rows.Find.  Para consultas que no involucran el PK:

  Construir una vista (DataView), ordenarla para que se construya el índice y utilizar los métodos Find y FindRows de la vista.

Elegir un DataReader o un DataSet

  Use un DataSet para:  Usar datos de forma remota entre un nivel y otro o desde un

servicio web XML.  Interactuar con datos dinámicamente, enlazar con un control

de Windows o web Forms.  Para combinar y relacionar datos procedentes de diferentes

orígenes.  Almacenar datos en memoria

caché dentro de la aplicación.  Proporcionar una vista XML de

los datos.  Procesamiento de datos sin

necesidad de tener una conexión abierta con el origen.

  Utilizar el DataReader sino necesita la funcionalidad de modo desconectado que proporciona el DataSet. El rendimiento es mejor por no requerir la memoria y el procesamiento que se requiere con el DataSet.

Universidad Privada Telesup © 2014Av. 28 de Julio 1056 - Cercado de Lima