Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework
Transcripción
Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework
nº28 julio-agosto 2006 • 6,50 € (España) Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework • Windows Server System dotNetManía www.dotnetmania.com Dedicada a los profesionales de la plataforma .NET WebParts en ASP.NET 2.0 (y III) • Servicios Web nativos con SQL Server 2005 • Detección de problemas de rendimiento en SQL Server 2000 y SQL Server 2005 (IV) • Acceso a datos con ADO.NET 2.0 (sin asistentes) dnm.editorial dotNetManía Dedicada a los profesionales de la plataforma .NET Vol. III •Número 28 • Julio-Agosto 2006 Precio: 6,50€ .NET Framework 3.0 Editor Paco Marín ([email protected]) Atención al suscriptor Pilar Pérez ([email protected]) Consejo de Redacción Dino Esposito, Guillermo 'guille' Som, José Manuel Alarcón, Lorenzo Ponte, Luis Miguel Blanco, Miguel Katrib (Grupo Weboo) y Octavio Hernández Colaboradores habituales Antonio Quirós, Braulio Díez, Carlos Quintero, Eladio Rincón, Javier Aragonés, Jorge Serrano, José Miguel Torres, Iván González, Pepe Hevia, Salvador Ramos y Sergio Vázquez Además colaboran en este número David Perona, Francisco A. González, José Luis Balsera Ilustraciones Yamil Hernández Edición, suscripciones y publicidad .netalia c/ Robledal, 135 28529 Rivas-Vaciamadrid (Madrid) www.dotnetmania.com Tf. (34) 91 666 74 77 Fax (34) 91 499 13 64 Imprime Color Digital ISSN 1698-5451 Depósito Legal M-3.075-2004 >> << Bienvenido al número 28, de julio y agosto de 2006, de dotNetManía. Entre los eventos Tech-Ed 2006 de Boston y MEDC Europe 2006 de Niza, este mes se han generado muchas e importantes noticias, pero ninguna tan polémica como la asignación del nombre comercial a la “suma” de .NET Framework 2.0 y WinFX. Y todo porque le han puesto “.NET Framework 3.0”. A todas las personas que yo he consultado les parece raro y confuso; y si leemos los comentarios que ha generado la noticia (unos 400 solo en en el blog de S. “Soma” Somasegar) vemos que hay bastante consenso sobre el tema. Podrían haberle puesto un número inferior o podrían haber esperado a que apareciese Orcas y así, tanto .NET Framework como las librerías y el CLR tendrían la versión 3.0, pero al parecer a alguien de marketing se le ocurrió que WinFX estaba añadiendo mucha confusión... Deberán darle un premio, porque precisamente “confusión” es la palabra que más se está usando ahora. Aunque la verdad es que tampoco tiene mayor importancia, o eso es lo que a mí me parece. Este mes nos hemos cogido la maleta y nos hemos ido a Boston con Francisco González de Solid Quality Learning y a Niza con José Luis Balsera de Raona. Ambos se han estre- nado este mes cubriendo el Tech-Ed y el MEDC, respectivamente; por tal motivo aprovecho para darles la bienvenida. Igualmente, le doy la bienvenida a otro colaborador invitado, David Perona, que se estrena con su “Servicios Web nativos con SQL Server 2005”. Este mes vuelve Marino Posadas con otra de sus excelentes entrevistas, esta vez a Arvindra Sehmi, la cabeza visible del Enterprise Team en Microsoft Corp's Developer and Platform Evangelism Group en EMEA. José Manuel Alarcón termina con su estupenda serie de artículos sobre WepParts en ASP.NET 2.0 y Eladio Rincón nos envía el penúltimo de su interesante serie sobre la detección de problemas de rendimiento en SQL Server. El artículo de portada este mes es nuevamente para la sección dnm.futuro, donde Octavio Hernández presenta las novedades de VB 9.0 para implementar LINQ. Este tipo de contenidos quizá no se puedan aplicar a día de hoy, pero pienso que son necesarios para ir preparándonos para el nuevo .NET Framework ¿3.5? con el CLR ¿3.0? y C# ¿3.0? o VB ¿9.0?. Mejor de versiones no hablamos :-). Y dentro hay más. Espero que le guste. Paco Marín <<dotNetManía Redactor Jefe Marino Posadas ([email protected]) 3 28 dnm.sumario MEDC Europe 2006 08-09 Tech-Ed Boston 2006 10-11 Entrevista a Arvindra Sehmi 12-14 Nuestro entrevistado de hoy es la cabeza visible del Enterprise Team en Microsoft Corp's Developer and Platform Evangelism Group en Europa, Oriente Medio y África (EMEA) y su trabajo se focaliza hacia la adopción de las mejores prácticas dentro de la comunidad de arquitectos de EMEA. WebParts en ASP.NET 2.0 (III) 16-20 Con este artículo finalizamos la serie sobre WebParts comenzada hace dos números en dotNetManía. En él trataremos algunos conceptos avanzados sobre bloques personalizables que nos permitirán llegar a un buen nivel en el desarrollo de este tipo de aplicaciones. En concreto, veremos cómo intercambiar información entre ellos y cómo exportarlos para su reutilización. Lo que nos traerá Orcas:VB 9.0 y LINQ 22-29 dnm.sumario Este artículo presenta las novedades que incluirá (probablemente con algunas variaciones) Visual Basic 9.0, incluyendo la sintaxis de las expresiones de consulta, que constituyen el principal reflejo en el lenguaje de la tecnología LINQ, y las extensiones para el soporte directo de XML. Servicios Web nativos con SQL Server 2005 30-35 Con el uso de HTTP EndPoints podemos exponer a la Web tanto los procedimientos almacenados como las UDF de nuestra base de datos sin tener que usar ninguna otra herramienta ni abrir puertos TCP para SQL Server 2005. Detección de problemas de rendimiento en SQL Server 2000 y SQL Server 2005 (IV) 36-39 En esta cuarta entrega nos vamos a centrar en analizar qué tipo de información hay almacenada en la memoria de SQL Server, división del uso de la memoria y cómo detectar bloqueos con las nuevas DMV de SQL Server 2005. Acceso a datos con ADO.NET 2.0 (sin asistentes) 41-46 Tal como comentamos en el número anterior, en esta ocasión vamos a ver cómo podemos acceder a una base de datos usando única y exclusivamente código, es decir, sin usar los asistentes que Visual Studio 2005 pone a nuestra disposición y que, en honor a la verdad, a muchos les facilitará la tarea de crear aplicaciones ADO.NET de una forma bastante sencilla. dnm.todotnet.qa Informes, autenticación y actualización por lotes 47-49 Esta semana, la primera de las 3 preguntas de rigor resuelve problemas relacionados con Reporting en ASP.NET. Otras preguntas se centran en la autenticación por Internet y las actualizaciones por lotes en ADO.NET. dnm.laboratorio FileHelpers 50-51 Es relativamente frecuente que el trasvase de información desde/hacia una aplicación se realice mediante archivos planos generados periódicamente. En tales ficheros, los registros se almacenan en líneas de texto que deben ser interpretadas para su posterior explotación. En el laboratorio de esta semana analizamos una librería que permite importar, exportar y explotar con gran comodidad archivos de este tipo en aplicaciones .NET. dnm.comunidad.net 52-54 Eventos locales Emprendia. La iniciativa para los e-mprendedores dnm.biblioteca.net 55 Programming Microsoft ASP.NET 2.0 Core Reference Visual C# 2005: A Developer's Notebook dnm.desvan 58 6 noticias.noticias.noticias.noticias.noticias.noticias << dotNetManía << dnm.noticias .NET Framework 3.0 A principios del pasado mes de Junio,S.“Soma” Somasegar,corporate vice president de la Developer Division de Microsoft, anunció la decisión de Microsoft de ponerle nombre comercial a WinFX: .NET Framework 3.0. Además de esto, Infocard también ha sido bautizado y a partir de ahora se llamará Windows CardSpace y también le conoceremos por sus siglas WCS. Así, las tecnologías que incluían WinFX hasta el momento: Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), Windows Workflow Foundation (WF) y Windows CardSpace (WCS) se suman a .NET Framework 2.0 para convertirse finalmente en .NET Framework 3.0. Sin embargo, las tecnologías anteriores como ADO.NET, ASP.NET, WinForms y el propio CLR o las BCL, no cambian y seguirán en su versión 2.0 como actualmente. Esto significa que, aunque pudiera parecerlo por el cambio de versión principal del .NET Framework, no hay cambios sobre lo antiguo y podemos seguir trabajando con los compiladores y las técnicas actuales como hasta ahora. .NET Framework 3.0 verá la luz con la salida de Windows Vista y estará disponible también para Windows XP y Windows Server 2003, tal y como estaba pensado. Ahora .NET Framework 3.0 versión CTP de junio ya está dispo- S. “Soma” Somasegar es corporate vice president of the Developer Division at Microsoft Corporation. Esta división es responsable de todos los lenguajes de programación, herramientas y plataformas en Microsoft, incluyendo Visual Studio, Web Platform and Tools, .NET Framework, CLR y otras tecnologías de la plataforma de desarrollo .NET. Además supervisa el India Develpment Center (IDC) en Hyderabad, India. Somasegar comparte frecuentemente sus pensamientos con los desarrolladores a través de su blog en: http://blogs.msdn.com/somasegar. nible para su descarga pública en: http://www.microsoft.com/downloads/de tails.aspx?FamilyId=8D09697E-48684D8D-A4CF-9B82A2AE542D. Esto ha creado cierta confusión en la comunidad de desarrolladores, ya que la versión 3.0 está construida sobre la versión 2.0 de .NET Framework. Parecía obvio que WinFX tendría que sumarse a .NET Framework, pero la mayoría pensábamos –equivocadamente, por lo que se ve– que WinFX se integraría en el .NET Framework con la aparición de lo que a día de hoy llamamos Orcas y que además añadiría LINQ, pasando a llamarse, entonces sí, .NET Framework 3.0. Sin embargo, ahora lo que sabemos es que cuando aparezca Orcas, el número de .NET Framework será el 3.5, mientras que la versión del CLR será para entonces la 3.0. Asimismo, Somasegar anunció que DLinq pasará a llamarse LINQ to SQL mientras que XLinq se llamará LINQ to XML. El esquema general de nombres para LINQ es el siguiente: LINQ para ADO.NET, el cual incluye: LINQ to DataSet LINQ to Entities LINQ to SQL El soporte de LINQ para otros tipos de datos incluye: LINQ to XML LINQ to Objects Más información en el blog de S. “Soma” Somasegar en http://blogs. msdn.com/somasegar, en el sitio de MSDN en http://msdn.microsoft.com/ winfx, o en los nuevos sitios de http://www.netfx3.com. Microsoft libera públicamente la beta 2 de Windows Vista Microsoft ha anunciado la disponibilidad del Programa de Evaluación de Windows Vista Beta 2 para clientes, pensado especialmente para aquellos desarrolladores y profesionales de TI que no disponen de suscripción a MSDN y TechNet, pero que desean recibir la beta 2 del próximo sistema operativo de la compañía y disfrutar de sus múltiples escenarios. Los profesionales inscritos en este programa podrán acceder a la beta 2 de Windows Vista a través de la des- carga gratuita de la Web de la compañía o recibir el producto en DVD, mediante el pago de los costes de producción y distribución. Todos los detalles sobre la descarga de la beta 2 de Windows Vista se encuentran en http://www.microsoft. com/spain/windowsvista donde los usuarios también disponen de la versión beta del asesor de actualizaciones Windows Vista Upgrade Advisor, la herramienta de software de diagnóstico que les ayudará a elegir la edición de Windows Vista más adecuada a sus necesidades, así como a conocer si sus equipos son capaces de soportar las características del nuevo SO. Una vez instalada la beta 2 de Windows Vista, los usuarios disponen de una guía de producto detallada para profesionales de TI y desarrolladores, programa antivirus para proteger sus equipos, así como información acerca de todas las versiones del nuevo sistema operativo, blogs, artículos técnicos, etc. dnm.noticias Primera CTP de Microsoft Robotics Studio Más de 250 participantes se dan citan en la 3ª edición del Borland Day Microsoft ha presentado en la RoboBusiness Conference and Exposition 2006, la primera CTP de Microsoft Robotics Studio, la plataforma de desarrollo de robótica integrada y destinada a las academias, aficionados y desarrolladores comerciales, que servirá para crear aplicaciones robóticas. Microsoft Robotics Studio incluye una herramienta de programación visual que facilita la creación y utilización de aplicaciones para robots. Permite a los desarrolladores generar servicios modulares para hardware y software, permitiendo a los usuarios interactuar con los robots a través de interfaces basadas en la Web o en Windows. Por supuesto, pueden extenderse funcionalidades desarrollando con cualquiera de los lenguajes de la plataforma .NET. Más información y descargas en: http://msdn.microsoft.com/robotics. Bill Curtis,director de procesos de Borland,exhorta a los asistentes a centrarse en la gestión del ciclo de vida de las aplicaciones como la mejor manera de conseguir el éxito en el desarrollo de las aplicaciones. Los robots de MSN invaden el mundo Microsoft ha iniciado un concurso internacional para incorporar a su servicio de mensajería instantánea MSN Messenger (próximamente Windows Live Messenger) nuevas funciones que ofrezcan prestaciones complementarias a sus más de 205 millones de usuarios en todo el mundo. Esta iniciativa está dirigida a desarrolladores de software y tiene como objetivo crear robots inteligentes que integrados dentro del programa de mensajería instantánea proporcionen de forma automática e interactiva respuestas e información a los usuarios, como si de una persona real se tratara. Los creadores de los robots más útiles e imaginativos obtendrán hasta 40.000 dólares en premios, mientras que todas las propuestas aceptadas estarán disponibles en http://www.robotinvaders.com. Los desarrolladores tienen a su disposición en el centro de recursos de Windows Live (http://www.msdn.com/live) todas las herramientas , tecnologías y guía necesarias para poder participar. Concurso para desarrolladores sin fronteras Programa ninemillion.org En el Tech-Ed 2006 se anunció un concurso que pretende animar a los desarrolladores y arquitectos de software a presentar un diseño para una aplicación empresarial de Office que favorezca a una organización benéfica de su elección. Los ganadores pueden recibir una financiación de 150.000$ en efectivo, además de otros premios para hacer realidad sus ideas. Más en: www.developwithoutborders.com. Coincidiendo con el Día Mundial del Refugiado, ACNUR y Microsoft pretenden atraer la atención sobre la situación actual de los niños refugiados en todo el mundo. A través de su red de servicios online MSN, Microsoft proporcionará soporte a la campaña a través de visibilidad publicitaria y contenido editorial en sus portales y servicios, y con alojamiento y traducción a 9 idiomas de la Web www.ninemillion.org. taciones y formación en esta metodología de procesos, están mejorando el desarrollo de aplicaciones. Además, han participado como ponentes, dando un Bill Curtis, director de valor mayor al procesos de Borland evento y complementando las soluciones de Borland, las siguientes compañías: Aventia, Coritel, EDS, Microsoft, Oracle, Sogeti, Sun y MTP. También han sido patrocinadores el Club-BPM, HP, Intel y TAISA. Además... Windows Communication Foundation RSS Toolkit Este toolkit, que viene con todo el código fuente, ilustra como exponer feeds ATOM y RSS a través de WCF endpoints. Descargar desde http://wcf.netfx3.com/files/folders/encoders/entry3262.aspx. Creative Commons Add-in para Microsoft Office Microsoft y CC se han asociado con la finalidad de realizar una herramienta de licencia de copyright que permita una fácil adición de la información de licencia de CC para que se pueda trabajar con ella a través de MS Office. Disponible gratis en http://office.microsoft.com y de http://www.creativecommons.org. Nuevos planes para WinFS No habrá beta 2 de WinFS y no aparecerá en solitario. Se rumorea que quizá lo haga en 2007-2008 con Katmai, la nueva versión de SQL Server. Ver en: http://blogs.msdn.com/winfs. Liberada la edición CTP de SQL Server 2005 Everywhere Edition Es la próxima versión de SQL Server 2005 Mobile Edition. Más información en: http://www.microsoft.com/sql/ctp_sqleverywhere.mspx. dnm.noticias << dotNetManía El tema central del Borland Day 2006 ha sido la “Optimización del Desarrollo de Software” (Software Development Optimization – SDO) y los diferentes ponentes han demostrado diversas maneras de alcanzar este objetivo mediante casos reales y ejemplos de las mejores prácticas del desarrollo de software. Asimismo, y con el mismo objetivo, se han presentado nuevas soluciones específicas para el gobierno y la gestión de las TI, la gestión con calidad del ciclo de vida, la definición y gestión de requisitos y la gestión del cambio. Una de las temáticas más seguidas este año, ha sido CMMI (Capability Maturity Models Integration), donde Borland ha mostrado como sus implemen- 7 dnm.directo.eventos José Luis Balsera MEDC Europe 2006 Del 6 al 8 de junio se celebró en la ciudad francesa de Niza la Microsoft Mobile and Embedded DevCon 2006 Europe, la conferencia para desarrolladores de sistemas y aplicaciones para dispositivos móviles e incrustados que Microsoft organiza, en diversos lugares del mundo,para dar a conocer las novedades que se producen en este campo de la mano de los propios responsables de su diseño e implementación. El lema de este año fue “Avivar el conocimiento.Acelerar el desarrollo” << Las sesiones se agruparon en torno a 3 ejes: el desarrollo para José Luis Balsera es Ingeniero Senior de Software en Raona (www.raona.com), donde trabaja como desarrollador, arquitecto y formador en tecnologías .NET. José Luis está especializado en el desarrollo de aplicaciones móviles usando .NET Compact Framework y smart clients la plataforma Windows Embedded, el desarrollo de aplicaciones para Windows Mobile y la movilización de negocios usando tecnologías Microsoft. También se ofreció la posibilidad de “tocar” código mediante prácticas en laboratorio, bien siguiendo unos guiones, bien siguiendo las instrucciones de algún experto, sobre varios de los temas que se trataron durante las conferencias. Durante la sesión de presentación, Todd Warren, vicepresidente corporativo de la división de dispositivos móviles e incrustados, hizo un balance positivo de la evolución de la tecnología y del mercado anunciando que su grupo fue el de mayor crecimiento para la compañía de Redmond, con un incremento del 40% anual durante ocho trimestres consecutivos. Entre los casos de éxito comentados, todos pertenecientes a empresas europeas, apareció el despliegue de dispositivos basados en Windows Mobile que hizo Correos recientemente. Lo más destacable, aparte de las novedades que comentaremos a continuación, fue la hoja de ruta para el lanzamiento de las nuevas versiones de los sistemas: tanto los sistemas incrustados (CE y XP Embedded) como Windows Mobile tendrán ciclos de 18 a 24 meses, con entregas de Feature Packs intermedias que ofrecerán mejoras e incorporarán nuevas funcionalidades. Por ejemplo, este año aparecerá Windows CE 6.0 y el próximo año se lanzará un feature pack con las actualizaciones que se desarrollen en ese intervalo. Lo mismo sucederá con Windows Mobile, pero cabe destacar que las actualizaciones de este sistema coincidirán, además, con las de las herramientas para Visual Studio 2005. En sintonía con la planificación expuesta este año tocaba explicar, principalmente, novedades para sistemas incrustados. Como decíamos, se presentó la versión beta de Windows CE 6.0, que tiene previsto su lanzamiento definitivo durante el último trimestre de este año. En esta ocasión el sistema ha visto totalmente remodelado su núcleo para dar respuesta a las necesidades que ya se están planteando y, sobre todo, a las necesidades futuras. Por fin se ha podido superar el límite de los 32 procesos simultáneos y la restricción a 32 MB del espacio de memoria virtual de cada uno de ellos. Los nuevos límites se sitúan en 32.768 procesos y 2 GB de memoria sin un aumento notable de los requisitos del sistema (300 KB es ahora el tamaño mínimo, frente a los 200 KB en Windows CE 5.0), lo que no se debe a que se prevea que aparezcan dispositivos con tales requerimientos sino, como humorísticamente comentó Mike Hall, senior technical product manager de Windows Embedded, para poder soportar el proceso número 33 que insistentemente los desarrolladores les pedían. También ha habido cambios en la modularización del sistema. Ahora podrán ejecutarse controladores en el espacio del núcleo con la finalidad de disminuir el coste de los cambios de contexto, e incluso podrán tener acceso a la interfaz de usuario. Obviamente, también existirá la posibilidad de restringir controladores a un espacio de ejecución aislado, en contexto de usuario, para no perjudicar al resto del sistema. Otro cambio importante es el de la separación física entre el kernel y la capa que expone el hardware del dispositivo (OEM Adaptation Layer), lo que permitirá cambiar el hardware sin tener que modificar el diseño del sistema. Otras novedades destacables serán la mejora de los mecanismos de seguridad y el soporte para archivos y volúmenes grandes mediante el sistema exFAT. Por último, aunque no menos importante, la herramienta principal para el diseño de sistemas, el Platform Builder, se ha incorporado a Visual Studio 2005. Esto, además de permitir un trabajo más productivo con el catálogo de componentes, ha permitido incorporar herramientas gráficas para las tareas más comunes, introducir Intellisense en otras y aprovechar todas las características del entorno de Visual Studio, como puede ser el control de código fuente. << dnm.directo.eventos Todd Warren, Corporate Vice President Mobile and Embedded Devices Product Group sino que es interpretado. Microsoft orienta el sistema a situaciones que no requieren mucha capacidad de cálculo, aunque sí robustez y fiabilidad, sincronización de datos e interfaz gráfica de usuario rica pero con interacción limitada. Las primeras aplicaciones reales las veremos en los portátiles que soporten el SideShow de Windows Vista y en controles remotos para Windows Media Center. Las sesiones dedicadas al desarrollo de aplicaciones, tanto nativas como para .NET Framework, estuvieron claramente enfocadas a profundizar en las técnicas para la adaptación al dispositivo, mejorar el rendimiento y aprovechar mejor las Managed API introducidas con la versión 2 del Compact Se presentó el .NET Micro Framework como un CLR “bootable” Framework. Como novedad más destacable en este ámbito, el equipo de Patterns & Practices presentó la Software Factory for Mobile Clients, que consiste en un conjunto de aplicaciones de referencia, patrones, application blocks, how to’s, documentación, etc., que tienen por objetivo proporcionar un entorno de desarrollo y un conocimiento de buenas prácticas para el desarrollo de aplicaciones móviles. Entre los bloques reutilizables incluidos merece la pena mencionar el Mobile Composite UI (para construir interfaces de usuario modulares), el Data Subscription Block (para la sincronización de datos con SQL Server), el esto, una buena colaboración del equipo del .NET Micro Framework y toda la estrategia de la que supieron dotar a sus algoritmos, los participantes proporcionaron una buena diversión al público con sus “combates”. Al final, de entre los 14 equipos, los representantes de una empresa austriaca se alzaron con la victoria. El concurso puso prácticamente el broche final a 3 días de sesiones, charlas informales, ejercicios prácticos y demostraciones que los más de 450 asistentes y 27 expositores pudieron compartir en una conferencia bien organizada y que esperemos vuelva a Europa en próximas ocasiones. <<dotNetManía La otra estrella en el apartado de sistemas operativos fue el .NET Micro Framework. Lo que empezó siendo el mecanismo que controlaba los relojes tipo SPOT (MSN Direct) está evolucionando en un sistema operativo dirigido a pequeños dispositivos como sensores, actuadores, monitores corporales para la atención médica, automatización del hogar, controles remotos, etc. Durante la conferencia, se presentó como novedad que aún no ha alcanzado ni el estadio de beta, por lo cual no hay ninguna certeza sobre las características de la versión final, ni sobre cuándo estará disponible. Simplificando los términos, se habló del .NET Micro Framework como un CLR “bootable”, es decir, el CLR inicia el sistema, gestiona los procesos, las interrupciones, la memoria, etc.; incluso los controladores de dispositivos se pueden escribir en C#. Actualmente funciona sobre procesadores ARM7 y ARM9, con requerimientos tan bajos como 27MHz, 384KB de RAM y 1 MB de ROM. En realidad, el tamaño útil mínimo del sistema es de 250 KB de ROM y 70 KB de memoria RAM, sin necesidad de MMU. En cuanto a su funcionalidad, cabe destacar que, aparte de las características básicas de .NET (excepciones, delegates, garbage collection, etc.), cuenta con los espacios de nombres fundamentales de la biblioteca de clases, como pueden ser System.Collec tions, System.Threading o System.Reflec tion. En algunos casos se han hecho modificaciones en la implementación (p. ej., datos más compactados en System.Runtime.Se rialization) o se ha tenido que modificar ligeramente las interfaces de las clases. La principal diferencia con el resto de implementaciones del CLR es que, por razones de espacio, el código no se compila just-in-time Disconnected Service Agent (para la invocación de Web Services en escenarios de conexión intermitente) y el Orientation Aware Control (para la adaptación de la interfaz de usuario a los diversos formatos de pantalla existentes). La versión presentada, que ya está disponible en GotDotNet solo para Pocket PC, aún no es la definitiva aunque se espera que aparezca en unos dos meses. En el ámbito de acceso a datos, se presentó SQL Server Everywhere, la nueva edición de SQL Server para dispositivos móviles, que en esta ocasión vendrá acompañada por versiones compatibles para el entorno PC. Las sesiones contaron con una buena asistencia en general y bastante participación en los turnos de preguntas. Cabe destacar también la total colaboración de la mayoría de los conferenciantes en este aspecto. Las respuestas se pudieron buscar también en las charlas con los expertos que se organizaron en el pabellón de Microsoft. Por último, destacaremos la sesión más celebrada y divertida de las tres jornadas: la competición de los Sumo Robots. Los pequeños robots gobernados por el .NET Micro Framework se entregaron a los grupos de asistentes que los solicitaron el primer día. Éstos pudieron asistir a una sesión práctica que les proporcionó los conocimientos básicos para programarlos. Con 9 dnm.directo.eventos Francisco A. González Tech-Ed Boston 2006 Entre el 11 y el 16 de junio se celebró la decimocuarta edición de Microsoft Tech-Ed, esta vez, en Boston, en el estado de Massachussets, sede de las prestigiosas universidades Harvard y el MIT (Massachussets Institute of Technology). El Tech-Ed es el mayor evento a nivel mundial para desarrolladores de software de tecnologías Microsoft. << Con una asistencia excelente, más de 12.000 personas, pales empresas de la industria como HP, ORACLE, IBM, EMC2... La estrella de todo el evento ha sido el TLC (Technical Learning Centre). Estos miniespacios estaban formados por una serie de mesas de trabajo y stands con máquinas y software preinstalado para que cualquiera pudiera dirigirse a los líderes de desarrollo y managers de los distintos productos de Microsoft así como a MVP, autores de libros, y expertos reconocidos por Microsoft en la industria. Las sesiones estuvieron agrupadas en distintas tecnologías donde podemos destacar: • Inteligencia de Negocio: donde se trataron temas relacionados con SQL Server 2005 (Integration Services, Analysis Services y Reporting Services), Bussiness Scorecard Manager 2005, Office 2007, Excel y SharePoint Portal Server. • Sistemas Conectados: Las aplicaciones actualmente no pueden estar en el contexto de una sola máquina o proceso y deben comunicarse con ambientes heterogéneos, exponiendo la problemática que esto conlleva. Se vieron aplicaciones como Windows Communications Foundation, Windows Workflow Foundation, Windows CardSpace (WCS) (antes InfoCard), WSE, .NET Enterprise Services, MSMQ, .NET Remoting, System Microsoft SQL Server 2005. Transactions, ASP.NET Web Services, Implementation and Maintenance, de Solid BizTalk Server, Commerce Server, Host Quality Learning, uno de los MCTS Training Kit Integration Server. (en inglés) para preparar el examen 70-431, se • Desarrollo y Administración de presentó en el Tech-Ed de Boston de este año, Bases de Datos: Mostrando las nuecomo uno de los libros más vendidos. vas características de SQL Server 2005: rendimiento, seguridad, diseño, escalabilidad y productividad. SQL Server Microsoft y sus “diamantes” (MVP, partners, MCT, regional directors, etc…) mostraron la utilización de los productos al más alto nivel así como sus experiencias en la vida real. El show comenzó el domingo por la noche con la keynote, donde se lamentó la ausencia de Bill Gates o Steve Ballmer. Bob Muglia (Senior Vice President), Ray Ozzie (Chief Technical Officer) y Chris Capossella (Corporate Vice President) enfocaron principalmente en la necesidad de capacitar y reconocer a los profesionales de la informática. Con eslóganes como “Power to the pros” (poder para los profesionales), “Do more with more” (Haz más con más) y “People Ready” (personal preparado) se mostró el compromiso de Microsoft de capacitar a los profesionales con las herramientas necesarias para afrontar los problemas de ahora y del futuro. El glamour de la keynote lo ofreció la actriz de la serie norteamericana 24 Horas, Mary Lynn Rajskub que, con humor, continuó enfatizando la importancia del personal IT en las organizaciones. En total hubo más de 1.000 sesiones en sus distintas modalidades. Sesiones formales, grupos de discusión, desayunos y cenas de trabajo, laboratorios tutorizados y un sinfín de actividades. Alrededor de todas estas actividades estaba la feria con las princiFrancisco A. González Díaz trabaja como Ingeniero de Integración de Solid Quality Learning. Es Ingeniero Superior en Informática por la Universidad de Murcia. MCP en BizTalk Server. << dnm.directo.eventos 2005, ADO.NET, SQL Server 2005 Express y SQLCLR fueron de gran interés en esta edición del Tech-Ed. • Herramientas para desarrolladores: donde se abarcó el ciclo de desarrollo utilizando Visual Studio Team System. Las herramientas destacadas en este grupo fueron: Visual C#, Visual Basic, Visual Studio, Debugging, .NET Framework, 64-bit, CLR, Visual Studio Team System, Windows Form, Smart Clients y Windows Mobile 5.0. Novedades Durante el Tech-Ed fuimos testigos de bastantes novedades, no solo del anuncio de abandono del día a día, en el equipo de Microsoft, por parte de Bill Gates a mediados de 2008 dejando al mando a Steve Ballmer, sino también supimos que en los próximos 16 meses tendremos nuevas versiones del top 3 de los productos de Microsoft en rentabilidad y uso. Tendremos Office 2007, Windows Vista a principios de 2007 y en otoño de 2007 llegará Longhorn Server, el nuevo sistema operativo de servidor que reemplazará a Windows Server 2003. Otra de las novedades más reseñables es que Microsoft ha renombrado su software en el apartado de seguridad con un nuevo producto llamado Microsoft Forefront, que contiene Microsoft Forefront Client Security (actualmente Microsoft Antigen for Exchange), Microsoft Forefront Security for SharePoint (actualmente Microsoft Antigen for SharePoint), Microsoft Antigen for Instant Messenger y Microsoft Internet Security & Acceleration Server 2006 (servidor para la protección de amenazas por Internet en las organizaciones) Chris Capossela anunció la disponibilidad Exchange Server 2007 Beta 2 para finales de 2007. Alex Cobb anunció BizTalk Server 2006 R2 y un nuevo paquete de adaptadores que se presentarán próximamente. En cuanto a High Performance Computing (HPC), Microsoft presentó Computer Cluster Server 2003, que responde a la demanda para la ejecución de aplicaciones en paralelo o de gran consumo de recursos. Entre sus objetivos están las aplicaciones científicas que requieran grandes cálculos o el procesamiento de tareas de business intelligence. En los próximos 16 meses tendremos nuevas versiones del top 3 de los productos de Microsoft en rentabilidad y uso.Tendremos Office 2007,Windows Vista a principios de 2007 y en otoño de 2007 llegará Longhorn Server Además, los asistentes pudimos obtener la primera edición CTP del Visual Studio Team Edition for Database Professionals, un nuevo producto de la línea Team System (http://msdn.microsoft.com/vstudio/te amsystem/products/dbpro). Durante esta semana, Tech-Ed ha creado un lugar para el intercambio de conocimiento, anuncios y debates sobre tecnología, con una gran cantidad de personal de Microsoft y profesionales de todo el mundo en un ambiente internacional. Próxima cita: Tech-Ed Europe en Barcelona a principios de noviembre. Les mantendremos informados. Solid Quality Learning en el Tech-Ed de Boston En el TLC de SQL Server, con el eslogan “Always on Technologies”, Solid Quality Learning tuvo un papel destacado. Un gran conjunto de sus mentores impartió sesiones, demostraciones y presentó libros y proyectos junto con Microsoft. Además, tuvimos dos buenas noticias: la primera es que supimos que el Training Kit sobre SQL Server 2005 desarrollado por Solid Quality Learning y recién publicado está en la lista de más vendidos de Amazon; y la segunda es el reconocimiento a Mauro Sant’Anna, uno de los mentores de Solid Quality Learning, como regional director del año. <<dotNetManía Estas no fueron las únicas líneas, pues se trataron todos los productos de Microsoft relacionados con arquitectura, aplicaciones para negocios, Management and Operations, mensajería y movilidad, Microsoft Application Platform, Microsoft IT, Office System, seguridad, soluciones verticales para la industria, desarrollo Web, Windows Client, Windows Server Infrastructure, etc. Alejandro Leguizamo, mentor de Solid Quality Learning en uno de los ChalkTalk sobre minería de datos con SQL Server 2005 Analysis Services 11 dnm.directo.entrevistas Marino Posadas Entrevista a Arvindra Sehmi Nuestro entrevistado de hoy es la cabeza visible del Enterprise Team en Microsoft Corp’s Developer and Platform Evangelism Group en Europa, Oriente Medio y África (EMEA) y su trabajo se focaliza hacia la adopción de las mejores prácticas dentro de la comunidad de arquitectos de EMEA. << Antes de nada, a modo de presentación, ¿cuál es tu Marino Posadas es asesor técnico y redactor de dotNetManía, MVP de C# y formador de Alhambra-Eidos labor actual en Microsoft? Pertenezco al grupo de Desarrollo y Plataforma de Microsoft para Europa, Oriente Medio y África, y tengo a mi cargo el Enterprise Team de Arquitectura. Soy responsable de dos tipos principales de arquitectos: los de soluciones y los de infraestructura. También realizamos labores de marketing y soy además el encargado de suministrar asistencia a nuestros “partners” y asociados de desarrollo respecto a cuestiones de arquitectura. Aparte de eventos de gran calado, como puedan ser los IT Forums o el Tech-Ed, promovemos acciones del tipo workshop, o Deep-Dives (cursos de inmersión profunda), sobre tecnologías fundamentales, generalmente en la línea del producto que aparece a corto/medio plazo. De igual forma, en ocasiones asesoramos a clientes en formato “uno a uno”, esto es con asesorías personalizadas sobre desarrollos puntuales, para ofrecerles diseño de soluciones y revisión de estructuras arquitectónicas. Paulatinamente, las tecnologías vinculadas con los servicios Web han ido siendo aceptadas e implantadas en soluciones actuales, pero la impresión es que –todavíaSOA como arquitectura no es lo suficientemente compren- dida y adoptada. ¿Cuál sería tu consejo a este respecto? La primera cuestión sería separar los dos conceptos, al menos inicialmente, aunque pertenezcan al mismo grupo conceptual. Respecto a los servicios Web, tenemos claro que son la tecnología que va a servir de base a todo lo que signifique interoperabilidad. Y, además, incluyen todo lo que suministran los Web Services Enhancements, ahora en su versión 3.0. En Vista y Longhorn, esta tecnología está presente dentro de WCF (antes Indigo), que incluye estos estándares vinculados a los servicios Web. Tenemos un modelo de programación bastante sofis- Marino Posadas y Arvindra Sehmi << dnm.directo.entrevistas ¿Puede Microsoft ofrecerte una guía de construcción, una asesoría puntual, para ayudarte a la resolución de esos problemas arquitectónicos? Totalmente. Esa es una de las cosas que hace mi equipo <<dotNetManía ticado, que es la base de Indigo, pero no nos olvidamos de los niveles más inferiores y sus posibilidades. Ahora bien, todo esto no significa sino que la orientación a servicios es una de las posibilidades arquitectónicas que las nuevas plataformas van a ofrecer, pero ni mucho menos la única. Si hablamos genéricamente de una orientación a servicios (una arquitectura SOA), existen varios principios que deben de cumplirse, uno de los cuales consiste en identificar exactamente los límites de la arquitectura de negocio, los contratos de negocio necesarios para su funcionamiento, etc. Y nunca hablando de productos, sino simplemente de estructuras arquitectónicas del software. El paso siguiente es hacer corresponder esa arquitectura con una implementación concreta, donde sí intervendrán productos concretos. Si eso se hace utilizando herramientas vinculadas con .NET, puedes usar tecnologías punteras, como BizTalk o SharePoint, por ejemplo, y tienes muchas otras posibilidades… Como la de construirlo tú mismo si conoces suficientemente bien los principios en que se basa… Exactamente. Ahora bien, ¿puede Microsoft ofrecerte una guía de construcción, una asesoría puntual, para ayudarte a la resolución de esos problemas arquitectónicos? Totalmente. Esa es una de las cosas que hace mi equipo. Así pues, Indigo dará toda la infraestructura para diversas soluciones de comunicación. Pero eso nos lleva a una pregunta sobre remoting. ¿Se le supone obsoleto, a la vista de las novedades venideras? No realmente. Todavía va a estar ahí, y nos ha ayudado a comprender mucho mejor los problemas vinculados a las arquitecturas distribuidas. Lo que sucede es que las restricciones de remoting (su propia naturaleza) no lo capacitan para ciertas soluciones distribuidas de naturaleza heterogénea, y además no Arvindra Sehmi cumple con ciertos principios de la orientación a servicios, especialmente en lo referente a los contratos y el formato de intercambio basado en mensajes. ¿Sería adecuado decir que si tienes totalmente el control del dominio de instalación, la opción de remoting es perfectamente válida y de buen rendimiento, pero si no es así la opción mejor serían los servicios Web? Te diré que –de hecho- esa es exactamente la forma en que lo estamos recomendando. Y además, remoting va a formar parte integrante del modelo de programación de Indigo. Todavía es muy consistente, si te encuentras dentro de estos términos. Otra cuestión que surge vinculada con la adopción de estas arquitecturas es el rendimiento (o la posible penalización asociada a su implantación). ¿Qué puedes decirnos al respecto? El rendimiento está asociado muchas veces con el mensaje intercambiado; con su formato después de la seriación. De ahí que –tanto en Indigo como en .NET 2.0- hayamos optimizado notablemente la forma en que se serian los mensajes XML para favorecer este aspecto. De hecho, ya hay comparativas de rendimiento muy favorables respecto a la 13 << dnm.directo.entrevistas <<dotNetManía Respecto a los servicios Web, tenemos claro que son la tecnología que va a servir de base a todo lo que signifique interoperabilidad.Y, además, incluyen todo lo que suministran los Web Services Enhancements, ahora en su versión 3.0. En Vista y Longhorn, esta tecnología está presente dentro de WCF (antes Indigo), que incluye estos estándares vinculados a los servicios Web 14 utilización de servicios Web. Respecto al protocolo HTTP, resulta muy apropiado para una semántica preguntarespuesta. Se pueden utilizar otros transportes, como TCP/IP, MSMQ, SMTP o incluso algún otro tipo. Pero la importancia de disponer de distintos transportes es que podemos seleccionar distintos modelos como el asincrónico unidireccional (garantizado y fiable), o puedes seleccionar un mecanismo bidireccional y utilizarlo junto a un estándar de servicios extendidos como WS-Reliable Messaging o WS-Security. Además, la gente está empezando a construir aplicaciones cada vez más y más complejas y el ajuste de rendimiento para estas aplicaciones se vuelve un asunto crucial en la implantación. Y a veces el problema está en que no acaban de comprender las implicaciones que la elección de una determinada arquitectura tiene en ese rendimiento. Y por otro lado, suministramos mecanismos para realizar las cosas de forma muy sencilla, de manera que también se corre el riesgo de que el desarrollador adopte el principio del mínimo esfuerzo sin analizar suficientemente las consecuencias de la adopción de una determinada técnica. Por eso suministramos guías y documentación (un montón de documentación, de hecho…). Otra cuestión que vincula al desarrollo con la arquitectura y la facilidad de uso de un programa tiene que ver con el modelo de propone Vista para la construcción de aplicaciones. O sea, ¿Cómo es posible unificar los modelos de aplicación Windows y Web, tan distantes en un principio? Básicamente porque vamos a contar con los medios para describir cómo va a ser la interfaz de usuario mediante XAML. Tú suministras esa descripción de la IU a un motor de interpretación. Si éste es de tipo Web, obtienes páginas Web, si se trata de un intérprete de Windows, obtienes aplicaciones Windows Forms. XAML es –realmente– una forma en la que puedes seriar objetos. Puedes entenderlo como una generalización de la seriación de objetos para la interfaz de usuario. ¿Crees que, quizá, la falta de conocimiento profundo de cuál es la forma correcta de implantar arquitecturas en capas constituye la principal barrera para su adopción masiva? Sin duda. Especialmente, de la forma de organizar la comunicación entre capas y la forma es que esta comunicación tiene diferentes impactos tanto en el desarrollo como en el rendimiento final de la aplicación. Se necesita comprender bien la arquitectura completa end-to-end, incluyendo las restricciones de implantación. En otro orden de cosas, hemos visto que Microsoft ha anunciado una nueva titulación relacionada con la arquitectura de aplicaciones. ¿En qué va a consistir? Hemos estado recogiendo la opinión de nuestros partners a ese respecto para acotar exactamente el alcance que debería de tener. E incluso hemos hablado con grandes partners de cara una unificación de criterios (Intel, Lotus, IBM, HP, etc.). De hecho, hemos establecido un sistema de mentoring, de forma que cualquiera que desee certificarse pueda contar con ese sistema en un período de 12 a 18 meses que consideramos el mínimo imprescindible antes de abordar las pruebas finales. Será un requisito enviar una serie de documentación para la certificación, ya que es difícil evaluar este tipo de conocimiento simplemente con sistemas on line. Es algo que recuerda a la defensa de una tesis que tú realizarás ante un grupo de expertos en arquitectura, para evaluar tus conocimientos. Y finalmente, tus recomendaciones para los que quieran abordar estas tecnologías… Pasar por una fase previa de estudio y pruebas similar a la que recomendamos para los exámenes que describía anteriormente. Libros y artículos sobre buenas prácticas, disponibles en MSDN, asistencia a foros, simposios y eventos sobre arquitectura, asimilación de patrones de diseño y su implantación en .NET Framework, y analizar aplicaciones ya resueltas y disponibles, tales como Global Bank Infrastructure, donde se explican todos estos términos en fases y desde diferentes perspectivas. dnm.asp.net José M.Alarcón WebParts en ASP.NET 2.0 (y III) Con este artículo finalizamos la serie sobre WebParts comenzada hace dos números en dotNetManía. En él trataremos algunos conceptos avanzados sobre bloques personalizables que nos permitirán llegar a un buen nivel en el desarrollo de este tipo de aplicaciones.En concreto,veremos cómo intercambiar información entre ellos y cómo exportarlos para su reutilización. << Con lo visto hasta ahora ya estamos en condiciones de construir complejas aplicaciones Web personalizables que eran impensables hasta la aparición de la versión 2.0 de ASP.NET. Sin embargo, hay ciertas funcionalidades que nos resultarían muy convenientes y que todavía no sabemos hacer: por ejemplo, establecer una comunicación entre los bloques. El hecho de poder separar nuestra aplicación en bloques de funcionalidad que luego se pueden distribuir a voluntad dentro de una o varias páginas es algo muy interesante. Sin embargo, en cuanto empecemos a usarlos en aplicaciones reales nos daremos cuenta de que no basta con tener esto. En la mayor parte de los casos no triviales veremos que es necesario que los bloques existentes, independientemente de su ubicación, se comuniquen entre sí. Por ejemplo, podemos disponer de un bloque que muestre una lista de productos y otro que sirva para ver un informe de ventas de esos productos. Si no podemos hacer que lo escogido en el primero influya en los resultados que muestra el otro, los bloques no nos valdrán de mucho. Comunicación entre bloques José Manuel Alarcón es redactor de dotNetManía. Es ingeniero industrial y especialista en consultoría de empresa. Ha escrito varios libros, y ha publicado más de doscientos artículos sobre informática e ingeniería en revistas especializadas.Visita su blog en www.jasoft.org. El ejemplo anterior es solo uno más de los muchos que se nos pueden ocurrir, pero evidencia la necesidad de varias funcionalidades para conseguir nuestro objetivo. En primer lugar, necesitamos alguna forma de que la información fluya entre los bloques. Pero no llega solo con eso, ya que tenemos que asegurarnos de que solo los bloques compatibles sean capaces de comunicarse (la información del producto seleccionado puede que no signifique nada para otros bloques que haya en la misma página). Finalmente, debemos encontrar un método estándar que permita relacionar desde la interfaz de usuario a los bloques compatibles entre sí, independientemente del tipo de datos que intercambien. Para construir la comunicación entre dos bloques debemos hacer lo siguiente: 1. Decidir qué datos vamos a intercambiar, cuál es su tipo, su formato y su cantidad. Definir una interfaz que permita intercambiar dicha información. 2. Definir uno de los controles como proveedor. 3. Definir otro (u otros) como consumidor(es). 4. En caso de querer una conexión estática, hay que definir ésta. 5. En caso de necesitar conexiones dinámicas (decididas por el usuario en tiempo de ejecución), es necesario usar un control especial para definirlas. Vamos a crear un ejemplo simple que ilustre todo el proceso. Crearemos dos WebParts mediante controles de usuario. En uno de ellos habrá un campo de texto cuyo contenido será transmitido al otro bloque, de modo que siempre que haya alguna variación en el primero se vea reflejada en el segundo. Dado que los principios básicos de comunicación entre WebParts son los mismos, le resultará fácil reconstruir el ejemplo para comunicar cualquier otro tipo de información, incluso más compleja formada por diversos miembros. Primer paso: la interfaz de comunicación En este caso lo que se transmitirá desde un bloque al otro es simplemente texto (el contenido del cuadro de texto del control origen de datos). Podría ser el identificador de un producto, o una estructura compleja que represente varios atributos de un cliente, por ejemplo. En cualquiera de los casos, lo que << dnm.asp.net debemos tener muy claro antes de hacer nada es qué se va a transmitir, para luego ser consecuentes en la definición de toda la arquitectura. En el caso que nos ocupa, dado que sólo es texto, podemos definir en la carpeta App_Code (para que esté al alcance de toda la aplicación) una interfaz como ésta llamada ITextTransfer: Partial Class Proveedor Inherits System.Web.UI.UserControl Implements ITextTransfer Public Function Texto() As String Implements ITextTransfer.Texto Return TextBox1.Text End Function End Class Fuente 2 Más sencilla – imposible. Su único miembro es un método que devuelve una cadena. En lugar de una función, podríamos haber definido también una propiedad de solo lectura. Si lo que intercambiamos es algo más complejo que una cadena, bastará con definir una clase o estructura en alguna parte y devolverla a través de la interfaz. Esta interfaz es la que se pasará entre ambos extremos de la conexión. Segundo paso: definición de la fuente o proveedor Ahora vamos a crear un control que se encargará de enviar datos a los posibles consumidores que definamos. Agregue al proyecto un nuevo control de usuario llamado Proveedor.ascx y agregue sobre su superficie un control TextBox y un botón. No es necesario introducir código alguno para responder a los eventos de estos dos elementos. El cuadro de texto será un mero contenedor de información y el botón lo usaremos únicamente para forzar el envío de datos al servidor (es decir, para forzar un postback): <asp:TextBox ID=”TextBox1” MaxLength=”16” Runat=”server” /> <asp:Button ID=”Button1” Text=”Enviar datos” Runat=”server” /> Fuente 1 Como proveedor de la información textual que nos interesa, este control deberá implementar un método que proporcione acceso a un objeto que implemente la interfaz que hemos acordado en el paso anterior, el cual será “enviado” a los consumidores con los que se comunique. El objeto que implementa esta interfaz puede ser una clase definida para la ocasión o, más comúnmente, puede ser el propio WebPart, que en ese caso deberá implementar la interfaz. Es decir, en nuestro ejemplo, deberá definir un método Texto tal y como indica ésta en el fuente 2. Lo único que hace la función es devolver la información que nos interesa, o sea, el contenido del cuadro de texto. Además, como ya he dicho, es necesario indicar a la infraestructura de WebParts cómo se realizará la comunicación y que éste es un bloque que proveerá de datos a otros. Esto se consigue definiendo un método cualquiera que devuelva la interfaz de comunicación y marcándolo como proveedor de origen de conexiones, así: <ConnectionProvider(“Proveedor”, “ProveedorID”)> _ Public Function GetTextTransferInterface() As ITextTransfer Return Me End Function Fuente 3 En este código vemos la definición de un método que lo único que hace es devolver una referencia al propio control, que será el origen de la conexión. El método se puede llamar como queramos. Finalmente, y lo más importante, el atributo ConnectionProvider sirve para indicar a la infraestructura de WebParts que este método actúa como origen de una conexión entre bloques, e indicamos como atributos la descripción y el identificador único que le otorgamos a dicho origen. Esto es tal vez lo más complicado de entender de todo el proceso, así que medítelo un rato antes de continuar leyendo. En cualquier caso, como se ve en el fragmento anterior, si bien es algo complejo conceptualmente es muy fácil de implementar en la práctica. Tercer paso: definir un consumidor de datos La construcción del consumidor de datos sí que es realmente sencilla. Lo único que debemos hacer es definir un método que reciba como parámetro la interfaz de intercambio de datos que hemos decidido antes y decorarlo con un atributo. Añada un control de usuario al proyecto y llámelo Consumidor.aspx. Arrastre sobre su superficie una etiqueta de texto. En ella NOTA mostraremos el texto que emite el proveedor del paso En el anterior artículo de esta serie se afiranterior. maba que sólo se pueden crear verbos perEn la vista de código sonalizados al definir WebParts puros, pero fuente del control defino en controles de usuario. En realidad sí na un método para asiges posible implementando la interfaz nar el contenido de la IWebActionable. Muchas gracias a Juan Luis Ceada por apuntar esta posibilidad. etiqueta como en el fuente 4. <<dotNetManía Public Interface ITextTransfer Function Texto() As String End Interface 17 << dnm.asp.net <ConnectionConsumer(“Consumidor”, “ConsumidorID”)> _ Public Sub GetTextTransferInterface(_ ByVal proveedor As ITextTransfer) Label1.Text = proveedor.Texto() End Sub Fuente 4 El control no necesita implementar la interfaz, ya que sólo la consume. Basta con definir un método similar a éste en el que el único parámetro es un objeto que implementa la interfaz de intercambio de datos y que está decorado con un atributo ConnectionConsumer que indica a la infraestructura de WebParts que se trata de un punto final en una conexión, especificando su descripción y un identificador único. Dentro del método el código es muy sencillo ya que tenemos una referencia al control origen de datos de la conexión, y sólo tenemos que llamar al método Texto de la interfaz para obtener la cadena que está contenida dentro de su cuadro de texto. Este método será llamado de forma automática por parte de la infraestructura de WebParts siempre que sea necesario refrescar los contenidos de la conexión, por lo que nuestro bloque no tiene que preocuparse de nada más. Si en lugar de usar controles de usuario hubiésemos implementado un control WebPart real, la forma de proceder sería exactamente la misma. Cuarto paso: conexiones estáticas <<dotNetManía Una vez que hemos definido correctamente el conducto de paso y los dos extremos de la conexión, sólo resta conectarlos entre sí. La forma más sencilla de hacerlo es definir una conexión en tiempo de diseño entre un control fuente y un control consumidor. Es el control WebPartManager, encargado de controlar toda la lógica de la página, el que nos facilita los medios necesarios. 18 Figura 1 Arrastre un ejemplar de cada control que acabamos de crear a sendas WebPartZone de la página de ejemplo. Ahora seleccione el control WebPartManager1 y en sus propiedades pulse el botón de la propiedad StaticConnections, como se ilustra en la figura 1. En el diálogo que aparece solo tendremos que agregar un nuevo elemento y establecer el nombre de los controles que queremos conectar usando las propiedades ProviderID y ConsumerID para la fuente y el sumidero de información respectivamente. Como es obvio, estos controles deben haber sido definidos con la función correspondiente y deben usar la misma interfaz de comunicación. Si no fuese así, se produciría un error nada más ejecutar la página. Como resultado de haber usado este diálogo se incluye un elemento WebPartConnection en las etiquetas de la página (figura 2). Figura 2 Quinto paso: conexiones dinámicas Es probable que el establecimiento de conexiones estáticas sea el más interesante en la mayor parte de las situaciones, ya que no podemos esperar que un usuario medio tenga la capacidad (o más bien el interés) de definir sus propias conexiones entre bloques. Aún así, para cierto tipo de aplicaciones con usuarios más avanzados sí puede resultar de útil permitir que sea el propio usuario el que defina de qué forma quiere conectar unos elementos con otros. Esto es especialmente cierto cuando un mismo control de origen puede actuar como fuente para varios controles sumidero, cada uno especializado en ofrecer determinada información a partir de los datos facilitados por el primero. Por ejemplo, imaginemos una típica página de cuadro de mandos para ejecutivos en la que nuestros usuarios escogen lo que necesitan ver. Podemos definir ciertos controles proveedores que listen los productos y regiones en las que actúa nuestra empresa, así como otro para ofrecer los años de actividad para los que existen datos. Si construimos diversos controles sumidero que pueden enlazarse a todas estas fuentes (incluso a varias a la vez) para mostrar informes, gráficas de ventas, etc., ofreceremos una potente herramienta para consulta de información en la que cada uno de nuestros usuarios será capaz de ver exactamente lo que necesita. Sólo tendrán que arrastrar los controles “filtro” (orígenes) y los visualizadores en los que tengan interés y, en cuanto los enlacen, podrán navegar por la información de la manera que deseen y con la distribución en pantalla que les resulte más cómoda. << dnm.asp.net Figura 3 Figura 5 Figura 4 En situaciones como ésta es cuando necesitamos las conexiones dinámicas. En realidad, es también muy sencillo obtener esta funcionalidad. Basta con hacer uso del control ConnectionsZone disponible en la barra de herramientas de “Elementos Web en Visual Web Developer” (figura 3). Arrastre uno de estos a la columna derecha de la tabla que hemos estado usando en nuestros ejemplos. En la figura 4 podemos ver el aspecto que tiene sobre la superficie de diseño. En el control de catálogo añada los dos controles (la fuente y el sumidero) que acabamos de crear para que estén disponibles en la página. Por fin, añada un último control LinkButton para pasar al modo de conexión del WebPartManager. En su propiedad Text escriba “Conectar bloques”, y como resultado de su pulsación use el código del fuente 5. Al pasar a modo de conexión veremos que aquellos bloques que son fuente o sumidero de datos disponen de una opción Figura 6 Fuente 5 al paso final en el que se muestra el resultado de la operación. Una vez establecida la conexión, vamos a probarla. En el control origen introduzca una frase cualquiera en el campo de texto y pulse el botón para provocar un postback al servidor. A partir de ese momento, la frase aparecerá reflejada en el control sumidero en todo momento, manteniéndose sincronizado el contenido de ambos entre los postbacks (figura 6). Exportación de WebParts Si disponemos de un WebPart complejo, que ofrece muchas propiedades para configurar o las que tiene son complicadas, será interesante brindar la posibilidad de guardar sus ajustes para reutilizarlos. Así podremos hacer un uso posterior en el mismo portal o incluso llevárnoslo a otro portal que disponga del mismo control. De hecho, éste no tiene ni por qué ser el mismo, ya que mientras se llame igual y posea propiedades con el mismo nombre y tipo será compatible la <<dotNetManía nueva en su menú desplegable de acciones: “Conectar”. Al elegirla, aparece el diálogo de creación de conexiones en la página. Éste va mostrando diversos aspectos a medida que se establece la conexión. La figura 5 ilustra los tres pasos necesarios para crear una conexión dinámica y el aspecto del control en cada uno de ellos. El paso 1 aparece tras elegir el método “Conectar” en el menú desplegable del control origen de datos. Simplemente insta al usuario a crear una nueva conexión para éste pulsando sobre el enlace de la parte superior. También informa de las conexiones existentes con origen en éste, de haber alguna anterior. A continuación, se permite seleccionar el control sumidero o destino de la conexión, para lo cual debemos elegirlo de una lista desplegable. En ésta sólo se muestran los controles que estén presentes en la página y que implementen la interProtected Sub LinkButton5_Click(ByVal sender As Object, faz común de comunicaByVal e As System.EventArgs) Handles LinkButton5.Click ción que tiene el control WebPartManager1.DisplayMode = WebPartManager.ConnectDisplayMode origen. Una vez elegido el End Sub control se pulsa sobre el botón “Conectar” y se llega 19 << dnm.asp.net Figura 7 información transferida, puesto que los ajustes se hacen mediante reflexión y no con tipos estrictos. Para que un bloque pueda exportar sus propiedades hay que indicar esta necesidad en el constructor de la clase, usando su propiedad ExportMode. En la figura 7 se observan los tres posibles valores que tiene esta propiedad: exportarlo todo, no exportar nada (valor por defecto) o exportar sólo aquello que no sea confidencial. Normalmente no tendremos propiedades confidenciales, pero es posible que en ocasiones pudieran hacernos falta. Si, por ejemplo, una de las propiedades del WebPart es la clave que éste necesita para conectarse a un origen de datos y obtener sus contenidos, no deberíamos permitir que se exporte y esté al alcance de cualquiera. Para marcar una propiedad como confidencial debemos usar una de las sobrecargas del atributo Personalizable ya visto, cuyo segundo argumento es precisamente un booleano para indicarlo: <<dotNetManía Personalizable( PersonalizationScope.Shared, False) 20 No basta con marcar un bloque como exportable. Se debe habilitar explícitamente la capacidad de exportación de la infraestructura desde el archivo de configuración web.config usando el atributo enableExport del nodo <webParts> y estableciéndolo como verdadero. Al hacer todo esto, el control ofrecerá una opción de exportación en su menú desplegable. Al elegirla, se creará un archivo con el mismo nombre que el título del control y extensión .WebPart que podremos almacenar en disco. Se trata de un archivo XML en el que aparece el nombre del tipo del control y una serie de nodos con las propiedades del control y sus valores en el momento de la exportación. Por ejemplo, vea el fuente 6. Este es el XML resultante de exportar el control que creamos antes y que sirve para mostrar el nombre de usuario de Windows actual. La mayor parte de las para las propiedades, forzar la carga de ciertos controles potencialmente dañinos, o saturar la memoria del servidor forzando la carga de muchos controles. Por ello la importación de WebParts debería estar per- <?xml version=”1.0” encoding=”utf-8”?> <webParts> <webPart xmlns=”http://schemas.microsoft.com/WebPart/v3”> <metaData> <type name=”Jose.WebParts.UsuarioWebpart” /> <importErrorMessage>No se puede importar este elemento Web.</importErrorMessage> </metaData> <data> <properties> <property name=”AllowClose” type=”bool”>False</property> <property name=”Width” type=”unit” /> <property name=”AllowMinimize” type=”bool”>True</property> <property name=”ExportMode” type=”exportmode”>All</property> <property name=”AllowConnect” type=”bool”>True</property> <property name=”ChromeType” type=”chrometype”>Default</property> <property name=”TitleIconImageUrl” type=”string” /> <property name=”Description” type=”string” /> <property name=”Hidden” type=”bool”>False</property> <property name=”TitleUrl” type=”string” /> <property name=”AllowEdit” type=”bool”>True</property> <property name=”Height” type=”unit” /> <property name=”HelpUrl” type=”string” /> <property name=”Title” type=”string”>Usuario Windows actual</property> <property name=”CatalogIconImageUrl” type=”string” /> <property name=”Direction” type=”direction”>NotSet</property> <property name=”ChromeState” type=”chromestate”>Normal</property> <property name=”AllowZoneChange” type=”bool”>True</property> <property name=”AllowHide” type=”bool”>False</property> <property name=”HelpMode” type=”helpmode”>Navigate</property> <property name=”Mayusculas” type=”bool”>False</property> </properties> </data> </webPart> </webParts> Fuente 6 propiedades son las estándar para un WebPart, y además serializa también nuestra propiedad Mayusculas (al final). Todo esto está muy bien pero, ¿de qué vale exportar estos valores si no podemos importarlos? Vamos a ver cómo se hace, ya que es también muy sencillo. Basta con añadir un control ImportCatalogPart a la zona de catálogos de nuestra página. Al hacerlo, cuando pasemos a modo catálogo se nos ofrece la posibilidad de buscar un archivo con extensión .WebPart en el disco duro y subirlo a la Web. Al recibirlo, se trata de instanciar un objeto del tipo indicado en el archivo que herede de WebPart, y se ajustan sus propiedades. Así de sencillo. Obviamente, esta característica tiene implicaciones de seguridad importantes, puesto que un usuario malicioso puede crear archivos XML con valores inadecuados mitida únicamente a usuarios de alto rango, y aún así las propiedades de los controles deberían hacer una buena validación de los datos que les lleguen. En resumen A lo largo de estas tres entregas hemos estudiado toda la infraestructura de WebParts que ofrece ASP.NET 2.0. Se trata de una característica muy espectacular en esta versión y que abre todo un mundo de posibilidades para el programador que sepa sacarle partido. Hemos aprendido prácticamente todo lo que necesita saber para hacer aplicaciones complejas con la infraestructura de bloques, desde los fundamentos hasta las características más avanzadas. Espero que estos contenidos le hayan resultado útiles y provechosos. dnm.futuro Octavio Hernández Lo que nos traerá Orcas: VB 9.0 y LINQ Este artículo presenta las novedades que incluirá (probablemente con algunas variaciones) Visual Basic 9.0, incluyendo la sintaxis de las expresiones de consulta, que constituyen el principal reflejo en el lenguaje de la tecnología LINQ, y las extensiones para el soporte directo de XML. << Ya en una entrega anterior hemos presentado los fundamentos de LINQ (Language INtegrated Query), una combinación de extensiones al lenguaje y librerías de código manejado que permite expresar de una manera uniforme consultas sobre colecciones de datos provenientes de las más diversas fuentes: objetos en memoria, bases de datos relacionales o documentos XML, entre otros. Si bien los ejemplos que acompañaban a ese artículo estaban codificados en C#, entonces mencionamos que la tecnología LINQ estaría disponible no solo para los programadores de este lenguaje, sino que Visual Basic 9.0 (la versión del lenguaje que implementará “Orcas”) también ofrecería las mismas facilidades (e incluso algunas más, podríamos añadir ahora) para expresar directamente con los recursos del lenguaje colecciones de datos de diferente naturaleza y consultas sobre ellas. Requisitos preliminares Octavio Hernández es colaborador habitual de dotNetManía, Ingeniero en Informática de Sistemas y MVP de C#. Para probar los ejemplos de código que acompañan al artículo, el lector deberá instalar la presentación preliminar de LINQ, disponible en la URL que se indica en la bibliografía [1]. El software de mayo de 2006 incluye versiones previas de los compiladores de C# 3.0 y VB 9.0, varios ensamblados en los que se implementan las novedades y la tecnología LINQ, y un conjunto de plantillas de proyectos que se muestra en la figura 1. Adicionalmente, se ofrece un directorio de ejemplos de código y otro de documentación. Recomendamos especialmente la lectura de los documentos incluidos en el directorio Docs, así como el análisis y ejecución de los ejemplos. Los ejemplos que se presentan en este artículo se apoyan en la clase Persona de entregas anteriores. Aunque está claro que en principio no habría sido necesario (uno de los objetivos centrales de .NET es precisamente facilitar la interacción de módulos desarrollados en diferentes lenguajes), el fuente 1 presen- Figura 1. Plantillas de proyectos LINQ en Visual Basic ta una versión de la clase implementada en Visual Basic 9.0. Nuevas características “básicas” de VB 9.0 En este punto introduciremos las novedades de más bajo nivel que incluye Visual Basic 9.0 y que en mayor o menor medida sirven como fundamento o pueden ser utilizadas en combinación con aquellas que directamente están relacionadas con LINQ y sus tecnologías “derivadas”. Estas novedades “básicas” son las siguientes: • Determinación implícita del tipo de variables locales. • Inicializadores de objetos y colecciones. • Tipos anónimos. • Tipos anulables*. • Métodos extensores. • Interfaces dinámicas. • Identificadores dinámicos*. • Relajación de delegados. Las características marcadas con * no están aún implementadas o lo están solo parcialmente en la versión actual de la presentación preliminar de LINQ para VB. Determinación implícita del tipo de las variables locales En Visual Basic 9.0 será posible obviar la especificación del tipo de una variable local que se vaya a inicializar explícitamente. El compilador determinará de forma implícita el tipo de la variable en base al tipo de la expresión de inicialización. Por ejemplo, en el fragmento de código que se muestra en el fuente 2 el compilador infie- Public Enum SexoPersona Mujer = 0 Varón = 1 End Enum Public Class Persona ‘ campos Private _nombre As String = Nothing ‘ en VB 9.0 se podrá utilizar: ‘ Private _sexo As SexoPersona? = Nothing Private _sexo As Nullable(Of SexoPersona) = Nothing Private _fechaNac As Nullable(Of DateTime) = Nothing ‘ constructores Public Sub New() ‘ nada End Sub Public Sub New(ByVal nombre As String, ByVal sexo As SexoPersona) MyClass.New() _nombre = nombre _sexo = sexo End Sub Public Sub New(ByVal nombre As String, ByVal sexo As SexoPersona, _ ByVal fechaNac As DateTime) MyClass.New(nombre, sexo) _fechaNac = fechaNac End Sub ‘ propiedades Public Property Nombre() As String Get Return _nombre End Get Set(ByVal value As String) _nombre = value.ToUpper() End Set End Property Public Property Sexo() As Nullable(Of SexoPersona) Get Return _sexo End Get Set(ByVal value As Nullable(Of SexoPersona)) _sexo = value End Set End Property Public Property FechaNac() As Nullable(Of DateTime) Get Return _fechaNac End Get Set(ByVal value As Nullable(Of DateTime)) _fechaNac = value End Set End Property Public ReadOnly Property Edad() As Nullable(Of Integer) Get If _fechaNac.HasValue Then Return Convert.ToInt32(DateTime.Today. _ Subtract(FechaNac.Value).TotalDays / 365.25) Else Return Nothing End If End Get End Property ‘ métodos Public Overrides Function ToString() As String Dim s As String = “” If _nombre Is Nothing Then s &= “ANONIMO” Else s &= _nombre If _sexo.HasValue Then If _sexo.Value = SexoPersona.Mujer Then s &= “ (M)” Else s &= “ (V)” End If End If If _fechaNac.HasValue Then s &= “ (“ & Edad.ToString() & “)” Return s End Function End Class Fuente 1. Clase Persona utilizada en los ejemplos <<dotNetManía << dnm.futuro 23 << dnm.futuro re que la variable N es de tipo Integer por el tipo de la constante que se le intenta asignar. Este mecanismo puede utilizarse también en otras construcciones del lenguaje, como los bucles For..Next y For Each..Next. Sub Ejemplo1() ‘ Declaración implícita del tipo de la variable Dim N = 2 ‘ equivale a Dim N As Integer = 2 piedades o campos del objeto se especifican mediante un inicializador de objeto. Para que este mecanismo funcione es requisito indispensable que la clase ofrezca un constructor sin argumentos, como ocurre en el caso de las clases que no tienen un constructor definido explícitamente y de aquellas que son sintetizadas artificialmente por el compilador (“tipos anónimos”, que presentaremos a continuación). b) Inicializadores de colecciones ‘ Declaración implícita del tipo de la variable ‘ y los elementos del array Dim Arr = {1, 2, 3, 4, 5, 6, 7, 8, 9} ‘ También en bucles for y foreach For Dim k = 1 To 10 Console.WriteLine(k) Next For Each Dim i In Arr Console.WriteLine(i) Next ‘ Enlace tardío con Strict On Dim M As Object M = 27 M = “abc” End Sub Fuente 2. Determinación implícita del tipo de las variables Independientemente del estado de la opción Option Strict, el acceso a las variables cuyo tipo es inferido por el compilador siempre se realiza mediante enlace temprano. De hecho, cuando esta opción esté en On (lo que vienen recomendando desde hace mucho nuestros columnistas - vea por ejemplo [3]), para utilizar el enlace tardío sobre una variable en VB 9.0 se deberá declararla explícitamente como As Object . Este cambio hacia una mayor utilización en situaciones “normales” del fuerte control de tipos hace posibles nuevas aplicaciones del enlace tardío que presentaremos más adelante en este artículo. Inicializadores de objetos y colecciones VB 9.0 añadirá nuevas construcciones sintácticas para permitir la especificación directa de constantes de clases y colecciones, que aportarán una mayor comodidad y economía de expresión al lenguaje. <<dotNetManía a) Inicializadores de objetos 24 En el fuente 3 se muestra cómo se podrá asignar una “constante” construida ad hoc a una variable de una clase cualquiera. En lugar de la llamada al constructor con argumentos, o de la llamada al constructor básico seguida de un bloque With..End With, en esta variante más “declarativa” los valores de las pro- La extensión de la sintaxis para la inicialización de objetos se ampliará también a las colecciones genéricas. El tipo al que se aplica el inicializador de colección debe implementar la interfaz genérica System.Collections.Generic.ICollection(Of T), y la inicialización se traduce en la construcción de la colección, seguida de una secuencia de llamadas al método ICollection(Of T).Add(T) para añadir cada elemento de la lista. El propio fuente 3 muestra más adelante cómo puede hacerse la inicialización de una variable Hijos de tipo List(Of Persona). ‘ a nivel de módulo para utilizarla en varios métodos Dim Hijos As List(Of Persona) = Nothing Sub Ejemplo2() ‘ Inicializador de objeto Dim ag = New Persona { _ Nombre := “Amanda”, _ Sexo := SexoPersona.Mujer, _ FechaNac := New DateTime(1998, 10, 23) _ } ‘ ** Equivale a: ‘ Dim ag = New Persona() ‘ With ag ‘ .Nombre = “Amanda” ‘ .Sexo = SexoPersona.Mujer ‘ .FechaNac = New DateTime(1998, 10, 23) ‘ End With ‘ Inicializador de colección Hijos = New List(Of Persona) { _ { _ Nombre := “Diana”, _ Sexo := SexoPersona.Mujer, _ FechaNac := New DateTime(1996, 2, 4) _ }, _ { _ Nombre := “Dennis”, _ Sexo := SexoPersona.Varón, _ FechaNac := New DateTime(1983, 12, 27) _ } _ } ‘ ** Equivale a: ‘ Dim hijos = New List(Of Persona) ‘ hijos.Add(New Persona(“Diana”, SexoPersona.Mujer,_ New DateTime(1996, 2, 4))) ‘ hijos.Add(New Persona(“Dennis”, SexoPersona.Varón,_ New DateTime(1983, 12, 27))) End Sub Fuente 3. Inicializadores de objetos y colecciones << dnm.futuro La expresión “tipos anónimos” se refiere a la posibilidad de que el compilador de VB 9.0 sintetice de forma automática nuevos tipos de datos a partir de las propiedades que se le indiquen en expresiones de inicialización. Por ejemplo, a partir del fragmento de código que se muestra en el fuente 4, el compilador generará un tipo dotado de las propiedades que se indican en su expresión de inicialización, Nombre y Ejemplares. El nombre que asigne internamente el compilador al tipo es irrelevante; lo realmente importante del ejemplo es que las variables rev1 y rev2 serán de un mismo tipo anónimo y no de dos tipos diferentes. El compilador “combina” las definiciones de tipos anónimos siempre que en las expresiones de inicialización se incluyan las mismas propiedades, los tipos de éstas coincidan y estén declaradas en el mismo orden. Sub Ejemplo3() ‘ Tipos anónimos Dim rev1=New {Nombre:=“DotNetManía”, Ejemplares:=12} Dim rev2=New {Nombre:=“MSDN Magazine”, Ejemplares:=12} ‘ ** Equivale a: ‘ Dim rev1 As _Anonimo1_ = New _Anonimo1_() ‘ ‘_Anonimo1_ es una clase que implementa propiedades ‘ ‘Nombre y Ejemplares (ver código fuente) ‘ With rev1 ‘ .Nombre = “DotNetManía” ‘ .Ejemplares = 12 ‘ End With ‘ Dim rev2 As _Anonimo1_ = New _Anonimo1_() ‘ With rev2 ‘ .Nombre = “MSDN Magazine” ‘ .Ejemplares = 12 ‘ End With End Sub Fuente 4. Generación de tipos anónimos Tipos anulables .NET Framework 2.0 implementó el tratamiento de los tipos genéricos a nivel de motor de ejecución, y a partir de esa posibilidad C# 2.0 y Visual Basic 2005 incorporaron al lenguaje la capacidad para definir y manipular tipos genéricos. Adicionalmente, entre las clases base de .NET 2.0 se incluye el tipo genérico Nullable(Of T), que nos permite dotar a los tipos valor de la semántica de valor nulo que caracteriza a los tipos referencia. Por ejemplo, declarando el campo privado _sexo de la clase Persona del fuente 1 de tipo Nullable(Of SexoPersona) podremos inicializarlo con el valor Nothing. Tal asignación se traduce en la asignación del valor False a la propiedad HasValue del tipo. Aparte de permitir aprovechar las características intrínsecas del tipo, la versión actual de Visual Basic no ofrece ninguna facilidad lingüística directa para trabajar con los tipos anulables. Corrigiendo esa limitación, y equiparándose en este sentido a C#, VB 9.0 integrará en el lenguaje el tratamiento de los tipos anulables. En primer lugar, ofreciendo una sintaxis más cómoda para la definición de estos tipos: en lugar de Nullable(Of Integer) ahora podremos usar la notación Integer?, mucho más concisa. Pero lo más importante es que se integrará en el lenguaje la operación sobre estos tipos en función de sus tipos subyacentes, utilizando una semántica de valor nulo similar a la de SQL. Por ejemplo, la primera suma que se muestra en el fuente 5 producirá Nothing, dado que uno de sus operandos tiene ese valor. Por el contrario, la segunda suma producirá 7, dado que ambos operandos tienen asignado un valor. Para lograr un efecto similar a éste en VB 2005 sería necesario encapsular el tipo Nullable(Of Integer) dentro de una estructura y definir para ésta los operadores correspondientes, como se ha hecho en [4]. Sub Ejemplo4() Dim m As Integer? = Nothing Dim n As Integer? = 4 Dim p As Integer? = 3 Dim x As Integer? = m + n ‘ x = Nothing Dim y As Integer? = n + p ‘ y = 7 End Sub Fuente 5. Declaración y uso de tipos anulables Métodos extensores Los métodos extensores (extension methods) son un recurso de conveniencia que permite extender o ampliar la funcionalidad de una clase sin necesidad de modificar su código fuente ni recurrir a la herencia. Los operadores de consulta de LINQ que veremos más adelante se implementan utilizando métodos extensores. Suponga que tenemos a nuestra disposición la clase Persona del fuente 1, pero únicamente en su forma compilada, como parte de una librería de clases. Suponga además que quisiéramos extender artificialmente la clase con métodos adicionales – por ejemplo, añadirle métodos lógicos que nos permitan conocer si la persona cumple años durante el mes actual o es mayor de edad. Usando los nuevos recursos que brindará VB 9.0, la solución consistiría en crear un módulo (que se muestra en el fuente 6), dotándolo de los métodos extensores correspondientes. Para poder utilizar los métodos de este tipo como métodos extensores, tanto el módulo como los propios métodos deberán marcarse con el atributo System.Runtime.CompilerServices.Extension. <<dotNetManía Tipos anónimos 25 << dnm.futuro <System.Runtime.CompilerServices.Extension()> _ Module Persona_Extension ‘ métodos extensores <System.Runtime.CompilerServices.Extension()> _ Public Function CumpleAñosEsteMes(ByVal [Me] As Persona) As Boolean Return [Me].FechaNac.HasValue AndAlso _ [Me].FechaNac.Value.Month = DateTime.Today.Month AndAlso _ [Me].FechaNac.Value.Day >= DateTime.Today.Day End Function <System.Runtime.CompilerServices.Extension()> _ Public Function MayorDeEdad(ByVal [Me] As Persona) As Boolean Return [Me].Edad.HasValue AndAlso [Me].Edad.Value >= 18 End Function ‘ método extensor con parámetro-función <System.Runtime.CompilerServices.Extension()> _ Public Function CumpleCondicion(ByVal [Me] As Persona, ByVal F As Func(Of Persona, Boolean)) As Boolean Return F([Me]) End Function End Module Fuente 6. Módulo que implementa los métodos de extensión Los métodos extensores deben tener un primer parámetro del tipo que se pretende extender, y dado que estos métodos se van a utilizar como métodos de instancia, surge naturalmente la idea de llamar al parámetro [Me] (los corchetes son necesarios, dado que Me es palabra reservada), como muestra el ejemplo. Una vez que tenemos nuestros métodos programados, solo tenemos que “ponerlos en ámbito” en el código donde queremos utilizarlos, mediante la directiva Imports. A partir de ese momento, podremos aplicar los métodos extensores a objetos de la clase “extendida” como si de un método de instancia corriente de ésta se tratase. En el fuente 7 se muestra un fragmento de código en el que se aplican los métodos extensores definidos anteriormente a un objeto de la clase Persona. Tenga en cuenta que muchos de los métodos extensores que se utilizan en LINQ requieren en calidad <<dotNetManía Sub Ejemplo5() Dim ag = New Persona { _ Nombre := “Amanda”, _ Sexo := SexoPersona.Mujer, _ FechaNac := New DateTime(1998, 10, 23) _ } 26 If ag.MayorDeEdad() Then Console.WriteLine(“Amanda es mayor de edad!”) Else Console.WriteLine(“Amanda es menor de edad.”) End If ‘ llamada a través de delegado If ag.CumpleCondicion(AddressOf MayorDeEdad) Then Console.WriteLine(“Amanda es mayor de edad!”) Else Console.WriteLine(“Amanda es menor de edad.”) End If End Sub Fuente 7. Utilización de métodos extensores de parámetros a delegados que “apunten” a la funcionalidad a ejecutar cuando llegue el momento adecuado. Por ejemplo, el fuente 6 ofrece un método extensor CumpleCondicion que recibe como parámetros la referencia a un objeto de la clase Persona para el que se desea comprobar si cumple una condición lógica determinada, y la condición en sí, expresada en forma de delegado genérico del tipo Func(Of Persona, Boolean). El fuente 7, por otra parte, muestra un ejemplo de su utilización. Interfaces dinámicas En aras de la completitud, mencionaremos brevemente tres nuevas características propuestas para VB 9.0 que no tienen relación directa con LINQ y que están orientadas a hacer el lenguaje más dinámico, en línea con las posibilidades que ofrecen otros lenguajes modernos como Python o Ruby. En primer lugar están las interfaces dinámicas, que permiten cobijar temporalmente bajo un mismo “paraguas” a objetos no relacionados entre sí pero que comparten (por azar o diseño consciente) una serie de características. Por ejemplo, el código que se presenta en el fuente 8 define la interfaz dinámica ITieneNombre, en la que tiene cabida cualquier objeto que disponga de una propiedad alfanumérica llamada Nombre. A continuación, se define una función que devuelve una persona o una revista (en este último caso utilizando un tipo anónimo). Un objeto declarado como de tipo correspondiente a una interfaz dinámica es accedido siempre mediante enlace tardío (dinámico), pero la suscripción a la interfaz dinámica nos permite disponer de las ventajas del tipado estático al acceder a los miembros, y en particular disponer de la ayuda Intellisense. Dynamic Interface ITieneNombre Property Nombre() As String End Interface Public Function ObtenerObjetoConNombre(_ ByVal N As Integer) As ITieneNombre Select Case N Case 1 Return New Persona(“Paco Marin”, SexoPersona.Varón) Case 2 Return New {Nombre:=“DotNetManía”, Ejemplares:=12} Case Else Return Nothing End Select End Function Public Sub Ejemplo6() ‘ ** interfaces dinámicas Dim objetoConNombre As ITieneNombre objetoConNombre = ObtenerObjetoConNombre(_ New Random().Next(3)) ObjectDumper.Write(objetoConNombre) End Sub Fuente 8. Utilización de interfaces dinámicas << dnm.futuro Un caso extremo de dinamismo es aquel en el que en tiempo de compilación no conocemos el nombre del método al que debemos llamar, los argumentos de la llamada o incluso la clase a la que el método pertenece. Los identificadores dinámicos permiten cubrir tales situaciones, y lograr una economía de expresión muy alta con respecto a si fuera necesario hacer las mismas tareas utilizando reflexión. El fuente 9 presenta ejemplos de llamadas dinámicas a los métodos de una clase Prueba. Como puede verse, en el código se llama a funciones cuyos nombres se almacenan en variables o expresiones de tipo String. Public Class Prueba Public Sub Saludo() Console.WriteLine(“Hola!”) End Sub Public Function Sumar(_ ByVal ParamArray nums As Integer()) As Integer Dim suma = 0 For Each i As Integer In nums suma += i Next Return suma End Function End Class Public Sub Ejemplo7() ‘ ** identificadores dinámicos Dim p As Object = New Prueba() ‘ As Object es imprescindible! Dim método As String = “Saludo” ‘ el nombre del método a llamar p.(método)() ‘ equivale a p.Saludo() Dim args = {1, 2, 4, 8} Console.WriteLine(“La suma es: “ & p.(“Sumar”)(args)) End Sub Fuente 9. Utilización de interfaces dinámicas Relajación de delegados Por último, otro cambio que se incorporará al lenguaje en la próxima versión hará consistentes las reglas de asociación de delegados a las reglas de llamadas a métodos, basadas en la contravarianza de los argumentos. Por ejemplo, en la aplicación Windows Forms cuyo código se muestra en el fuente 10 (proyecto LINQ_VB2), la firma del gestor asociado al evento Click ha sido modificada de forma tal que el segundo argumento es de un tipo (Object) más general que el que originalmente requiere ese evento (EventArgs). Esta novedad permitirá crear métodos delegados más generales y por lo tanto aplicables a un mayor número de situaciones. Public Class Form1 ‘ firma del gestor de eventos modificada! Private Sub Mensaje(ByVal sender As System.Object, ByVal e As Object) Handles Button1.Click MessageBox.Show(“Hola desde VB 9.0”, “Saludo”) End Sub End Class Fuente 10. Ejemplo de relajación de delegados LINQ en VB 9.0 Como hemos dicho al principio de este artículo en nuestra definición de LINQ, la clave de esta tecnología reside en que abre al programador la posibilidad de expresar las consultas sobre datos provenientes de las más disímiles fuentes (colecciones en memoria, bases de datos relacionales, documentos XML) utilizando recursos de su propio lenguaje de programación. No repetiremos aquí todo lo relacionado con los fundamentos, la arquitectura y el funcionamiento de LINQ, sino que referiremos al lector a [2]. El programador de VB que haya seguido este artículo hasta aquí ya dispondrá del bagaje conceptual necesario (tipos anónimos, métodos extensores) para comprender todo lo que en aquella referencia se trata. LINQ es una tecnología 100% multi-lenguaje, diferencias sintácticas aparte. Basaremos nuestra exposición en ejemplos que ayuden a comprender la sintaxis de las expresiones de consulta en VB 9.0. Expresiones de consulta Las expresiones de consulta (la documentación de VB se refiere a ellas como query comprehensions, mientras que la de C# las denomina query expressions) son el principal mecanismo mediante el que cobra vida la tecnología LINQ. No son otra cosa que expresiones responden a una nueva sintaxis añadida al lenguaje y que pueden actuar sobre cualquier objeto que satisfaga la interfaz genérica System.Collections.Generic.IEnumerable<T>, transformándolo mediante un conjunto de operadores en otra colección que implementa la misma interfaz. En el fuente 11 se muestran algunos ejemplos de expresiones de consulta basadas en la colección de objetos Hijos que hemos creado e inicializado en el fuente 3. Cualquiera que esté familiarizado con SQL reconocerá en las expresiones de consulta las operaciones del álgebra relacional como selección, proyección, ordenación o agrupación. Algunas operaciones, como los agregados (Count, Sum, etc.), aún no están presentes en la sintaxis VB implementada en la versión actual de la presentación preliminar, pero en cualquier caso, como muestra el segundo ejemplo, están disponibles si se utiliza la sintaxis explícita de llamadas que hemos descrito detalladamente en [2]. <<dotNetManía Identificadores dinámicos 27 << dnm.futuro Public Sub Linq1() ‘ lista de chicas, ordenada alfabéticamente Dim chicas = From h In Hijos _ Where h.Sexo.HasValue AndAlso _ h.Sexo.Value = SexoPersona.Mujer _ Select New {Nombre := h.Nombre, Edad := h.Edad} Order By Nombre ObjectDumper.Write(chicas) End Sub Public Sub Linq2() ‘ cantidad de hijos mayores de edad Dim promedio = (From h In Hijos _ Where h.MayorDeEdad() _ Select h).Count() ‘ ** en un futuro próximo: ‘ Select Count() From h In Hijos ... ObjectDumper.Write(promedio) End Sub Public Sub Linq3() ‘ agrupación por sexos Dim grupos = From h In Hijos _ Group By h.Sexo.Value _ Select It ‘ It - significa aquí “el grupo” ‘ cuántos de cada sexo For Each Dim g In grupos Console.WriteLine(g.Key & “ - “ & g.Count) Next End Sub Fuente 11. Ejemplos de expresiones de consulta Resultados de consultas como conjuntos de datos <<dotNetManía Otra de las novedades importantes relacionadas con LINQ e incorporadas en esta presentación preliminar es la posibilidad de tratar los resultados de consultas como conjuntos de datos. Específicamente, esta versión incorpora un nuevo operador, ToDataTable, que permite convertir el resultado de una consulta en un objeto DataTable para, por ejemplo, pasarlo a otra capa de la aplicación o conectar a él controles visuales. La figura 2 muestra una rejilla en la que se visualiza el resultado de una consulta sobre una colección de libros famosos. El código que produce la imagen se muestra en el fuente 12. 28 Figura 2. Enlace a datos de resultado de consulta Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim consulta = From l In libros _ Select l _ Order By Año Dim tabla As DataTable = consulta.ToDataTable() DataGridView1.DataSource = tabla End Sub Fuente 12. Enlace a datos sobre el resultado de una consulta Soporte directo para XLinq en el lenguaje VB 9.0 ofrece varias nuevas características destinadas específicamente a dar soporte intrínseco a XML y XLinq, la tecnología derivada de LINQ para la ejecución de consultas integradas sobre documentos XML. El tema merece un artículo independiente, y aquí solo presentaremos las principales novedades, que son: • Literales XML. • Importación y uso de espacios de nombres XML. • Enlace tardío sobre XML. ‘ ** importación de espacio de nombres XML Imports ns = “http://www.w3.org/1999” Public Sub Xml1() ‘ ** literales XML Dim ag = <Persona Nombre=”Amanda” <%= SexoPersona.Mujer %> Sexo=<%= <%= #10/23/1998# %>> %> FechaNac=<%= </Persona> Console.WriteLine(ag.GetType().ToString()) ObjectDumper.Write(ag) ‘ ** ahora con elementos y espacio de nombres Dim ag2 = <Persona xmlns=”http://www.w3.org/1999”> <Nombre>Amanda</Nombre> <%= SexoPersona.Mujer %></Sexo> <Sexo><%= %> <%= #10/23/1998# %> <FechaNac><%= %></FechaNac> </Persona> ‘ ** uso de espacio de nombres XML Console.WriteLine( “Amanda nació el “ + ag2. <ns:FechaNac>.Value) Dim sobrinos = <Sobrinos> <Persona Nombre=”Adrián” <%= SexoPersona.Varón %> Sexo=<%= <%= New DateTime(2005, 8, 2) %> FechaNac=<%= %>> </Persona> <%= ag %> </Sobrinos> Console.WriteLine(sobrinos.GetType().ToString()) ObjectDumper.Write(sobrinos) Fuente 13. Ejemplos de literales XML << dnm.futuro Literales XML Public Sub Xml2() ‘ ** literal XML a partir de consulta LINQ Dim hijosXML = <Hijos> <%= Select <Persona Nombre=<%= h.Nombre %> %> <%= h.Sexo.Value %> Sexo=<%= <%= h.FechaNac.Value %> FechaNac=<%= %>> </Persona> _ From h In Hijos %> </Hijos> Console.WriteLine(hijosXML.GetType().ToString()) ObjectDumper.Write(hijosXML) ‘ ** enlace tardío sobre XML For Each Dim x In hijosXML...Persona Console.WriteLine([email protected]) Next End Sub Fuente 14. Literal XML obtenido de una consulta LINQ Los objetos resultantes de la compilación de los fragmentos XML son de tipo XmlElement, definido en el ensamblado System.Xml.XLinq, lo que garantiza la total interoperabilidad con otros lenguajes que utilicen XLinq. Importación y uso de espacios de nombres XML Para dar consistencia a la inserción de XML en nuestro código fuente, VB 9.0 permitirá importar al mismo espacios de nombres XML usando la sentencia Imports, como se muestra en el fuente 13. A todo espacio de nombres XML importado siempre deberá asignársele un alias. Más adelante en el ejemplo se muestra la sintaxis que permite hacer uso de estos alias para cualificar elementos o atributos. Visual Basic 9.0 permite insertar directamente en el código fuente fragmentos de documentos XML nica, las variables de nuestro código se pueden enlazar en tiempo de ejecución a atributos y elementos XML a través de construcciones sintácticas especiales. El fuente 14 muestra un bucle en el que se utilizan dos de estas construcciones: la notación hijosXML...Persona representa al “eje descendiente”: la colección de todos los nodos Persona que descienden de hijosXML, no importa a qué nivel de profundidad; por otra parte, la notación x.@Nombre tiene que ver con el “eje de atributos” y produce una referencia al objeto XAttribute asociado al atributo Nombre del elemento x. Conclusión En este artículo hemos presentado las nuevas características que incluirá la versión 9.0 de Visual Basic, que estará disponible oficialmente junto con Orcas, la próxima versión de Visual Studio. En particular, hemos hecho mayor énfasis en las nuevas características de VB 9.0 que sirven de soporte para LINQ y XLinq. A esta última tecnología dedicaremos íntegramente una de nuestras próximas entregas. Agradecimientos El autor quiere agradecer la ayuda de Guillermo “Guille” Som, que ha contribuido a mejorar este artículo con múltiples sugerencias y puntualizaciones de gran utilidad. Bibliografía [1] Recursos relacionados con VB 9.0 y LINQ: http://msdn.microsoft.com/vbasic/future/default.aspx. [2] Hernández, Octavio “Lo que nos traerá Orcas: la tecnología LINQ”, publicado en dotNetManía Nº 25, abril de 2006. Enlace tardío sobre XML [3] Som, Guillermo “Generics y Visual Basic .NET”, publicado en dotNetManía nº 8, octubre de 2004. Además de permitir la codificación directa de XML, VB 9.0 también simplifica el acceso a las estructuras XML mediante el enlace tardío sobre XML. Mediante esta téc- [4] Som, Guillermo “Definición de estructura para operar sobre tipos anulables”, publicado en http://www.elguille.info. <<dotNetManía VB 9.0 permite insertar directamente en el código fuente fragmentos de documentos XML. Los valores que se asocian a los atributos y elementos no tienen que ser especificados necesariamente mediante constantes, porque el lenguaje incorpora una sintaxis que recuerda a la de ASP para “rellenar” las estructuras XML con el resultado de expresiones del lenguaje de programación. El fuente 13 muestra algunos ejemplos claros. Una aplicación muy potente de esta nueva característica de VB 9.0 es la que permitirá obtener un literal XML a partir del resultado de una consulta LINQ, como se muestra en el fuente 14. 29 dnm.servidores.sql David Perona Servicios Web nativos con SQL Server 2005 Con el uso de HTTP EndPoints podemos exponer a la Web tanto los procedimientos almacenados como las UDF de nuestra base de datos sin tener que usar ninguna otra herramienta ni abrir puertos TCP para SQL Server 2005. << En este artículo veremos cómo mediante el uso de los HTTP David Perona Martínez trabaja como desarrollador para Clave Informática, S.L. Es Técnico Superior en Administración de Sistemas Informáticos y MCAD.NET. EndPoints podemos exponer a la Web tanto los procedimientos almacenados como las UDF de nuestra base de datos prácticamente sin esfuerzo. Estos objetos nos permitirán crear interfaces de acceso vía HTTP o TCP para SOAP, T-SQL, Service Broker e incluso para DBMirroring. Nos centraremos en el objetivo de este artículo y hablaremos exclusivamente de la creación de HTTP/SOAP EndPoints en SQL Server. En cierta forma, esta habilidad ya estaba disponible con SQL Server 2000. SQLXML 3.0 nos proveía de un conjunto de herramientas que nos permitían enviar y recibir datos en formato XML y además permitía crear servicios Web con posibilidad de ejecución de procedimientos y UDF, al igual que los EndPoints. Una de las mejoras más notables que se han añadido con la aparición de los EndPoints es la supresión de IIS para gestionar las peticiones HTTP de los servicios Web. Pero alguien debe hacerse cargo de estas redirecciones, por lo que para poder crear estos servicios necesitaremos que la máquina en la que va a residir SQL Server funcione bajo Windows 2003 o Windows XP con SP2. Ya que será http.sys el encargado de realizar todo este trabajo. El funcionamiento de http.sys (HTTP Listener Process) es el siguiente. Imaginemos que hemos creado un EndPoint en la dirección http://miServer/dotnetmania. Al crearlo, queda automáticamente registrado en http.sys. Cuando llega una petición SOAP, la recoge en primera instancia el servidor especificado en la llamada, en nuestro caso miServer. El siguiente paso es comparar el resto de la cadena con la lista de EndPoints que el servidor tiene registrados y, en caso de coincidencia, éste envía la petición directamente al EndPoint correspondiente, omitiendo así el paso por IIS. En la figura 1 vemos claramente diferenciadas las distintas metodologías. Figura 1 Veamos un ejemplo Ahora que ya hemos visto quiénes somos y hacia dónde vamos, es el momento de entrar en materia. Para crear un servicio Web en SQL Server 2005 son necesarios tres pasos: 1. Crear el origen de datos. Un procedimiento almacenado, una UDF o incluso, como veremos más adelante, un proceso batch. 2. Crear un EndPoint especificando algún WebMethod que nos proporcione el acceso a esos datos. 3. Crear una aplicación cliente que solicite esos datos. En este ejemplo crearemos un servicio Web que nos ofrecerá una lista de todos los artículos de los << dnm.servidores.sql que disponemos y que al seleccionarlo, cualquiera de ellos nos enseñará su foto. Para ello, usaremos la base de datos AdventureWorks que adjunta SQL Server 2005. El primer paso será crear los objetos que nos ofrecerán los datos. En nuestro caso crearemos un procedimiento almacenado, que podemos ver en el fuente 1, y que nos devolverá un listado básico (código y nombre) de la tabla de Productos. CREATE PROCEDURE dbo.GetArticulos AS SELECT P.ProductID, P.Name FROM Production.Product P ORDER BY P.ProductID Fuente 1 En el fuente 2 tenemos el segundo procedimiento almacenado que nos hará falta. Este nos devuelve la imagen y el nombre del artículo que le pasemos como parámetro, de la tabla ProductPhoto. Sencillo, ¿verdad? Ya tenemos nuestro EndPoint creado y listo para su uso. Podremos comprobar su correcto funcionamiento si por ejemplo desde cualquier navegador le pedimos que nos devuelva el documento WSDL (Web Service Description Language) correspondiente al servicio. Con http://miServer/dotnetmania?WSDL nos mostrará una página con toda la información del EndPoint. Ahora que tenemos todos los requisitos a punto, crearemos una aplicación muy simple que nos mostrará el listado de artículos y que, al movernos por ellos, nos mostrará las fotos de cada uno. Para ello, abrimos Visual Studio y creamos un nuevo proyecto Windows, al que llamaremos EndPoints. Al formulario lo llamaremos frmEndPoint, y añadiremos los siguientes controles: • Un DataGridView, que llamaremos oGrid. • Un PictureBox, que llamaremos PicImagen. • Un Label, que llamaremos LblImagen. • Un Button, que llamaremos Button1. Con lo que conseguiremos que tenga una apariencia parecida la que vemos en la figura 2. CREATE PROCEDURE dbo.GetImagenArt @ProductID int AS SELECT PF.LargePhoto, PF.LargePhotoFileName FROM Production.Product P LEFT JOIN Production.ProductProductPhoto PPF ON P.ProductID = PPF.ProductID LEFT JOIN Production.ProductPhoto PF ON PPF.ProductPhotoID = PF.ProductPhotoID WHERE P.ProductID = @ProductID Fuente 2 CREATE ENDPOINT sql_DotNetMania STATE = STARTED AS HTTP ( PATH = ‘/DotNetMania’, AUTHENTICATION = (INTEGRATED), PORTS = (CLEAR), SITE = ‘miServer’) FOR SOAP ( WEBMETHOD ‘GetProducts’ (Name=’AdventureWorks.dbo.GetArticulos’), WEBMETHOD ‘GetImageProd’ (Name=’AdventureWorks.dbo.GetImagenArt’), BATCHES = DISABLED, WSDL = DEFAULT, DATABASE = ‘AdventureWorks’, NAMESPACE = ‘http://Adventure-Works/’) Fuente 3 Figura 2 Lo primero que debemos hacer es añadir una referencia Web a nuestro proyecto. Cuando se nos pregunte dónde se encuentra nuestro servicio, simplemente escribiremos la dirección del WSDL (que en nuestro caso será http://miserver/dotnetmania?WSDL). Una vez que lo tengamos localizado, le daremos el nombre Local_EndPoint. En el fuente 4 podemos ver el código del ejemplo. Como con cualquier servicio Web, tendremos que importar el espacio de nombres de la clase de este servicio en el encabezado del módulo en el que lo vayamos a usar. Importaremos también los espacios System.Data y System.Data.SqlClient, que nos harán falta para el desarrollo del ejemplo. En la cabecera de la clase inicializamos el objeto que contendrá el servicio y un array de objetos, pues- <<dotNetManía Con los procedimientos almacenados ya creados, el único paso que nos queda es crear nuestro EndPoint. Para ello, usaremos el código del fuente 3. 31 << dnm.servidores.sql Imports System.Data Imports System.Data.SqlClient Imports EndPoints.local_EndPoint Public Class frmEndPoint Dim myEndPoint As New EndPoints.local_EndPoint.sql_DotNetMania Dim oReturned() As Object Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim oSet As New DataSet oGrid.AllowUserToAddRows = False oGrid.AllowUserToDeleteRows = False oGrid.EditMode = DataGridViewEditMode.EditProgrammatically myEndPoint.Credentials = System.Net.CredentialCache.DefaultCredentials oReturned = myEndPoint.GetProducts If oReturned(0).ToString = “System.Data.DataSet” Then oSet = CType(oReturned(0), DataSet) oGrid.DataSource = oSet oGrid.DataMember = oSet.Tables(0).ToString oGrid.Refresh() End If End Sub Private Sub oGrid_RowEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles oGrid.RowEnter Dim oSet As New DataSet Dim oByte() As Byte Dim oRow As DataRow If Not oGrid.Item(e.ColumnIndex, e.RowIndex).Value.ToString.Trim = “” Then myEndPoint.Credentials = System.Net.CredentialCache.DefaultCredentials oReturned = myEndPoint.GetImageProd(oGrid.Item(0, e.RowIndex).Value.ToString.Trim) If oReturned(0).ToString = “System.Data.DataSet” Then oSet = CType(oReturned(0), DataSet) oRow = oSet.Tables(0).Rows(0) ‘ oByte = oRow(0) PicImagen.Image = New Bitmap(New System.IO.MemoryStream(oByte)) lblImagen.Text = oRow(1) End If End If End Sub End Class Fuente 4 to que el EndPoint no siempre nos va a devolver objetos de tipo DataSet. Dependiendo del tipo de consulta, podemos obtener distintos elementos, como podemos ver en la tabla 1. A continuación, pasaremos nuestras credenciales al servicio Web. Y si son aceptadas, ya podemos acceder Elemento en SQL Server Resultado de SELECT Resultado de SELECT especificando FOR XML Raise error <<dotNetManía Parámetro de salida 32 Filas Afectadas Valor devuelto por una consulta a todas los WebMethods que hayamos definido en nuestro EndPoint. Si nos fijamos en el código de Button1, está comprobando el tipo que ha devuelto la función GetProducts; en caso de ser un DataSet, lo asigna a un objeto DataSet local a la función y lo establece como DataSource del DataGridView. Con esto ya tendremos cargada toda la información de los artículos en la rejilla. Objeto .NET El último paso es comprobar el System.Data.DataSet movimiento por las filas de la rejilla para ir cargando las imágenes. System.Xml.XmlElement Como puede comprobarse, el códiSqlMessage (del WSDL) go es muy parecido al de la carga de SqlParameter (del WSDL) los artículos. SqlRowCount (del WSDL) Todo el código de este ejemplo puede descargarse de www.dotnetmaSystem.Int32 Tabla 1 nia.com. << dnm.servidores.sql Entrando en detalle En la propia instrucción de creación del EndPoint podemos especificar el nombre que le queremos dar, un login válido para SQL Server o Windows, que será el propietario de dicho servicio y el estado del servicio una vez que se haya creado. CREATE ENDPOINT AUTHORIZATION = usrDavid STATE = STARTED Los posibles valores para el parámetro STATE, son Started, Stopped (valor por defecto) y Disabled. Cuando el servicio está en el estado Stopped, sigue escuchando y recibiendo peticiones, aunque devuelve un mensaje de error al cliente. Por el contrario, cuando está en el estado Disabled, está “físicamente” desconectado, no recibe las peticiones. Obviando la propia definición del EndPoint, el resto de la sintaxis consta de dos partes claramente diferenciadas: En la primera parte, especificamos el protocolo de trasporte (TPC o HTTP), el servidor en el que residirá nuestro servicio, el puerto de escucha, el método de autentificación del EndPoint y una lista de direcciones IP a la que queramos restringir el acceso. • PATH – Especifica la URL de nuestro EndPoint, En nuestro caso, “/dotnetmania”. Esta es la dirección que tendremos que escribir para acceder al servicio. Con lo que la sintaxis queda de la siguiente forma: http://miServer/dotnetmania. • AUTHENTICATION – Especifica el tipo de autentificación que usaremos para nuestro servicio. Los posibles valores son: Basic, Digest, Integrated (usará la configuración de Windows), NTLM o Kerberos. • PORTS – Indica el tipo de puerto a usar. Los posibles valores son CLEAR (HTTP) o SSL (que aceptará HTTPS). • Clear_Port y SSL_Port – Permiten especificar puertos distintos a los que se asumen por defecto al indicar el parámetro PORTS. Por defecto, la opción CLEAR usará el puerto 80 y la opción SSL el 443. HTTP ( PATH = ‘/DotNetMania’, AUTHENTICATION = (INTEGRATED), PORTS = (CLEAR), SITE = ‘miServer’) FOR SOAP ( ... Fuente 5 80/DotNetMania'. De esta forma, la URL estará per- manentemente ocupada y evitaremos conflictos de dirección. De la misma forma, para cancelar la reserva de esta dirección, ejecutaremos lo siguiente: sp_delete_http_namespace_reservation N' N'http://miServer:80/DotNetMania'. Si, por el contrario, estuviésemos omitiendo el parámetro SITE, o le estuviésemos pasando como valor un “*”, la reserva que se crearía sería la siguiente: http://*:80/dotnetmania. En la segunda parte de la sintaxis de un EndPoint, informamos sobre el tipo de EndPoint que estamos creando y a qué peticiones va a estar escuchando. Podremos especificar tanto SOAP, como T-SQL, Service Broker o incluso Database Mirroring. Para cada uno de ellos, tendremos la posibilidad de especificar un subconjunto de parámetros para definir su configuración. Nos centraremos en SOAP, que es el objetivo de este artículo. Tendremos que definir como mínimo un <<dotNetManía Con este sistema, haremos accesible información de nuestro sistema vía servicios Web • SITE – Mediante este parámetro especificamos el nombre de la máquina en la que reside el servicio Web. Si omitimos este parámetro, se asumirá el valor “*”, que indica que la escucha se efectuará sobre todos los posibles hosts de la máquina que no estén explícitamente reservados. Otro posible valor es “+”, que indicará que la operación de escucha se efectuará sobre todos los posibles hosts de la máquina, pero sin discriminar los que estén reservados. Otros valores aceptados por esta propiedad pueden ser LocalHost, el nombre DNS o incluso la dirección IP de la máquina. Cuando creamos un EndPoint, implícitamente estamos reservando una URL para nuestro servicio. Por ejemplo, en el caso que nos ocupa, si observamos el fuente 5, estamos implícitamente reservando la dirección http://miServer:80/dotnetmania. Esto quiere decir que mientras nuestro servidor esté en ejecución, http.sys redireccionará cualquier petición que se haga a esta dirección a SQL Server. Sin embargo, podrá ser usada por cualquier otro servicio cuando el servidor esté detenido. Para evitar esta situación, una buena práctica es reservar la URL explícitamente, con ayuda del procedimiento almacenado sp_reserve_http_namespace. La sintaxis es la siguiente: sp_reserve_http_namespace N'http://miServer: 33 << dnm.servidores.sql Podremos especificar tanto SOAP, como T-SQL, Service Broker o incluso Database Mirroring • • • WebMethod, que enlazaremos a un procedimeinto almacenado o una UDF. Indicaremos si dejamos habilitada la posibilidad de ejecutar Batches sobre el servidor. Es altamente recomendable dejar esta opción deshabilitada (el estado por defecto), a menos que sea de vital importancia tenerla habilitada, lo que nos obligará a extremar al máximo las medidas de seguridad de nuestro servicio. No hace falta que os explique lo que podría pasar si no somos totalmente meticulosos en este aspecto. Además, podremos definir otras propiedades como quién será el encargado de generar la información WSDL que ofreceremos. Por defecto, es el mismo servicio el encargado de generar este fichero, aunque tenemos la opción de crear un procedimiento almacenado y que sea éste el que, a petición del cliente, ofrezca un XSD personalizado. Si usamos la opción Default, el EndPoint puede producir dos versiones distintas del mismo XSD. Con http://miServer/dotnetmania?wsdl, devolverá un XSD con tipos derivados, para un correcto mapeo de los tipos de datos más complejos que se pueden almacenar en SQL Server. Por otra parte, podremos usar http://miServer/ dotnetmania?wsdlsimple . Este es un formato Tipo de Autentificación <<dotNetManía • • • Configurando aspectos de seguridad Tipos de autentificación Si os fijáis, en la opción AUTHENTICATION del servicio Web no hay posibilidad de especificar la autentificación anónima, detalle éste que nos puede evitar más de un problema. Echemos un vistazo al resto de posibles tipos. Configurando permisos sobre EndPoints La sintaxis para ofrecer permisos a un EndPoint es muy parecida a la que se utiliza para el resto de objetos de SQL Server. Descripción BASIC Este método se caracteriza por añadir a la cabecera HTTP, el usuario y la contraseña codificados en Base64. Requiere la utilización de SSL en la definición del servicio, ya que estamos pasando la información de la conexión en la misma petición y es relativamente fácil decodificar un código en Base64. DIGEST Al igual que el método BASIC, pasa tanto el usuario como la contraseña a través de la red, pero esta vez codificados mediante MD5 (algoritmo de codificación unidireccional). Con este tipo de autentificación sólo podremos especificar usuarios de un dominio de Windows; no acepta usuarios locales de la máquina. Cuando el servidor recibe esta información,compara el hash de la contraseña con el que quedó almacenado cuando se creó el usuario. Como nota, diremos que este tipo de autentificación sólo acepta encriptación MD5 bajo controladores de dominio de Windows Server 2003. NTLM Es el mecanismo de autentificación de Windows 95, 98 y NT 4.0. Ofrece un sistema más completo que Basic y Digest.A partir de Windows 2000, se implementó con SSPI. Estándar en Internet. Soportado a partir de Windows 2000 por medio de SSPI. Cuando se usa este tipo, SQL Server asocia su instancia principal con la cuenta que la está ejecutando. KERBEROS 34 • reducido del anterior y se diferencia en que esta versión mapea todos los tipos de SQL Server en tipos nativos XSD. WEBMETHOD — Con este parámetro indicamos los distintos métodos que estarán disponibles para el servicio. A cada uno de ellos deberemos asociarles un procedimiento almacenado o una función al que quedará enlazado. Podremos definir varios WebMethods por EndPoint. BATCHES — Indica si es posible la utilización de TSQL. WSDL — Indica dónde está el XSD que será devuelto al cliente cuando nos lo solicite. DATABASE — Especifica la base de datos en la que reside nuestro servicio. NAMESPACE — Especifica el espacio de nombres para nuestro EndPoint. FORMAT — Indica qué posibles tipos ofrecerá el servicio como respuesta. {ALL_RESULTS, ROWSETS_ONLY, NONE}. LOGIN_TYPE — {MIXED, WINDOWS}. INTEGRATED Este tipo prepara a nuestro EndPoint para que responda a los tipos de autentificación NTLM y KERBEROS. Tabla 2 << dnm.servidores.sql Tipo_de_acción puede tomar valores como Alter, Connect, Control, Take Ownership y View Definition. Para ejecutar este comando, es necesario que estemos en la base de datos Master. Por ejemplo, el comando: USE Master Go GRANT CONNECT ON ENDPOINT::sql_DotNetMania TO usr_Clave Otorga permisos para poder usar el EndPoint con nombre sql_dotnetmania al usuario usr_Clave. El parámetro WITH GRANT OPTION indica que usr_Clave estará capacitado para asignar este mismo permiso a otros logins. Para denegar cualquier tipo de acción sobre un servicio: USE Master Go DENY [Tipo_de_acción] ON ENDPOINT::Nombre_EndPoint TO SQL_Login CASCADE El funcionamiento es el mismo. El parámetro CASCADE indica que se debe propagar la denegación del permiso a todos los logins a los que el denegado se lo haya garantizado previamente. Y para eliminar cualquier permiso establecido o denegado previamente, usaremos: USE Master Go REVOKE [Tipo_de_accion] ON ENDPOINT::Nombre_EndPoint [FROM | TO] SQL_Login Algunos consejos Como contrapartida a la facilidad de creación de HTTP EndPoints, tenemos que tener en cuenta que estamos trabajando con un servicio Web como cualquier otro, pero que está directamente conectado a la base de datos, por lo que el nivel de seguridad tiene que ser extremo. Aquí se exponen las prácticas básicas para asegurar nuestros servicios Web. • Usaremos autentificación Kerberos. En la propiedad AUTHENTICATION, especificaremos siempre Kerberos, o bien Integrated, que permitirá a Windows seleccionar la autentificación NTLM o Kerberos. • Limitaremos tanto como podamos el alcance de los permisos que otorguemos. Siempre intentaremos asignar permisos exclusivamente a personas El apartado más importante es la configuración de los aspectos de seguridad de estos objetos o grupos de personas que necesiten tener acceso a estos servicios. Desde luego, nunca debemos asignar ningún permiso al rol público. • Usar SSL para información confidencial. De este modo permitiremos la encriptación de los contenidos confidenciales que circulen por la red. SQL Server requiere la configuración de un certificado. En este punto, tendremos especial cuidado, pues si configuramos un certificado para el puerto 443 (puerto por defecto de SSL), estaremos aplicándolo a todo el tráfico que circule por ese puerto. Por ejemplo, IIS puede estar recibiendo información por el mismo puerto. En este caso, el certificado les afectaría a los dos. • Configurar estos servicios en servidores que estén tras un firewall. • Asegurarse de que la cuenta Invitado está deshabilitada en el sistema operativo. Otro aspecto importante a tener en cuenta es el rendimiento de estos servicios. Si la solución maneja mucho código XML o si hace un uso intensivo de procedimientos almacenados, el rendimiento que pueden ofrecer los HTTP EndPoints es considerablemente bueno, puesto que permiten compartir la lógica de negocio fácilmente con otras aplicaciones. Por otro lado, si nuestra aplicación hace uso de procesos transaccionales críticos, o trabajamos con tipos muy grandes, como Binary Image o Text, el rendimiento no será optimo. Tened en cuenta la sobrecarga que se genera al tener que convertir estos objetos en mensajes SOAP. Además, estamos hablando de un formato basado en texto, diferente al formato binario nativo de SQL Server, Tabular Data Stream (TDS). Esto significa que el tamaño de los datos a enviar aumentará entre un 20 y un 30%. Conclusión Con HTTP Endpoints, SQL Server 2005 nos ofrece una forma sencilla de crear interfaces para servicios Web, Service Broker e incluso para DB-Mirroring. Ahora nos será mucho más fácil acceder a nuestro servidor SQL Server desde lugares desde los que antes nos era muy trabajoso, como pudieran ser aplicaciones en sistemas no Windows, dispositivos móviles y un largo etcétera. <<dotNetManía GRANT [Tipo_de_acción] ON ENDPOINT::Nombre_EndPoint TO SQL_Login WITH GRANT OPTION 35 dnm.servidores.sql Eladio Rincón Detección de problemas de rendimiento en SQL Server 2000 y SQL Server 2005 (IV) En esta cuarta entrega nos vamos a centrar en analizar qué tipo de información hay almacenada en la memoria de SQL Server, división del uso de la memoria y cómo detectar bloqueos con las nuevas DMV de SQL Server 2005. << ¿Cómo está desglosada la información almacenada en la memoria? En el segundo artículo de la serie identificamos la actividad que había en la memoria (contadores como Memory:Pages/sec y Memory:Available Bytes, KBytes y MBytes deberían resultar familiares al lector); ahora veremos cuáles son los límites de memoria a los que debe hacer frente SQL Server y además cómo está repartida dicha memoria. Para ello utilizaremos dos herramientas: el monitor de rendimiento y, por otro lado, comandos DBCC y vistas de sistema de SQL Server. Monitor de rendimiento Eladio Rincón Es Director de Tecnología de Bases de Datos de Solid Quality Learning y colaborador habitual de dotNetManía. Es MVP en SQL Server y uno de los fundadores del grupo de usuarios de SQL Server en España GUSE. SQL Server tiene dos contadores de rendimiento que indican cuánta es la memoria del servidor que se está utilizando y cuánta es la memoria máxima a la que puede aspirar SQL Server (memoria objetivo). Como norma general, en mediciones largas de tiempo, el valor de la memoria reservada (SQL Server Memory:Memory Manager:Total Server Memory), debería tener valores inferiores al 80 por ciento de la memoria objetivo (SQL Server Memory:Memory Manager:Target Server Memory). Cuando la memoria objetivo se encuentra por encima de esos porcentajes, nos está indicando que SQL Server necesita más memoria de la que puede disponer, que no necesariamente indicará falta de memoria física. Por ejemplo, el mes pasado vimos cómo encontrar patrones de ejecución de consultas; ¿qué pasaría si encontráramos un patrón de consultas que se resuelve de forma inefi- SQL Server tiene dos contadores de rendimiento que indican cuánta es la memoria del servidor que se está utilizando y cuánta es la memoria máxima a la que puede aspirar SQL Server ciente? Imagínese que analiza el plan de ejecución de la consulta y se da cuenta que no existe un índice apropiado para la consulta. ¿Cómo resuelve SQL Server esa consulta? Evidentemente, leyendo muchísima información –probablemente recorriéndose un índice completo, en lugar de realizar búsquedas de índice (por rango, o búsqueda directa)– lo cual implicaría que SQL Server tendría que acceder mucho a disco para recuperar la información necesaria para procesar la consulta y, a su vez, localizar espacio en memoria para alojar las lecturas realizadas. Con contadores del monitor de rendimiento también podremos ver cuáles son los tipos de información que ocupan los buffers de memoria de SQL Server; los contadores para la versión 2000 son los que puede ver en la tabla 1. Para SQL Server 2005, los contadores son casi los mismos, excepto el último que en lugar de ser << dnm.servidores.sql SQLServer:Buffer Manager Procedure cache pages Páginas en caché de procedimiento Páginas totales reservadas SQLServer:Memory Manager Memoria para conexiones de usuario Connection Memory SQLServer:Memory Manager Lock Memory Memoria para bloqueos SQLServer:Memory Manager Optimizer Memory Memoria reservada por el optimizador SQLServer:Cache Manager Páginas utilizadas totales por el caché Cache Pages – _Total que nos encontramos con más frecuencia de la deseada en el que gran parte de la memoria disponible por SQL Server es utilizada para guardar planes de ejecución de las consultas que se procesan en el servidor. Tabla 1 SQLServer:Cache Manager, se ha cambiado por SQLServer:Plan Cache. Para calcular la memoria total usada por los objetos que exponen cantidad de páginas, deberá multiplicar el valor por 8 (una página = 8Kb). Con estos contadores obtenemos cómo está desglosado el contenido de la memoria; como la memoria es un recurso limitado, debemos hacer seguimiento de cómo distribuye SQL Server la memoria entre cada uno de sus componentes. Por ejemplo, si vemos que la memoria utilizada para caché de procedimiento es alta, estaremos forzando a que otros componentes de SQL Server, como la memoria para página de datos, vean reducida su área de trabajo. Lo mismo sucede para otros componentes como la memoria de bloqueos, como veremos más adelante. Sin embargo, estos contadores de rendimiento no serán válidos si el servidor SQL Server tiene habilitado el uso de memoria mediante AWE; para estos casos deberá analizarlo con comandos DBCC como vemos a continuación. Comandos DBCC Para sistemas con AWE habilitado, el comando DBCC MEMORYSTATUS devuelve información más precisa relativa a la distribución de la memoria; aunque la información presentada varía mucho entre la versión 2000 y la versión 2005, los valores que deseamos comprobar se encuentran presenten en ambas versiones. El comando devuelve una instantánea del reparto de memoria de SQL Server. Información sobre el comando se puede encontrar en los documentos de KB de Microsoft referenciados al final del artículo ([1] y [2]). En nuestro caso utilizaremos la información que muestra la versión 2000. El primer conjunto de resultados puede aparecer como se ve en la tabla 2. Buffer Distribution Stolen Free Procedures Buffers 4290 388 13510 Inram 0 Dirty 4238 Kept I/O Latched Other 0 0 168 19436 Tabla 2 La columna buffers está expresada en páginas de 8Kb, y la columna buffer distribution indica: • Stolen, buffers reservados para ordenaciones, operaciones hash, bloqueos, transacciones, etc. • Free, buffers disponibles para usar. • Procedures, buffers usados para caché de procedimiento: planes de ejecución, contextos de ejecución de procedimientos, etc. • Inram, buffers “pinned”. En desuso, se puede hacer que una tabla permanezca en memoria con el comando DBCC PINTABLE (en desuso). • Dirty, buffers con datos modificados que todavía no se han volcado a disco. • Kept, sin uso en SQL Server 2000, 2005. • I/O, buffers a la espera de completar operación de I/O. • Latches, buffers adquiridos para operaciones de latches (bloqueos para garantizar la consistencia física del medio). • Other, el resto de los buffers; es decir páginas de datos confirmados, y páginas de índices principalmente. En la tabla 2 podemos ver que casi la mitad de los buffers se utilizan para caché de procedimiento. Este es un caso Cómo gestiona SQL Server el caché de procedimiento No voy a explicar el funcionamiento completo del caché de procedimiento porque me llevaría más de un artículo, pero pretendo que se quede con la idea de qué hace SQL Server con el caché de procedimiento cuando recibe peticiones de consultas: • Cuando llega una consulta a SQL Server (consulta ad hoc, llamada a procedimiento almacenado, consulta parametrizada, etc.), lo primero que hace es validar si existe una coincidencia de la consulta en caché; en caso que no exista, la consulta se compila, se genera su plan de ejecución, se guarda el plan en caché, y a continuación se procesa la consulta. En el momento en que el plan se guarda en caché, queda disponible para que otras conexiones puedan utilizarlo. • ¿Qué pasaría si llega el mismo patrón de ejecución de nuevo? En lugar de recompilarla, el servidor reutilizará la que ya tiene en caché. Veamos en qué consiste el patrón de ejecución de las consultas con algunos ejemplos: 1. Select id, cantidad from dbo.Orders where id = 1 2. Select id, cantidad from dbo.Orders where id = 2 3. Select id, cantidad from dbo.Orders where id = [par0] 4. Exec dbo.ObtenerPedidos @par0 = 1 5. Exec dbo.ObtenerPedidos @par0 = 2 Para SQL Server las consultas 1 y 2 suponen dos planes de ejecución diferentes; sin embargo, si las consultas 1 y 2 hubieran sido parametrizadas, habrían utilizado el plan de ejecución “genérico” 3. Por otro lado, las consultas 4 y 5 de igual manera comparten el mismo plan de ejecución porque los argumentos son parametrizados. Alrededor de este proceso <<dotNetManía SQLServer:Buffer Manager Total pages 37 << dnm.servidores.sql hay políticas que sigue SQL Server para invalidar planes de ejecución, auto-parametrización de consultas, recompilación, etc., que se pueden consultar en los documentos de referencia [4]. Fíjese que esta estrategia es parecida a la que seguimos en el artículo anterior referente a la búsqueda de patrones de ejecución de consultas :-). Veamos ahora cuál es el contenido del caché de procedimiento; para ello usaremos las vistas de sistema que tenemos en SQL Server, tanto 2000, como 2005. La misma consulta en SQL Server 2000, sería la siguiente: select c.usecounts, c.cacheobjtype, c.objtype, c.sql from master.dbo.syscacheobjects c Analicemos las columnas que devuelve la consulta: • Usecounts: número de veces que se ha usado el plan desde el momento en que se insertó en caché. • Cacheobjtype : tipo de objeto de caché almacenado; puede ser plan compilado, plan ejecutable, árbol relacional, procedimiento almacenado extendido… • Objtype : el tipo de objeto referenciado; valores como consulta ad-hoc, vista, procedimiento almacenado, trigger, sentencia preparada..., son algunos de los valores que puede tener. • Text (“sql” en SQL Server 2000): los primeros 3.900 caracteres de la sentencia interpretada que se ejecutó. [ ] NOTA Desde la versión 7.0 de SQL Server, Microsoft dejó de dar soporte al comando DBCC MEMUSAGE;la idea del comando era muy interesante porque reportaba los 20 objetos que más memoria usaban,sin embargo,si hace uso del comando estará corriendo un riesgo que debería analizar si está dispuesto a asumir; en la lista de recursos puede ver el documento de KB relacionado [3] Vistas de sistema de SQL Server <<dotNetManía Para ver el contenido de la caché de procedimientos usaremos la vista de sistema syscacheobjects que se encuentra en la base de datos master. En la versión 2005 también se puede consultar, pero se recomienda hacerlo a través de las vistas dinámicas de administración (DMV) sys. dm_exec_cached_plans, y sys.dm_exec_sql_ text. Son vistas muy descriptivas sobre la información que contienen; quizás la única novedad en SQL Server 2005 es que para “cruzar” ambas vistas haremos uso del nuevo operador CROSS APPLY de la siguiente forma: 38 select c.usecounts, c.cacheobjtype, c.objtype, s.text from sys.dm_exec_cached_plans c cross apply sys.dm_exec_sql_text (c.plan_handle) s Generalmente buscamos la frecuencia con que se reutilizan los planes de ejecución y ése es un valor que nos da la columna usecount. Si el valor de usecount es muy bajo indica que ese plan de ejecución es muy poco reutilizado. ¿Qué quiere decir esto? Que SQL Server tuvo que soportar el coste de compilar el plan de ejecución de la consulta, ponerlo en caché, y luego se reutilizó muy poco. Este es un caso típico que se produce en aplicaciones cliente que envían consultas ad hoc al servidor. La consulta ad hoc, normalmente, tiene que pasar por el proceso de compilación excepto en los casos de autoparametrización. Sin embargo, usando procedimientos almacenados, al tener su plan de ejecución en caché, no es necesario recompilarlos (la excepción es el uso de la opción WITH RECOMPILE, o invalidación del plan por estadísticas desactualizadas de los objetos asociados al procedimiento almacenado). En el siguiente artículo de esta serie, analizaremos los casos en los que pueda ser recomendable recompilar planes de ejecución y buscaremos solucio- nes a potenciales problemas del uso de planes de ejecución en caché no óptimos para todos los tipos de llamadas. Bloqueos Otro de los problemas frecuentes que encontramos en nuestros clientes son esperas causadas por bloqueos; como deben recordar del primer artículo de la serie, si tuviera problemas de bloqueos, habrían sido reportados con los comandos DBCC y DMV relacionados con waitstats. Sin embargo, estos problemas suelen ser solucionados con estrategias adecuadas de indexación. Hasta ahora hemos estado hablando de minimizar el número de lecturas que debe hacer el sistema de discos; normalmente se consiguen buenos resultados optimizando las consultas más frecuentes; a su vez, esto supondría que el sistema procesaría las consultas en menos tiempo y, por lo tanto, bloquearía menos tiempo recursos de SQL Server como tablas, índices, filas, etc. Sin embargo, habrá ocasiones en que existen pequeños bloqueos que necesita detectar y, al ser tan pequeños, no estarían reportados en las consultas patrones creadas en el artículo anterior. Para ello utilizaremos la técnica que vamos a explicar en la siguiente sección. Cómo detectar bloqueos La vista de sistema master.dbo.sysprocesses expone información sobre las conexiones que están activas en el servidor; las conexiones de usuario comienzan a partir de spid 51; los valores anteriores a 51 (no quiere decir que utilice todos), SQL Server se los reserva para procesos dedicados a tareas específicas, por ejemplo proceso de checkpoint, proceso de truncado de registro de transacciones, proceso de localización de abrazos mortales, etc. En SQL Server 2005, la DMV que expone la información que necesitamos es sys.dm_exec_ requests. Concretamente lo que estaremos buscando será la columna blocked en la versión 2000 y la columna blocking_ session_id en la versión 2005. Dichas columnas indican cuál es el proceso que está bloqueando al actual, por lo que intentaremos buscar lo siguiente: << dnm.servidores.sql Id_conexión Id_bloqueador sql_conexion sql_bloqueador 53 55 select * from dbo.tabla where condicion delete from dbo.tabla where condicion 54 55 update dbo.tabla where condicion delete from dbo.tabla where condicion 56 55 select * from dbo.tabla where condicion delete from dbo.tabla where condicion 52 55 select * from dbo.vista where condicion delete from dbo.tabla where condicion poder hacer una operación cross apply con la DMV sys.dm_exec_sql_text de la que obtenemos la sentencia SQL que se está ejecutando en ese momento. El resto de la consulta realiza la misma operación, pero en este caso para obtener información sobre el proceso bloqueador. Conclusiones Tabla 3 En este caso concreto, la conexión 55 está bloqueando a los procesos 52, 53, 54 y 56. Fíjese que la conexión 55 está bloqueando la tabla dbo.tabla y no permite que pueda ser accedida por el resto de peticiones (incluso una vista). Ahora que conocemos cuál es el resultado que queremos obtener, debemos definir: • La frecuencia con que se ejecuta el análisis. El ejemplo será cada 2 minutos. • El tiempo de duración de los bloqueos. En el ejemplo será 20 segundos. • Dónde se reportan los bloqueos localizados. El proceso será encapsulado en un procedimiento almacenado, que con una frecuencia de 2 minutos “buscará” procesos bloqueados en el sistema; además tomará una muestra de los procesos que se encuentran bloqueados (la columna blocked o blocking_ session_id) y, pasados 20 segundos, se tomará otra muestra para ver si todavía siguen bloqueados, en cuyo caso se tomarán las medidas correspondientes de auditoría. En este artículo hemos visto cómo analizar la distribución de la memoria de SQL Server entre los componenEl pseudocódigo del proceso sería el siguiente: tes del motor. También hemos aprendido a ver el contenido del caché de <cada 2 minutos> procedimiento e identificar la frecuen<capturar_procesos_bloqueados en v1> cia de uso de los planes de ejecución <esperar 20 segundos> localizados en memoria. Asimismo <capturar_procesos_bloqueados en v2> hemos aprendido a localizar procesos <si procesos bloqueados en v1 y v2> <auditar/reportar estado> que intervienen en bloqueos, desglosando el bloqueo en dos partes: el proceso select cur1.session_id, cur1.blocking_session_id, que bloquea y los prosql1.text sql_bloqued, sql2.text sql_bloquer cesos que sufren el blofrom sys.dm_exec_requests cur1 queo; de esta forma se join @t last pueden desarrollar on cur1.session_id = last.session_id cross apply sys.dm_exec_sql_text(cur1.sql_handle) sql1 prácticas de auditoría left join sys.dm_exec_requests cur2 en sus sistemas para on cur2.session_id = last.blocking_session_id detectar largos tiempos outer apply sys.dm_exec_sql_text(cur2.sql_handle) sql2 de ejecución causados por bloqueos. Fuente 1 El código completo lo puedes encontrar en [5], sin embargo vamos a explicar su parte más importante (ver fuente 1). La variable de tabla @t representa las conexiones bloqueadas y sus bloqueadores. Su resultado se cruza con la DMV sys.dm_exec_requests para obtener el handler (referencia a la consulta en ejecución) de la sesión, y así Referencias INF: Using DBCC MEMORYSTATUS to [1] Monitor SQL Server Memory Usage http://support.microsoft.com/kb/271624/en-us How to use the DBCC MEMORYSTATUS command to monitor memory usage on SQL [2] Server 2005. http://support.microsoft.com/ kb/907877/en-us BUG: DBCC MEMUSAGE Is Not Supported in SQL Server 7.0. http://support. [3] microsoft.com/default.aspx?scid=kb; en-us;196629 ] Fíjese que se hace una operación left join con el proceso bloqueador porque es posible que el proceso que está bloqueando no se encuentre en ejecución. Para finalizar, el proceso puede rellenar los resultados en una tabla para analizarlo posteriormente, puede enviar un correo electrónico a una lista de destinatarios, o incluso se puede configurar para matar al proceso que está causando los bloqueos con el comando KILL. Mi recomendación es registrarlo en una tabla para posteriormente analizar (y tirar del hilo),para encontrar el proceso de negocio asociado a los bloqueos. Batch Compilation, Recompilation, and Plan Caching Issues in SQL Server 2005. [4] http://www.microsoft.com/technet/prodtechnol/ sql/2005/recomp.mspx Cómo capturar procesos bloqueadores y procesos bloqueados en SQL Server 2005. http://siquel[5] net.etraducciones.com/default.aspx?Tema=MSS QL05&Seccion=ADM05&Articulo=003.xml Hands-On SQL Server 2000 Troubleshooting: Locking and blocking de NetImpress. eBook escrito por Kalen Delaney en el que ana[6] liza todos los pormenores de los bloqueos, tipos de bloqueos, captura de bloqueos y abrazos mortales. Sólo se puede adquirir en formato electrónico en librerías virtuales. <<dotNetManía [ NOTA 39 dnm.inicio.fundamentos dnm.incio.taller Guillermo “Guille” Som Acceso a datos con ADO.NET 2.0 (sin asistentes) Tal como comentamos en el número anterior, en esta ocasión vamos a ver cómo podemos acceder a una base de datos usando única y exclusivamente código, es decir, sin usar los asistentes que Visual Studio 2005 pone a nuestra disposición y que, en honor a la verdad, a muchos les facilitará la tarea de crear aplicaciones ADO.NET de una forma bastante sencilla. Como pudimos comprobar en el número anterior, crear un formulario para acceder a una tabla o a un procedimiento almacenado es muy fácil si nos apoyamos en los asistentes de acceso a datos que Visual Studio 2005 (y con sus limitaciones, las versiones Express) pone a nuestra disposición. Pero algunos programadores de la “vieja escuela” preferimos o nos gusta más escribir código para obtener casi la misma funcionalidad. Por tanto, en esta ocasión vamos a crear un proyecto en el que tendremos la misma funcionalidad que vimos en el número anterior, pero escribiendo todo el código de forma manual. Hacerlo de esta forma no es solo por capricho o masoquismo, sino porque así tendremos una perspectiva diferente que nos permitirá entender mejor cómo realizar las tareas comunes de acceso a datos con ADO.NET 2.0. Detalles del proyecto que realizaremos usando solo código Guillermo “Guille” Som es Microsoft MVP de Visual Basic desde 1997. Es redactor de dotNetManía, miembro de Ineta Speakers Bureau Latin America, mentor de Solid Quality Learning Iberoamérica y autor del libro Manual Imprescindible de Visual Basic .NET. http://www.elguille.info Como hemos comentado anteriormente, crearemos un proyecto que nos permitirá hacer, de forma manual, lo mismo que hicimos en el número anterior. Y para facilitar la tarea, vamos a relacionar los pasos que seguiremos para conseguir nuestro propósito, aunque antes resumiremos brevemente qué funcionalidad tendremos en nuestro proyecto. El proyecto nos permitirá acceder a una base de datos creada con SQL Server 2005 que estará definida en la instancia de SQLEXPRESS. Esa base de datos será la mis- ma que usamos en el número anterior (pruebaGuille) y que podremos crear usando una utilidad que incluimos en el ZIP con el código de ejemplo. Crearemos dos formularios; uno de ellos nos permitirá mostrar, modificar y añadir nuevos datos, y el formato que usaremos consistirá en mostrar cada campo de la tabla (Prueba) en una caja de texto. Además tendremos un segundo formulario en el que mostraremos los datos en un control DataGridView; esos datos los obtendremos por medio de un procedimiento almacenado (StoredProcedure1) al que le indicaremos la fecha a partir de la que queremos mostrar dichos datos. Preparativos para realizar la conexión a la base de datos Para poder acceder a los datos, tendremos que conectarnos a la base de datos que será del tipo SQL Server 2005, creada en la instancia de SQL Express, aunque no necesariamente tiene por qué ser así. Para realizar dicha conexión, tendremos que establecer la cadena de conexión que le indicará a ADO.NET las características de la base de datos a acceder. Dicha cadena será la siguiente: Data Source=(local)\SQLEXPRESS; Initial Catalog=pruebaGuille; Integrated Security=True Particularmente, tendremos que crear un objeto de la clase SqlDataAdapter del espacio de nombres <<dotNetManía << Acceso a datos sin asistentes 41 << dnm.inicio.taller SqlClient. Entre otras cosas, a ese objeto le podemos pasar la mencionada cadena de conexión, además de la selección de los datos que queremos manipular. La selección de datos que haremos será la de todas las columnas y todas las filas de la tabla Prueba, quedando dicha cadena de esta forma: using sinAsistentesCS.Properties; Esto nos permitirá acceder a ese valor de la siguiente forma: string cadenaConexion = Settings.Default.conexionGuille; SELECT * FROM Prueba Esta cadena la podemos adaptar a los datos que queramos manipular, y no solo podemos indicarla como una sentencia “directa” sino que también podemos usar un procedimiento almacenado que hayamos definido en nuestra base de datos. En este primer ejemplo “manual” o sin asistentes usaremos un procedimiento almacenado para seleccionar los datos que se hayan modificado a partir de una fecha. En una próxima ocasión veremos más ejemplos en los que usaremos procedimientos almacenados no solo para mostrar o recuperar los datos, sino también para realizar operaciones de actualización, etc. Incluso crearemos esos procedimientos almacenados usando código de C# (y de VB), pero por ahora es preferible dejar las cosas simples. La cadena de conexión la vamos a guardar en los datos de configuración de la aplicación. Para ello usaremos la ficha “Configuración” de las propiedades de la aplicación. Tal como podemos ver en la figura 1, en el nombre asignaremos conexionGuille y en el ámbito seleccionaremos “Aplicación”; esto hará que se añada a nuestro proyecto un fichero llamado app.config que será el que contenga todos los valores añadidos con el ámbito de aplicación; esos valores serán de solo lectura. <<dotNetManía Figura 1.Asignar la cadena de conexión a las propiedades de configuración. 42 Para acceder a los valores de configuración podemos agregar una importación del espacio de nombres Properties que estará incluido en el espacio de nombres de nuestra aplicación. Por ejemplo, si el espacio de nombres predeterminado es sinAsistentesCS, tendremos que añadir la siguiente línea al principio de los ficheros de código en los que vayamos a usar esos datos de configuración: Si no añadimos esa importación tendremos que acceder a los valores de configuración indicando el espacio de nombres en el que está definida la clase Settings: string cadenaConexion = Properties.Settings.Default.conexionGuille; [ NOTA En Visual Basic 2005, los datos de configuración están incluidos en My.Settings, y podemos acceder a la cadena de conexión usando: Dim cadenaConexion As String = My.Settings.conexionGuille ] Realizar la conexión a la base de datos Una vez que tenemos preparada la cadena de conexión a la base de datos que queremos usar, es hora de preparar las clases de ADO.NET que nos permitirán realizar la conexión y el acceso real a esos datos. Inicialmente necesitaremos un objeto del tipo SqlDataAdapter, que será el que se encargue de conectar a la base de datos. También necesitaremos un objeto de tipo DataSet o DataTable, el cual recibirá los datos que indiquemos en la cadena de selección. Debido a que solo accederemos a los datos de una tabla, nos resultará más simple usar un objeto del tipo DataTable, ya que un objeto DataSet, entre otras cosas, puede contener varias tablas, las relaciones entre ellas, etc.; por tanto no lo necesitaremos en esta ocasión. En el fuente 1 podemos ver el código necesario para realizar la conexión a la base de datos indicada en el parámetro de configuración conexionGuille que anteriormente asignamos en las propiedades de la aplicación; esa cadena de conexión la indicamos en el consstring cadenaConexion = Properties.Settings.Default.conexionGuille; string sel = “SELECT * FROM Prueba”; da = new SqlDataAdapter(sel, cadenaConexion); dt = new DataTable(); da.Fill(dt); Fuente 1. Creamos los objetos que usaremos para acceder a los datos de la base de SQL Server. << dnm.inicio.taller tructor del objeto SqlDataAdapter, al que también le indicamos la cadena de selección con idea de que sepa qué datos debe traer de la base de datos para asignarlos al objeto DataTable, acción que indicamos mediante el método Fill del adaptador. Crear los comandos de actualización, inserción y eliminación SqlCommandBuilder cb = new SqlCommandBuilder(da); Si usamos una tabla en la que tenemos un índice automático, debemos asignar a la propiedad MissingSchemaAction del DataAdapter el valor AddWithKey, de forma que se genere automáticamente el valor del campo autoincremental. La asignación la haremos de esta forma: da.MissingSchemaAction = MissingSchemaAction.AddWithKey; Figura 2. El formulario principal en modo de diseño tros, se guardarán los cambios que hayamos hecho. Pero si no queremos disponer de esta funcionalidad “auto-asignadora”, podemos quitar la marca de ese control y será responsabilidad nuestra si guardamos o no los cambios que realicemos. Para ese caso, tenemos el botón de actualizar (la imagen con un disquete). Por supuesto, esas asignaciones se harán solo si los datos realmente han cambiado, comprobación que hacemos cada vez que cambia el contenido de las cajas de textos o el control DateTimePicker. Cuando los eventos de cambio de esos controles se disparan, lo que hacemos es comprobar si realmente el contenido ha cambiado (ver el fuente 2), de forma que si se vuelve a dejar el mismo contenido que había antes, el registro no debe marcarse como modificado. private bool comprobarCambiado() { bool cambiado = false; Dar funcionalidad a la aplicación Una vez que tenemos los datos en el objeto DataTable, ya solo nos queda mostrar los datos, añadir nuevos, eliminar y actualizar los cambios y, cuando creamos conveniente, guardar esos cambios en la base de datos. Debido a que no estamos usando un asistente, será nuestro trabajo la creación completa de la interfaz del usuario, por tanto tendremos que agregar los controles en los que mostraremos los datos, así como los botones que nos permitirán navegar por los registros de la tabla que vamos a utilizar. Nuestro formulario de prueba tendrá el aspecto mostrado en la figura 2, que como podemos comprobar es muy parecido al que el propio asistente de Visual Studio 2005 crearía. Aunque en esta aplicación de ejemplo hay ciertos cambios, y no nos referimos solo a cambios en las imágenes usadas, o en el número de botones. En esta aplicación usaremos un control CheckBox para indicar si queremos asignar automáticamente los cambios que realicemos a los datos de la tabla; de esta forma, cada vez que nos desplacemos entre los regis- if( txtNombre.Text != dt.Rows[filaActual][“Nombre”].ToString()) cambiado = true; if( txtEmail.Text != dt.Rows[filaActual][“e-mail”].ToString() ) cambiado = true; if( Convert.ToDateTime( txtFechaAlta.Text).Date.CompareTo( Convert.ToDateTime( dt.Rows[filaActual][“FechaAlta”]).Date) != 0 ) cambiado = true; if( txtComentario.Text != dt.Rows[filaActual][“Comentario”].ToString()) cambiado = true; return cambiado; } Fuente 2. La función que comprueba si se ha modificado el contenido de las cajas de texto usadas para introducir los datos Moverse por los registros de la tabla, actualizando si es necesario Como podemos comprobar en el código del fuente 2, tenemos una variable (filaActual) que controla la fila o registro con el que estamos trabajando en cada momento, y es por medio de esa variable con la que <<dotNetManía Si nuestra intención es poder añadir, eliminar y modificar los datos que manipularemos, tenemos que indicar los comandos correspondientes para estas tres acciones. Esos comandos (que no son otra cosa que instrucciones de Transact-SQL), los podemos crear de forma automática por medio de la clase SqlCommandBuilder, a cuyo constructor le pasaremos un objeto del tipo SqlDataAdapter. Los mencionados comandos se crearán basándose en la cadena de selección que hemos utilizado, pero de esos detalles no tenemos que preocuparnos, ya que lo único que tenemos que hacer es algo como esto: 43 << dnm.inicio.taller navegamos usando los primeros cuatro botones de la barra de herramientas. En cada método de evento de esos botones hacemos la asignación correspondiente para mantener adecuadamente el valor de la fila actual, y después simplemente llamamos a un método que será el que se encargue de mostrar la información en las cajas de texto correspondientes. En ese mismo método (que podemos ver en el fuente 3), hacemos ciertas comprobaciones adicionales, con idea de que el valor de la fila actual esté en el rango adecuado, además de comprobar si tenemos que guardar los datos o no. private void btnPrimero_Click(object sender, EventArgs e) { filaActual = 0; mostrarDatos(); } private void btnAnterior_Click(object sender, EventArgs e) { filaActual—; mostrarDatos(); } private void btnSiguiente_Click(object sender, EventArgs e) { filaActual++; mostrarDatos(); } private void btnUltimo_Click(object sender, EventArgs e) { filaActual = dt.Rows.Count - 1; mostrarDatos(); } Como podemos comprobar, será en el método mostrarDatos en el que tendremos que escribir el códi- go necesario para mostrar los datos en los controles. Como es de suponer, si la fila que intentamos mostrar está eliminada, simplemente salimos sin mostrar nada, aunque debemos comprobar a qué fila debemos desplazarnos; esa parte la veremos a la hora de eliminar los registros. En ese mismo método asignamos el valor a otra variable (filaAnt) que nos será de utilidad en el caso de que haya cambiado el contenido de los controles, y la usaremos para indicar en qué fila debemos hacer la asignación de dichos cambios. Esta comprobación la hacemos en el método comprobarActualizar, desde el que llamamos al método actualizarDatos, que recibe como parámetro la fila que hay que actualizar, tal como podemos comprobar en el fuente 4. private void comprobarActualizar() { if(chkActualizarAuto.Checked && modificado && (filaActual != filaAnt)) actualizarDatos(filaAnt); } private void actualizarDatos(int fila) { dt.Rows[fila][“Nombre”] = txtNombre.Text; dt.Rows[fila][“e-mail”] = txtEmail.Text; dt.Rows[fila][“FechaAlta”] = Convert.ToDateTime(txtFechaAlta.Text); dt.Rows[fila][“Comentario”] = txtComentario.Text; modificado = false; btnGuardarEnBase.Enabled = true; } private void mostrarDatos() { if( dt.Rows.Count < 1 ) return; if( filaActual < 0 ) filaActual = 0; if( filaActual >= dt.Rows.Count - 1 ) filaActual = dt.Rows.Count - 1; if(dt.Rows[filaActual].RowState == DataRowState.Deleted) { // TODO: Comprobar a qué fila podemos desplazarnos return; } comprobarActualizar(); filaAnt = filaActual; <<dotNetManía txtID.Text = dt.Rows[filaActual][“ID”].ToString(); txtNombre.Text = dt.Rows[filaActual][“Nombre”].ToString(); txtEmail.Text = dt.Rows[filaActual][“e-mail”].ToString(); txtFechaAlta.Text = dt.Rows[filaActual][“FechaAlta”].ToString(); txtComentario.Text = dt.Rows[filaActual][“Comentario”].ToString(); 44 txtActual.Text = (filaActual + 1).ToString(); modificado = false; Fuente 4.El código para asignar los cambios a la fila correspondiente y el que comprueba si se deben actualizar los datos Como vemos, también hay un solo método en el que hacemos todo lo necesario para asignar los cambios a la fila que se ha modificado. El método actualizarDatos recibe un parámetro con el índice de la fila modificada porque nos servirá también en caso de que pulsemos en el botón “Actualizar”, aunque en ese caso, el registro que debemos asignar es el de la fila actual (ver fuente 5). Por esa razón, en vez de usar una de las variables “globales” hemos optado por usar un parámetro. private void btnActualizar_Click(object sender, EventArgs e) { actualizarDatos(filaActual); } Fuente 5. El método del evento del botón para actualizar Eliminar y crear nuevos registros } Fuente 3. Los métodos de navegación y el encargado de mostrar los datos en los controles Las otras dos acciones que utilizaremos para eliminar datos o para crear nuevos en principio no tienen << dnm.inicio.taller mayores complicaciones; al menos la de crear nuevos datos, ya que simplemente añadiremos una nueva fila a la colección de filas de la tabla. Esa acción, tal como vemos en el fuente 6, consiste en obtener una nueva fila (DataRow) que nos proporciona el objeto DataTable, asignar los valores predeterminados que creamos conveniente y finalmente añadirla a la colección Rows. private void btnNuevo_Click(object sender, EventArgs e) { // Comprobar si los datos actuales hay que guardarlos automáticamente comprobarActualizar(); DataRow dr = dt.NewRow(); dr[“Nombre”] = “Nuevo”; dr[“FechaAlta”] = DateTime.Now; dt.Rows.Add(dr); btnGuardarEnBase.Enabled = true; habilitarBotones(); btnUltimo.PerformClick(); } Fuente 6. El código para crear nuevos registros A la hora de eliminar registros tampoco tendremos que hacer demasiado, ya que como vemos en el fuente 7, solo tenemos que llamar al método Delete de la fila actual. private void btnBorrar_Click(object sender, EventArgs e) { // Eliminar la fila actual // Comprobar si los datos actuales hay que guardarlos automáticamente comprobarActualizar(); // Confirmar el borrado if( MessageBox.Show(“...”) == DialogResult.Yes ) { dt.Rows[filaActual].Delete(); if( dt.Rows[filaActual].RowState == DataRowState.Deleted ) { // Comprobar a qué fila podemos desplazarnos // Si la primera está borrada, buscar la siguiente que no lo esté if( filaActual == 0 ) { for( int i = filaActual + 1; i < dt.Rows.Count; i++ ) { if( dt.Rows[filaActual].RowState == DataRowState.Deleted ) { filaActual++; } else { filaActual—; break; } } btnSiguiente.PerformClick(); return; } else { // Si la última está borrada, buscar la anterior que no lo esté if( filaActual == dt.Rows.Count - 1 ) { for( int i = filaActual - 1; i >= 0; i— ) { if( dt.Rows[filaActual].RowState == DataRowState.Deleted ) { filaActual—; } else { filaActual++; break; } } btnAnterior.PerformClick(); return; } } if( (filaActual - filaAnt) >= 0 ) btnSiguiente.PerformClick(); else btnAnterior.PerformClick(); btnGuardarEnBase.Enabled = true; return; modificado = false; btnSiguiente.PerformClick(); } } Fuente 8. Comprobación a incluir en el método mostrarDatos, de qué fila está disponible cuando hemos eliminado algunas } Fuente 7. El método para eliminar registros Para que todo funcione correctamente, debemos cambiar la comprobación de si la fila está eliminada que mostramos en el fuente 3 por la del código fuente 8, de esa forma no entraremos en un bucle sin fin que finalmente resultaría en un error de desbordamiento de la pila (stack overflow). Guardar los cambios realizados en la base de datos La forma en que estamos tratando los datos es de forma desconectada, es decir, esos datos los estamos mani- <<dotNetManía Como vemos, el problema de eliminar registros no está en la forma de eliminarlos, sino a la hora de navegar entre los registros, ya que es posible que nos encontremos con un registro eliminado, en cuyo caso no debemos mostrarlo. En realidad, el problema nos lo podremos encontrar cuando queramos navegar al primero o al último y éstos estén eliminados, o incluso si hay varios seguidos que están eliminados. Por tanto, en el método mostrarDatos debemos tener en cuenta estas posibilidades y no “intentar” mostrar los datos de los registros eliminados. 45 << dnm.inicio.taller pulando en nuestro equipo, pero los cambios no se están reflejando en la base de datos. Por tanto, si queremos que todos esos cambios se hagan efectivos en la base de datos, debemos pulsar en el botón con el icono de varios disquetes. Desde el método gestor de ese evento le indicaremos al DataAdapter que use las instrucciones de actualización, eliminación o inserción que correspondan, lo cual logramos llamando al método Update del objeto SqlDataAdapter pasándole como parámetro la tabla que contiene las filas modificadas, y finalmente le indicaremos a la tabla que acepte los cambios. Todo esto lo hacemos por medio de dos líneas de código, tal como podemos ver en el fuente 9. private void btnGuardarEnBase_Click(object sender, EventArgs e) { try { // Comprobar si los datos actuales hay que guardarlos automáticamente comprobarActualizar(); da.Update(dt); dt.AcceptChanges(); btnGuardarEnBase.Enabled = false; } catch(Exception ex) { MessageBox.Show(“Error al guardar los datos en la base\n” + ex.Message, “Error”); } private void btnBuscar_Click(object sender, EventArgs e) { string cadenaConexion = Properties.Settings.Default.conexionGuille; try { SqlDataAdapter da = new SqlDataAdapter(“StoredProcedure1”, cadenaConexion); da.SelectCommand.CommandType = CommandType.StoredProcedure; da.SelectCommand.Parameters.Add(“@Param1”, SqlDbType.DateTime); da.SelectCommand.Parameters[“@Param1”].Value = Convert.ToDateTime(txtFecha.Text); DataTable dt = new DataTable(); da.Fill(dt); if( dt.Rows.Count > 0 ) { dgvDatos.DataSource = dt; habilitarBotones(true); } else { dgvDatos.DataSource = null; habilitarBotones(false); } filaActual = filaAnt = 0; mostrarDatos(); } catch(Exception ex) { MessageBox.Show(“Error\n\n” + ex.Message, “Error”); } } Fuente 10. El método para buscar datos usando un procedimiento almacenado } Fuente 9. Debemos guardar en la base de datos los cambios realizados localmente Mostrar los datos a partir de una consulta realizada con un procedimiento almacenado <<dotNetManía Por razones obvias de espacio no podremos ver con detalle la parte que nos falta de este proyecto: mostrar los datos por medio de una consulta usando un procedimiento almacenado de SQL Server; pero al menos veremos el código que tendremos que usar, que ejecu- 46 Figura 3. El formulario usado para mostrar los datos a partir de una fecha taremos desde otro formulario (ver figura 3) en el que tendremos un control DataGridView y los controles para navegar entre los registros mostrados, además de la caja de texto en la que indicaremos la fecha a usar para la consulta y el botón “Buscar” que será el encargado de asignar al grid los datos a mostrar. En el fuente 10 tenemos el código de ese método de búsqueda. Conclusiones Como hemos visto, no es tan complicado crear código para acceder a datos sin apoyarnos en los asistentes de Visual Studio 2005, y la ventaja es que sobre este código tenemos más control que en el caso del código generado de forma automática. Sí, tiene un poco de más trabajo, pero en realidad lo más laborioso es el tema del diseño del formulario de introducción de datos, el cual aunque lo generara el propio Visual Studio con sus asistentes seguramente acabaríamos modificando para adaptarlo a nuestro gusto. Pero gracias a los nuevos controles y nuevas ayudas del diseñador de formularios de Visual Studio 2005, esto será una tarea relativamente fácil. Como siempre, en el ZIP con el código completo del ejemplo usado en este artículo encontrarás tanto la versión para C# como para Visual Basic 2005. dnm.todotnet.qa Dino Esposito Informes, autenticación y actualización por lotes << ¿Cuántos de vosotros escribís o mantenéis aplicaciones Dino Esposito es mentor de Solid Quality Learning y autor de “Programming Microsoft ASP.NET 2.0 Core Reference” y “Programming ASP.NET 2.0 Applications Advanced Topics”, ambos de Microsoft Press.Afincado en Italia, Dino es un ponente habitual en los eventos de la industria a nivel mundial.Visite su blog en: http://weblogs.asp.net/despos. Puede enviarle sus consultas a [email protected] que generan informes semanal o mensualmente? Es una tarea común en muchas compañías y muchos campos de la industria. Hace unos años, Microsoft introdujo Reporting Services como un añadido a SQL Server 2000. Hoy la herramienta ha evolucionado y se acompaña con sendos controles Windows y Web que muestran los informes del servidor, pero son también capaces de realizar gran parte del procesamiento en el cliente con una mínima degradación de rendimiento. ¿Cómo crear informes imprimibles con ASP.NET? ¿Los Reporting Services de SQL Server son un requisito? Me gustaría crearlo como un PDF o una página Web navegable. En Visual Studio 2005, hizo su debut un nuevo control –el control ReportViewer–. Está diseñado para permitirte añadir características avanzadas de generación de informes en las aplicaciones. Existen dos versiones del control, para aplicaciones Windows y Web. Vamos a centrarnos en el control ASP.NET de servidor, ya que has mencionado esta opción expresamente. Sin embargo, el comportamiento del control Windows es muy similar. Como sugiere el nombre, el control ReportViewer muestra un informe al usuario, pero no suministra capacidades de manipulación de datos. Esto es, se precisa de la presencia de un origen de datos válido. A este respecto, funciona tanto en modo de procesamiento local o remoto. Cuando se trabaja en modo local, la definición del informe se toma de un fichero con extensión .rdlc. El fichero puede se referenciado por su nombre y ser local a la aplicación o funcionar como un recurso incrustado en el ensamblado. En este caso, el control abre una definición, la procesa y la carga en el área de visualización. En modo de procesamiento remoto, sin embargo, el control recupera un informe de un servidor con SQL Server 2005 Reporting Services instalado. Todo el procesamiento de datos e interpretación estructural de los mismos se realiza en el servidor y requiere de la presencia de informes publicados previamente. Para usar el visor de informes en modo remoto, se necesita una copia licenciada de SQL Server 2005 Reporting Services. El procesamiento remoto ofrece una mayor escalabilidad y rendimiento y ofrece características adicionales, tales como el uso de cachés y nuevos formatos de salida de informes. Demos un rápido paseo por el visor de informes, y veamos cómo se construye un informe local. Comenzamos por añadir un control ReportViewer a un formulario Web y establecer su propiedad ReportPath. La propiedad indica la fuente para el informe a mostrar. Para proceso local, debe ser un fichero con extensión .rdlc. ¿Cómo se crea? Añades un nuevo ítem al proyecto del tipo Informe (Report file). Después de abrir el RDLC para edición, los contenidos del cuadro de herramientas cambian para mostrar la lista de ítems disponibles. Añadamos una tabla y un objeto Chart. Lo siguiente es que tienes que especificar el origen de datos para el informe. Seleccionamos “Orígenes de Datos del sitio Web” y optamos por la opción “Crear un Nuevo Origen de Datos”. El familiar asistente nos guiará en los pasos necesarios para la creación de un DataSet con estructura, a partir de una consulta. Ahí se especifica la consulta a agregar e incluir desde la base de datos. Pongamos esta misma: <<dotNetManía Esta semana, la primera de las 3 preguntas de rigor resuelve problemas relacionados con Reporting en ASP.NET.Otras preguntas se centran en la autenticación por Internet y las actualizaciones por lotes en ADO.NET. 47 << dnm.laboratorio.net SELECT e.lastname AS Employee, SUM(price) AS Sales FROM (SELECT o.employeeid, od.orderid, SUM(od.quantity*od.unitprice) AS price FROM Orders o, [Order Details] od WHERE Year(o.orderdate) = @year AND od.orderid=o.orderid GROUP BY o.employeeid, od.orderid ) AS t1 INNER JOIN Employees e ON t1.employeeid=e.employeeid GROUP BY t1.employeeid, e.lastname1 Fuente 1 La consulta recupera la cantidad total de ventas para cada uno de los empleados de la base de datos Northwind en un año en concreto. Los datos recuperados muestran dos columnas, Employee (tipo String) y Sales (tipo double). Para mostrar los resultados de la consulta en el área de la tabla del informe, arrastramos los nombres de las columnas desde la ventana del explorador de orígenes de datos. De igual forma, debemos seleccionar qué columnas suministran los datos para las series y cuáles las de las categorías. En este punto la definición del informe está terminada. Puede mejorársele, posteriormente, incluyendo algún gráfico o información de estilo. Para ser precisos, el informe simplemente contiene información de correspondencia entre un origen de datos concreto y sus áreas visuales constituyentes: la tabla y el objeto Chart. La vinculación física del informe con sus datos sucede a través del visor de informes. El siguiente código de marcado expresa la relación entre ambos: <rsweb:ReportViewer ID="ReportViewer1" runat="server" Width="100%"> <LocalReport ReportPath="Samples\Core\Live\MyReport.rdlc"> <DataSources> <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="DataSet2_Employees" /> </DataSources> </LocalReport> </rsweb:ReportViewer> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetData" TypeName="DataSet2TableAdapters.EmployeesTableAdapter"> <SelectParameters> <asp:Parameter DefaultValue="1997" Name="year" Type="Decimal" /> </SelectParameters> </asp:ObjectDataSource> <<dotNetManía Fuente 2 48 El visor de informes está enlazado a uno o más controles ObjectDataSource, cada uno de ellos apuntando a un adaptador de tabla o a un objeto de negocio definido por el usuario. El visor de informes puede enlazar múltiples orígenes de datos debido a que –a su vez– el informe puede contener varias vistas de datos, mostrando distintos conjuntos de información. La figura 1 muestra un informe simple en una página ASP.NET. Como puede verse, la salida del control en pantalla contiene una barra de herramientas donde puede navegarse para seleccionar el formato de expor1 Figura 1. Un informe simple, mostrado mediante el control ReportViewer tación a PDF o Excel. Como ya hemos mencionado, hay más formatos disponibles (así como servicios de caché) si el informe se genera mediante Reporting Services. Estamos construyendo una aplicación Web y queremos que cualquier usuario se autentique de forma automática en ASP.NET utilizando su propia cuenta de acceso. Todos los ejemplos de autenticación Forms que hemos encontrado usan una base de datos para comprobar las credenciales. ¿Qué estamos haciendo mal? En teoría, las aplicaciones ASP.NET soportan cuatro modos de autenticación: None, Passport, Windows y Forms. Se selecciona el adecuado en el fichero Web.Config a través de la sección <authentication> en su atributo mode. En su conjunto, solo tienen sentido los dos últimos para la mayoría de aplicaciones Web. El modo None, significa que no hay autenticación de ninguna clase. De cualquier forma, se trata de una forma recomendada para aplicaciones de carácter anónimo ya que deshabilita el módulo de autenticación haciendo que el proceso de solicitud sea más rápido. El modo Passport requiere que el usuario haya pasado por el proceso de adhesión a la iniciativa Passport, y, cuando se requiera autenticación, el usuario es redirigido al sitio Web de Passport donde se comprueban sus credenciales. Olvida esta opción si estás construyendo una intranet o si la compañía no es parte del grupo Passport. Los dos modos restantes, –Windows y Forms– apuntan a escenarios distintos. El modo Forms es para aplicaciones Web en las que el código ASP.NET es el encargado de comprobar las credenciales contra un almacén de datos administra- Nota del traductor: tomada de la base de datos Northwind, que se instala de forma predeterminada en SQL Server 2000, pero no en SQL Server 2005. “ No hay razón estructural por la que una actualización por lotes no soporte actualizaciones multitabla ” añadida, borrada o modificada. Para cada estatus, define un comando ADO.NET (o procedimiento almacenado) y ejecuta el comando correspondiente para cada fila. Punto. No hay razón estructural por la que una actualización por lotes no soporte actualizaciones multitabla. Este tipo de actualización no se basa en ninguna característica oculta del sistema –es, solamente, código de ayuda escrito por algunos desarrolladores para ahorrar código a otros desarrolladores. ¿Por qué las actualizaciones por lotes ADO.NET solo soportan escenarios de actualización de tabla única? Porque fue diseñado de esta forma y porque hacerlo así simplifica notablemente el código necesario. ¿Qué puede hacerse? El método GetChanges() de la clase DataSet permite la selección de un array con todas las filas de una tabla con un estatus particular: añadida, borrada o modificada. De esta forma, es muy sencillo almacenar en distintos contenedores todas las filas borradas o actualizadas para cada tabla implicada. A continuación, llamas a una sobrecarga poco conocida del método Update en el adaptador asociado que –justamente– acepta un array de objetos DataRow. int Update(DataRow[] rows); Mediante la llamada a la sobrecarga de Update con varios arrays de objetos DataRow se nos permite construir nuestra propia lógica de actualización para múltiples tablas. Por ejemplo, dadas un par de tablas de Pedidos y Detalles_de_Pedidos, cuando el usuario solicita el borrado de un pedido puedes, primero, actualizar todas las filas de Detalles_de_Pedidos que están borradas en forma lógica y, posteriormente, actualizar las filas de Pedidos marcadas para borrado. Todavía se utilizan actualizaciones por lotes, pero usando tablas relacionadas. Con toda seguridad, este código parece código estándar que se implementa de forma manual. Por otra parte, se trata de una forma de atajo y no es practicable en todos los casos. Traducción por Marino Posadas <<dotNetManía do por el usuario. El modo Windows es para aplicaciones de intranet. Cuando IIS recibe una petición de ASP.NET, primero acredita al usuario utilizando el esquema de autenticación activo: Basic, Digest o Integrado con Windows. A continuación la clave de seguridad se pasa a ASP.NET junto con la petición. Lo que suceda a continuación depende de la configuración de la autenticación en ASP.NET. Cuando la autenticación es Windows, ASP.NET acepta la credencial enviada por IIS y copia la información al objeto Context de usuario. No se llevan a cabo más acciones de autenticación. Si la autenticación se establece a Forms, ASP.NET ignora la información enviada por IIS y procede con su propio sistema de autenticación. En la mayoría de aplicaciones de Intranet, cuando los usuarios se conectan se les solicita la credencial. Éstas son transmitidas al servidor (dependiendo el esquema de autenticación, en modo de texto plano o codificado) y validadas contra el grupo de usuarios autorizados. Si configuras IIS para soportar Windows Integrado, no aparece ninguna caja de diálogo, sino Internet Explorer y la información introducida es transmitida al servidor automáticamente sin intervención posterior. En este punto, si ASP.NET se configura como autenticación Windows, el nombre de login del usuario se utiliza para rellenar el campo Name del objeto User, siempre que éste sea reconocido y aceptado por el servidor Web. En suma, para obtener el comportamiento deseado tienes que habilitar la opción “Integrada con Windows” como esquema de autenticación IIS y dejar el modo autenticación ASP.NET en su forma predeterminada –Windows. Por último, hay que recalcar que la autenticación “Integrada con Windows”, no está soportada fuera de la familia de navegadores Internet Explorer (aunque funciona incluso en versiones tan arcaicas como Internet Explorer 2.0) y es impracticable con la presencia de cortafuegos. Sé que la opción de actualización por lotes de ADO.NET está diseñada para actualizar una tabla a la vez. Sin embargo, tengo un montón de tablas relacionadas y quiero usar esta técnica para persistir los cambios periódicamente a una base de datos. ¿Alguna sugerencia? La opción de actualización por lotes de ADO.NET es cualquier cosa menos una herramienta mágica que ahorre a los desarrolladores el esfuerzo de codificar un montón de código complejo. Puede ahorrarte tiempo, pero no es mágica. Ni siquiera es muy lista. La actualización por lotes, implementa una especie de caché de escritura donde volcar los cambios que quieres realizar en la base de datos en un momento dado. El mecanismo recorre las filas de una tabla dada y comprueba el estatus de actualización de esas filas: [email protected] [email protected] << dnm.laboratorio.net 49 dnm.laboratorio.net Lorenzo Ponte FileHelpers Es relativamente frecuente que el trasvase de información desde/hacia una aplicación se realice mediante archivos planos generados periódicamente. En tales ficheros, los registros se almacenan en líneas de texto que deben ser interpretadas para su posterior explotación. En el laboratorio de esta semana analizamos una librería que permite importar, exportar y explotar con gran comodidad archivos de este tipo en aplicaciones .NET. << FileHelpers es una librería destinada a facilitar el procesamiento de información proveniente de ficheros planos. Estos ficheros suelen crearse mediante una planificación temporal y depositarse en una ubicación física. Dentro de los ficheros, los registros se almacenan en líneas, con los campos delimitados por caracteres de separación preestablecidos o representados sobre un ancho fijo. Tradicionalmente, el tratamiento de estos datos se realiza mediante las conocidas funciones ReadLine(), Substring(), Split(), Convert(), etc. FileHelpers evita tener que escribir este tipo de código, gracias a un potente asistente al que podremos indicarle de qué forma queremos que se haga la extracción de los datos y que generará automáticamente una estructura de clase para dar soporte al formato. FileHelpers es una librería destinada a facilitar el procesamiento de información proveniente de ficheros planos 10248|VINET|04071996|32.38 10249|TOMSP|05071996|11.61 10250|HANAR|08071996|65.83 10251|VICTE|08071996|41.34 Fuente 1 Lorenzo Ponte es redactor de dotNetManía. Es Arquitecto de Sistemas y Aplicaciones .NET. Experto en Datawarehousing y Business Intelligence, Marketing Intelligence, CRM analítico. Actualmente es consultor de la empresa Matchmind y Webmaster de clikear.com Veamos un ejemplo muy sencillo. Supongamos que el archivo a tratar tiene la siguiente estructura: La clase que se generará para leer esos datos es la que vemos en el fuente 2. En nuestro código, el primer paso para utilizar la librería consistiría en agregar una referencia al ensamblado FileHelpers.dll. Para leer y escribir archivos con el formato especificado, debemos crear una instancia de la clase FileHelperEngine y usarla tal y como podemos ver en el fuente 3. << dnm.laboratorio.net FileHelpers nos ha dejado muy buen sabor de boca, destacando su facilidad de uso y las posibilidades que ofrece para la explotación de datos almacenados en ficheros [DelimitedRecord("|")] public class Orders { // No se necesitan conversores para // los tipos básicos public int OrderID; public string CustomerID; [FieldConverter(ConverterKind.Date, "ddMMyyyy")] public DateTime OrderDate; Fuente 2 FileHelperEngine engine = new FileHelperEngine(typeof(Orders)); // Para leer usamos: Orders[] res = (Orders[]) engine.ReadFile("Archivo de Entrada.txt"); // Para escribir usamos: engine.WriteFile("Archivo de Salida.txt", res); Fuente 3 La variable res es un array en el que cada elemento se mapea a un registro del archivo original. Con lo cual podríamos recorrer la información de la siguiente manera: foreach (Orders order in res) { Console.WriteLine("Información del pedido:"); Console.WriteLine(order.CustomerID + " - " + order.OrderDate.ToString("dd/MM/yy")); } Fuente 4 Algunas de las características principales de FileHelpers son: • Fácil de usar. • Funciona tanto para archivos delimitados como para los de ancho fijo. • Ofrece conversores de tipos automáticos y personalizados. • Trabaja también en modo asincrónico. • Soporta cualquier lenguaje de .NET: C#, VB.NET, J#. • Soporta .NET Compact Framework. • Soporta plantillas CodeSmith para generar las clases automáticamente. • Puede trabajar tanto con archivos o flujos (streams). • Soporta diferentes tipos de manejo de errores. • Soporta cadenas entrecomilladas como en MS Excel. • Soporta la posibilidad de establecer el tipo de codificación de los datos. • Permite interpretar el valor nulo en caso de que existan campos vacíos. • Posibilidad de modificar dinámicamente diversas características. • Documentación en inglés bastante completa. Conclusiones Desde el laboratorio de dotNetManía tenemos que decir que FileHelpers nos ha dejado muy buen sabor de boca, destacando su facilidad de uso y las posibilidades que ofrece para la explotación de datos almacenados en ficheros. Felicitamos a su creador Marcos Meli por el gran trabajo realizado y animamos a la comunidad a seguir su ejemplo. Ficha técnica Nombre FileHelpers Versión 1 Autor Marcos Meli Web http://filehelpers.sourceforge.net Categoría Gestión de archivos Precio Gratis (código fuente incluido) Valoración << dotNetManía public decimal Freight; } 51 dnm.comunidad.eventos 52 eventos.eventos.eventos.eventos.eventos.eventos << dotNetManía << dnm.comunidad.eventos Microsoft celebró el Developer Day de Madrid Microsoft reunió a más de 600 personas con las que compartió algunas de las nuevas funcionalidades sobre seguridad para desarrolladores. Microsoft organizó el día 31 de mayo en Madrid, el Microsoft Developer Day, el mayor evento que la compañía organiza para el colectivo de desarrolladores españoles, al que asistieron más de 600 personas. En esta ocasión estuvo dedicado a las nuevas funciones de seguridad de Windows Vista para desarrolladores y las ventajas que ofrece la plataforma .NET en materia de seguridad. Después de la keynote introductoria de Héctor Sánchez Montenegro, director de seguridad corporativa de Microsoft Ibérica, empezaron las charlas técnicas con Marino Posadas de Alhambra-Eidos y redactor jefe de esta publicación, que junto a Jesús Villalobos de Certia expusieron su sesión “Procesos para un desarrollo seguro”. En esta sesión se explicó el modelo de amenazas y las estrategias de defensa, así como las herramientas para el desarrollo seguro o cómo se articulan dichas estrategias en una aplicación ASP.NET 2.0. Continuó Fernando Guerrero, regional director de Solid Quality Learning, con su ponencia “Seguridad en SQL Server 2005 para desarrolladores”, empezando por ganarse al público en clave de humor con una serie de barbaridades que usuarios y desarrolladores acostumbramos a realizar y que le sirvió para convencernos de lo necesario del principio de menor privilegio, por el cual la mayor parte de servicios están parados o deshabilitados de inicio. Aprendimos nuevas características de seguridad en SQL Server 2005, incluyendo el cifrado de los datos almacenados con certificados digitales y las técnicas de funcionamiento aislado del CLR. Después de un merecido descanso, vino la ponencia “Autorización, autenticación y cifrado en .NET” que expuso Pablo Abbate, de Danysoft, en la que aprendimos cómo incorporar las técnicas de autorización, autenticación y cifrado de datos que incorpora el nuevo .NET Framework, en nuestras aplicaciones. Entonces intervino César de la Torre, de Renacimiento, uno de los principales expertos de WCF y Web Services en nuestro país, para exponer su ponencia “Aplicaciones distribuidas seguras con WS-Security”. La gran de mayoría de las aplicaciones desarrolladas en la actualidad exponen o utilizan componentes y servicios distribuidos. César nos mostró las tecnologías incluidas en WSE 3.0 y Windows Communication Foundation para evitar que estas comunicaciones distribuidas sean un punto débil en la seguridad de nuestras aplicaciones. “Defensa contra ataques Web comunes” era el título de la ponencia de Isabel Gomez de Microsoft Ibérica y de Miguel Jiménez de Ilitia, en la que nos enseñaron las técnicas que utilizan los atacan- “La naturaleza de los ataques a la seguridad es muy variada y, de hecho,también lo es la defensa contra dichos ataques.Buena parte de esa defensa tiene que ver con la administración del propio sistema operativo, pero nuestro código puede, en ocasiones,permitir lo que el propio sistema impide y eso supone un planteamiento serio de todo el modelo de amenazas.” (Marino Posadas, Seguridad en .NET Framework). El cuaderno técnico “Programación segura con .NET Framework” de Marino Posadas se regaló a cada asistente de este evento centrado en la seguridad en el desarrollo de aplicaciones. tes en los sitios Web como buffer overrun, inyección SQL, cross-site scripting, robo de sesión, etc., y cómo defendernos de ellos. Ya en el turno de tarde, tuvimos ocasión de escuchar la distendida charla “Seguridad para el cliente rico. Presente y futuro” de David Carmona de Microsoft Ibérica (el cliente) y Pablo Peláez, regional director de Visual Programming (el rico). El nuevo concepto de smart client también plantea cuestiones de seguridad que hay que atajar de raíz. En esta sesión vimos cómo publicar nuestra aplicación Windows Forms o Windows Presentation Foundation para que nuestros usuarios puedan acceder a su aplicación de una forma transparente y segura. Los dos MVP de Windows Security Chema Alonso, de Informática 64 y Juan Luis Rambla expusieron su ponencia “Implantación de una infraestructura segura” en la que nos explicaron que la multitud de servicios del sistema operativo y del propio hardware que utilizan nuestras aplicaciones, también pueden añadir puntos vulnerables. Aprendimos las mejores prácticas para que estos sistemas externos a nuestras aplicaciones estén bien configurados y actualizados para que no proporcionen una puerta de entrada a los atacantes. Para finalizar, “Novedades de seguridad en Windows Vista” de José Parada Gimeno, ITPro evangelist de Microsoft Ibérica. Un completísimo repaso a la seguridad en Windows Vista y las implicaciones que tienen las nuevas características del sistema operativo en el desarrollo de sus aplicaciones. << dnm.comunidad.eventos CODECAMP - VIC 2006 MSDN y Spain.NET han organizado, con el apoyo del Ayuntamiento de Vic, el segundo CodeCamp, un evento de fin de semana enmarcado en el proyecto Emprendia y dirigido a desarrolladores de software que quieran conocer las oportunidades que la tecnología puede brindarles a la hora de desarrollar sus negocios. Siguiendo este objetivo, entre las sesiones del CodeCamp se incluyeron temas como la construcción de un plan de negocio, la formación de una sociedad o la búsqueda de subvenciones. Además, se presentaron casos de éxito contados en primera persona por los responsables de empresas emprendedoras. David Carmona en el momento en que era entrevistado por la cadena televisiva “La Sexta” Grupo de Usuarios .NET de Málaga Durante los días 17 y 18 de junio pudimos asistir a uno de los eventos más interesantes celebrados en nuestro país. Total- Alfonso Rodríguez y Pep Lluis mente gra- Baño, los padres del invento tuito (incluyendo alojamiento, comida y actividades lúdicas) con ponencias de destacadísimos oradores entre los que se encontraban: David Carmona, Aurelio Porras, Guillermo Som, Salvador Ramos, Octavio Hernández, Jesús Villalobos, Vicenç Masanas, Daniel Seara, Dino Esposito, Nilda Díaz y Marta Santos. La ciudad de Vic ha sido elegida para celebrar la segunda edición del CodeCamp por el vínculo existente entre el municipio y Microsoft, ya que fue aquí donde se creó en el año 2001 Spain.NET, el primer Grupo de Usuarios de tecnología Microsoft .NET en España y uno de los primeros en Europa. En Málaga, el 6 de junio, tuvo lugar la reunión inaugural del Grupo de Usuarios .NET de Málaga. El lanzamiento fue todo un éxito, con más de 35 asistentes. Como ponente invitado, Miguel Katrib de- Miguel Katrib leitó a los asistentes con las novedades más interesantes en C# 3.0, así como LINQ. Se explicó los objetivos del grupo y se fijó fecha para próxima reunión. El grupo de usuarios de .NET nació en 2006, en un intento de promover de alguna forma a los usuarios de tecnología Microsoft .NET y en concreto desarrolladores que se encuentran en Málaga y su alrededor. El fundamento del grupo es la de fomentar la comunicación entre sus miembros, así como a través de la Web para una audiencia más amplia. Como cualquier grupo de usuarios, se hacen reuniones mensuales donde se comparte información, se discute sobre distintos aspectos relacionados con la vida profesional y, en general, todo lo que puede ayudar para progresar en la tecnología .NET. Más información: www.malagadnug.org. Solid Quality Learning University celebró el II SQLU Summit El equipo de mentores de Solid Quality Learning en el Summit de Madrid De esta forma, Solid Quality Learning continúa con sus tareas de capacitación y formación para todos los especialistas relacionados con el mundo de las aplicaciones que administran información. Capacitación que continuará en sus instalaciones de formación así como con sus capacidades de entrenamiento en línea. Para saber más de próximos eventos y entrenamientos, visita www.sqlu.com. dnm.comunidad.eventos << dotNetManía Durante la semana del 19 al 23 de junio, Solid Quality Learning repitió su exitoso summit en Madrid. En esta oportunidad, las distintas sesiones se dividieron en dos grandes grupos: la Sala de los índices y la Sala de los cubos. En la primera, temas relacionados con la optimización, alta disponibilidad y programabilidad fueron los más importantes, mientras que en la segunda se vieron en profundidad temas de inteligencia de negocios, análisis de información y generación de informes. La calidad de las sesiones ha sido determinada por sus mentores, como Fernando Guerrero, Adolfo Wiernik, Alejandro Leguizamo, Antonio Soto, Daniel Seara, David Carmona (Microsoft), Eladio Rincón, Eugenio Serrano, Francisco González, Guillermo Som, Javier Loría, Jordi Rambla, Miguel Egea y Salvador Ramos. Además de los trascendentes temas tratados a nivel de base de datos, también fue posible estudiar temas relacionados con el desarrollo de aplicaciones relacionadas con datos, así como las últimas novedades acerca de la administración de proyectos de bases de datos con Team System Edición para desarrolladores de bases de datos. 53 dnm.comunidad.net << dnm.comunidad.net Emprendia La iniciativa para los e-mprendedores <<dotNetManía << ¿Quién no ha soñado con repetir el éxito de la fre- 54 gona o el chupa-chups? Todos los desarrolladores tenemos ese gusanillo desde jóvenes, aunque en contadas ocasiones se hace realidad. Y no suele ser por falta de ideas, que las hay y muy buenas en España, sino por el momento de empezar a ponerlas en práctica. Ahí es donde empiezan los problemas: ¿Cómo empiezo a desarrollar? ¿De dónde saco información? ¿Cómo lo doy a conocer? ¿A quién se lo vendo? En MSDN Comunidades llevamos conociendo a gente con estas inquietudes desde nuestros inicios. Al contrario que en otros sectores, el perfil de desarrollador emprendedor suele ser muy técnico, con talento, escasos conocimientos de negocio y trabajador por cuenta ajena que araña tiempo a los amigos o la familia para seguir desarrollando software en su casa. Ésta es la magia del software: sin apenas inversión, cualquier persona con ganas y talento puede lanzar al mercado un producto innovador que consigue competir con las grandes corporaciones. De hecho la mayoría de estas corporaciones nacieron así, en un garaje americano entre varios amigos con gafas, pantalones de pana y seguidores de La Guerra de las Galaxias. Tengo la gran suerte de trabajar en una empresa que empezó así. No fue un ejecutivo agresivo recién salido de un MBA el que fundó Microsoft, sino dos “geeks” que disfrutaban escribiendo código y sin aspecto de empresarios. Aunque puede sonar a broma, algunas veces todavía se ve ese espíritu en Microsoft; solo hay que ver algunas iniciativas que se llevan a cabo (véase www.on10.net o www.channel9.msdn.com). Hace poco me encontré de cerca con este espíritu de garaje en Microsoft. Desde MSDN Comunidades queríamos ayudar a estos desarrolladores inquietos que se quedan trabajando por la noche en una idea loca. Cuando solo era un esbozo, se la contamos a varios miembros de la dirección de Microsoft Ibérica y el resultado fue increíble. No solo nos animaron con la idea, sino que nos apoyaron directamente, ilusionados como si fueran ellos los emprendedores que se encierran en sus garajes. Así nació Emprendia. Con esta iniciativa queremos ayudar a los desarrolladores de software españoles con ideas innovadoras en la puesta en marcha de un proyecto empresarial. El objetivo es claro: colaborar con los desarrolladores para que sus ideas puedan convertirse en una realidad. Para ello dentro del programa Emprendia se ofrecen tres tipos de ayudas: • Formación (¡Aprende!): los proyectos de software innovadores requieren en muchas ocasiones tecnologías diver- sas que utilizan los últimos avances de la industria. Dispositivos móviles, comunicaciones distribuidas, servicios ofrecidos por Internet o nuevas experiencias de usuario requieren una formación técnica que no está disponible en muchas ocasiones. El programa Emprendia incluye múltiples recursos gratuitos para la formación necesaria en estas tecnologías. Estos cursos se añaden a los que ya estaban disponibles online en MSDN y complementan la formación requerida por un emprendedor. No podemos olvidar tampoco la formación de negocio necesaria para tener éxito: finanzas, subvenciones, constitución de empresas, etc. Este tipo de formación también se añade al porfolio de MSDN, estando disponible on line para todos los desarrolladores. • Puesta en marcha (¡Construye!): una vez hayamos decidido ser emprendedores, llega la hora de empezar a trabajar. Los participantes del programa tienen acceso a multitud de recursos subvencionados para la puesta en práctica del proyecto. En esta línea se ofrecen los CodeCamps, encuentros de fin de semana donde conocer a otros emprendedores y aprender las tecnologías más “calientes” del mercado e información de los expertos en cómo formar una empresa. También se ofrece acceso gratuito a sesiones de negocio intensivas de dos días impartidas por la prestigiosa escuela de negocios IDE-CESEM. Tampoco podemos olvidarnos de los recursos necesarios para desarrollar el software. Los participantes tienen acceso a una subvención íntegra o casi íntegra (dependiendo del volumen) de todo el software necesario de Microsoft durante el primer año. Se ofrece también la posibilidad de asistir al Microsoft Technology Center que Microsoft comparte con el Gobierno de Aragón para una consultoría tecnológica sobre el proyecto. • Comunicación (¡Comunica!): Microsoft ofrece a los proyectos participantes del programa Emprendia diversos medios de comunicación para dar a conocer su idea. Los emprendedores que así lo deseen pueden publicar su proyecto en la Web de Microsoft o participar en eventos de forma conjunta. Para más información sobre Emprendia puedes acceder al sitio web www.msdnemprendia.com. ¡Contamos contigo! David Carmona Grupo Desarrolladores y Plataforma Microsoft Ibérica << dnm.biblioteca.net dnm.biblioteca.net Programming Microsoft ASP.NET 2.0 Core Reference Dino Esposito Editorial: Microsoft Press ISBN: 0735621764 Páginas: 336 Primera edición: Noviembre, 2005 Idioma: Inglés La obra, que ha tenido una acogida espectacular en Amazon, con 5 estrellas por parte de todos los comentarios de lectores, es un trabajo perfecto para el que desea saber de verdad cómo funciona ASP.NET en su interior y cómo eso se refleja en todos los aspectos de nuestras aplicaciones, desde la flexibilidad hasta la escalabilidad o el rendimiento. De obligada lectura, que se dice… Visual C# 2005:A Developer’s Notebook Jesse Liberty Editorial: O'Reilly Media ISBN: 059600799X Páginas: 221 Primera edición: Mayo, 2005 Idioma: Inglés Jesse Liberty es bien conocido por la capacidad divulgativa de sus obras (numerosísimas, sobre la plataforma .NET), dando cobertura tanto a los lenguajes principales (C# y Visual Basic .NET), como a la plataforma y los más destacados espacios de nombres para desarrollo (ASP.NET, ADO.NET). Este libro también ha tenido una acogida espléndida por la comunidad de desarrolladores y tiene –además– la ventaja de resultar una auténtica actualización (sin repeticiones) de la versión anterior. El autor se centra en todas las novedades del lenguaje, las explica y decora con código fuente explicativo y nos ofrece aspectos no vistos en otras obras de divulgación sobre C# 2.0, dentro de un marco conciso pero exacto donde se dice justamente lo que se quiere decir y nada más. Una excelente actualización. <<dotNetManía << Nuestro admirado colaborador italiano, Dino Esposito, ha reunido algunos de sus mejores consejos sobre el desarrollo en ASP.NET 2.0 dentro de esta obra de calado, donde nos ilustra con la precisión que en él es característica y, sobre todo, nos permite tener una auténtica “voz de la experiencia” sobre esta herramienta, con la que lleva trabajando desde las primeras versiones alfa. 55 [ ] dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club >>> dnm.club > << dnm.desvan noticias.noticias Marino Posadas Microsoft desvela los contenidos de su nueva certificación de arquitectura (MCA:Microsoft Certified Architect) La compañía de Redmond explicaba a primeros del pasado mes de junio los contenidos y objetivos perseguidos durante más de un año de proceso de diseño de esta certificación, que se prevé, con mucho, la más exigente de todas las propuestas hasta el momento. Casualmente, en la entrevista con Arvindra Sehmi que el lector encontrará en páginas interiores, comentábamos con él esta certificación y nos ampliaba información al respecto. Independientemente, ya existe una página Documentos en la Red oficial sobre MCA: http://www.microsoft.com/learning/ mcp/architect/overview. Microsoft integrará todas sus herramientas de BI en la solución PerformancePoint Server 2007 Según BI-Spain.com (http://www.bi-spain.com), Microsoft está trabajando en la integración de sus herramientas de BI (Business Scorecard Manager 2005 y ProClarity Analytics Server) en un mismo producto llamado PerformancePoint Server 2007. La versión beta (se dice), estará lista para noviembre de este año y el producto, para mediados de 2007. Además, PerformancePoint Server 2007 mejorará las capacidades de análisis y reporting de SQL Server 2005, utilizando el nuevo Office 2007. Sitios del mes Vídeo de BJ Ostergren, para la CNN, en el que se muestra qué fácil resulta robar datos de identidad en Internet. Entre sus quejas, la más importante recae sobre los gobiernos, que -a vecesdejan información confidencial en la red. Accesible en http://www.cnn.com/2006/TECH/internet/06/12/idtheft.internet/index.html. Nuevos foros MSDN y TechNet en castellano: Disponibles en las direcciones http://forums. microsoft.com/msdn-es/default.aspx? siteid=11 y http://forums.microsoft.com/TechNet-ES/default.aspx? SiteID=30 respectivamente. Puro desarrollo. Sitio de David Cervigón, evangelista de Microsoft y ponente habitual en conferencias y eventos, además de especialista en interioridades de los sistemas. Sin desperdicio: http://blogs.technet.com/davidcervigon. 20 Consejos para los autores de una bitácora (Corporate Weblog Manifesto): Un código de comportamiento eficaz y ético para los autores de bitácoras. Para los no autores, algún consejo interesante en otros campos. Por Scobleizer (http://scoble.weblogs.com/2003/02/26.html). Blog de Robert Hensing, miembro de la división Security Engineering and Communications en Redmond. Buenos comentarios sobre seguridad, y sobre todo, de primera mano. En http://blogs.technet.com/robert_hensing. Utilidades del mes Blog de Aaron Margosis, de similar corte al anterior, y tam- <<dotNetManía Control de usuario de Google Maps para ASP.NET. En el sitio 58 http://googlemaps.subgurim.net puede encontrarse una interesante aportación de un grupo español. Es un control que emula Google-Maps, y posee un montón de opciones de configuración y programación, a través de una sencilla API. Requiere de un registro, eso sí. bién con la seguridad en mente (http://blogs.msdn.com/ aaron_margosis). A destacar, varias series de artículos sobre técnicas seguras de programación y testeo. Los sitios de Lluís Franco: Este MVP en Visual Basic, no se conforma con el sitio Web de su empresa (la recomendable http://www.uyssoft.com), sino que desde hace algún tiempo actualiza una interesante bitácora de noticias sobre desarrollo en todas las tecnologías .NET: http://msmvps.com/blogs/lfranco/archive/category/1118.aspx.
Documentos relacionados
Entrevista a Jim Gray Entrevista a Jim Gray
Delphi 2005 ofrece la posibilidad de desarrollar para la plataforma .NET utilizando dos vías diferentes para el acceso a datos: a través de los recursos que ofrece la VCL.NET, una librería de compa...
Más detalles