<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7202343029566820509</id><updated>2012-02-16T21:42:07.283-03:00</updated><category term='C#'/><category term='Visual Studio'/><category term='MVC'/><category term='SEO'/><category term='Live'/><category term='Arquitectura'/><category term='SQL Server'/><category term='Eventos'/><category term='Tools'/><category term='Social Networks'/><category term='Tips'/><category term='OOXML'/><category term='Azure'/><category term='Entity Framework'/><category term='S+S'/><category term='Open Source'/><category term='ASP.NET'/><category term='ADO.NET'/><title type='text'>Gustavo Azcona</title><subtitle type='html'>Experiencias en .NET</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8463460832681266473</id><published>2011-07-05T11:53:00.001-03:00</published><updated>2011-07-05T12:06:37.718-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Entity Framework: Code First</title><content type='html'>&lt;p&gt;Finalizando la serie de posts sobre los enfoques de Entity Framework, ahora intentaré explicar el enfoque &lt;strong&gt;Code First&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;Puedes leer mis posts anteriores sobre &lt;strong&gt;&lt;a href="http://gustavoazcona.blogspot.com/2011/06/entity-framework-database-first.html" target="_blank"&gt;Database First&lt;/a&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;a href="http://gustavoazcona.blogspot.com/2011/07/entity-framework-model-first.html" target="_blank"&gt;Model First&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Este post es más bien conceptual, puede contener algunos detalles prácticos, pero no pretende mostrar ejemplos ni guías paso a paso. En futuros post intentaré dar ejemplos prácticos sobre cada uno de estos enfoques.&lt;/p&gt;  &lt;h4&gt;Code First&lt;/h4&gt;  &lt;p&gt;Este enfoque está disponible a partir de la versión &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=8363" target="_blank"&gt;ADO.NET Entity Framework 4.1&lt;/a&gt; y nos permite crear un modelo de clases &lt;strong&gt;POCO&lt;/strong&gt; (Plain Old CLR Object) a partir del cual podemos generar una base de datos y/o mapear esas clases a una base de datos existente.&lt;/p&gt;  &lt;p&gt;Aquí no existe un archivo &lt;strong&gt;edmx&lt;/strong&gt; con las definiciones XML del modelo conceptual, el modelo de datos y el mapeo entre ambos.&lt;/p&gt;  &lt;p&gt;El modelo conceptual está definido por el conjunto de clases que hemos creado para representar a las entidades de nuestro modelo de dominio. La idea es que nuestras clases POCO sean mapeadas directamente a la base de datos.&lt;/p&gt;  &lt;p&gt;La ventaja de usar clases &lt;strong&gt;POCO&lt;/strong&gt; es que el modelo de clases es más limpio y las clases no tienen dependencia con &lt;strong&gt;EntityFramework&lt;/strong&gt; (como sucede cuando las entidades heredan de &lt;strong&gt;EntityObject&lt;/strong&gt;, implementan ciertas interfaces y contienen atributos).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;&lt;strong&gt;¿Cómo se mapean las clases POCO a la base de datos?&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;De forma predeterminada, se &lt;strong&gt;utiliza un mapeo por convención en lugar de configuración&lt;/strong&gt;. Es decir, si no especificamos el mapeo, se utilizan los nombres de las clases y sus propiedades para generar los nombres de las tablas y sus campos.&lt;/p&gt;  &lt;p&gt;Este &lt;strong&gt;mapeo por convención&lt;/strong&gt; puede ser suficiente en nuevos proyectos, donde estamos definiendo y diseñando el modelo conceptual y la base de datos desde cero.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;&lt;strong&gt;¿Qué pasa si ya tengo una base de datos heredada? &lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;Si el esquema de la base de datos heredada coincide con el modelo conceptual, entonces el mapeo por convención seguirá siendo suficiente y aplicable y todos felices! (Probabilidad: 0.0000001%)&lt;/p&gt;  &lt;p&gt;La experiencia indica que si ya tenemos una base de datos heredada, es altamente probable que haya diferencias con el modelo conceptual utilizado en la aplicación. Entonces:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;h5&gt;¿Qué hacemos cuando el esquema de base de datos es diferente al modelo conceptual?&lt;/h5&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;h5&gt;&lt;strong&gt;¿Qué tal si quiero especificar restricciones, tipos de datos o validaciones a los campos?&lt;/strong&gt;&lt;/h5&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Bien, podemos resolver estas cuestiones y otras tantas a través de:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Data Annotations &lt;/li&gt;    &lt;li&gt;Mapping Fluent API &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Data Annotations&lt;/h4&gt;  &lt;p&gt;Estas clases están disponibles en el namespace &lt;/font&gt;&lt;font size="2" face="Trebuchet MS"&gt;&lt;strong&gt;System.ComponentModel.DataAnnotations&lt;/strong&gt; y permiten especificar restricciones o validaciones, especificar nombres de tablas o campos, etc.&lt;/font&gt;    &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-S_TDKUGIhsI/ThMlLavrD3I/AAAAAAAAAOI/6MWBFxMDQ4g/s1600-h/image_thumb112.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image_thumb11" border="0" alt="image_thumb11" src="http://lh3.ggpht.com/-_1cSL_T3OYk/ThMlMub1m_I/AAAAAAAAAOM/JAkb5RzU13U/image_thumb11_thumb.png?imgmax=800" width="423" height="243" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Hay dos artículos interesantes sobre &lt;strong&gt;Data Annotations&lt;/strong&gt; que recomiendo (en inglés):&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a title="http://msdn.microsoft.com/en-us/data/gg193958" href="http://msdn.microsoft.com/en-us/data/gg193958" target="_blank"&gt;Code First DataAnnotations&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a title="http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx" href="http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx" target="_blank"&gt;Data Annotations in the Entity Framework and Code First&lt;/a&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h4&gt;&lt;strong&gt;Mapping Fluent API&lt;/strong&gt;&lt;/h4&gt;    &lt;p&gt;La segunda alternativa que Code First ofrece para definir el mapeo entre el modelo conceptual y la base de datos es mediante Fluent API. Esta API permite especificar la configuración de mapeo y otras configuraciones mediante código.&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-dWXjz_2HVjI/ThMlOlB64hI/AAAAAAAAAOQ/tjvPkulh-Lg/s1600-h/image_thumb32.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image_thumb3" border="0" alt="image_thumb3" src="http://lh4.ggpht.com/-J1MSJlI5q1I/ThMlQYG32AI/AAAAAAAAAOU/7bv3lLhE92E/image_thumb3_thumb.png?imgmax=800" width="420" height="297" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Los siguientes enlaces contienen un artículo interesante con ejemplos sobre &lt;strong&gt;Code First Fluent API&lt;/strong&gt; y un video paso a paso:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a title="http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx" href="http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx" target="_blank"&gt;Fluent API Samples&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a title="http://msdn.microsoft.com/en-us/data/gg194005" href="http://msdn.microsoft.com/en-us/data/gg194005" target="_blank"&gt;Code First: Mapping Fluent API&lt;/a&gt; (Video) &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h4&gt;&lt;strong&gt;¿Y el contexto de datos de Code First?&lt;/strong&gt;&lt;/h4&gt;    &lt;p&gt;De forma predeterminada, con el enfoque &lt;strong&gt;Database First&lt;/strong&gt; y &lt;strong&gt;Model First&lt;/strong&gt; disponemos de una clase &lt;strong&gt;ObjectContext&lt;/strong&gt; del cual hereda el contexto de datos de nuestra aplicación.&lt;/p&gt;    &lt;p&gt;Con el enfoque &lt;strong&gt;Code First&lt;/strong&gt; tenemos un nuevo contexto llamado &lt;strong&gt;DbContext&lt;/strong&gt; del cual debe heredar el contexto de datos de nuestra aplicación.&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-Sx0Xi46KI5I/ThMlRCUJrXI/AAAAAAAAAOY/UC273haImGk/s1600-h/image_thumb52.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image_thumb5" border="0" alt="image_thumb5" src="http://lh4.ggpht.com/-YFdIzm5QbQM/ThMlSDJ8-qI/AAAAAAAAAOc/_bcna_x8cnM/image_thumb5_thumb.png?imgmax=800" width="412" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;En el contexto de datos, básicamente estamos definiendo cuáles son los conjuntos de entidades que serán mapeados a la base de datos.&lt;/p&gt;    &lt;p&gt;Adicionalmente, podemos usar inicializadores de bases de datos, especificar configuraciones de mapeo o interceptar las operaciones de &lt;strong&gt;SaveChanges&lt;/strong&gt; (entre otras).&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;DbContext&lt;/strong&gt; no es más que una versión simplificada de &lt;strong&gt;ObjectContext&lt;/strong&gt;, y también puede ser usando con los enfoques &lt;strong&gt;Database First&lt;/strong&gt; y &lt;strong&gt;Model First&lt;/strong&gt;.&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h4&gt;¿Cómo o cuando se genera la base de datos?&lt;/h4&gt;    &lt;p&gt;Cuando se crea una instancia de &lt;strong&gt;DbContext&lt;/strong&gt;, de forma predeterminada, se utiliza una estrategia de inicialización que crea a base de datos si no existe, opcionalmente se puede agregar código para insertar registros después de la creación.&lt;/p&gt;    &lt;p&gt;Estas operaciones de inicialización pueden ser implementadas usando el método &lt;strong&gt;Database.SetInitializer&lt;/strong&gt;. Éste método toma como parámetro una estrategia de inicialización de base de datos. &lt;/p&gt;    &lt;p&gt;Entity Framework Code First incluye 3 inicializadores:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;CreateDatabaseIfNotExist&lt;/li&gt;      &lt;li&gt;DropCreateDatabaseAlways&lt;/li&gt;      &lt;li&gt;DropCreateDatabaseIfModelChanges&lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;Podemos utilizar estos inicializadores de base de datos, cuando la aplicación se inicia. Por ejemplo, en una aplicación web podríamos usarlo en el evento &lt;strong&gt;Application_Start&lt;/strong&gt; del archivo &lt;strong&gt;global.asax&lt;/strong&gt;, en una aplicación de consola podríamos incluirlo en el método &lt;strong&gt;Main&lt;/strong&gt; del programa principal.&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-GZR17yq8QnY/ThMlSmRofII/AAAAAAAAAOg/rcqlFPUMZY0/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-5Ny1fqMKZcY/ThMlTQZ9IvI/AAAAAAAAAOk/pBI3GamfghU/image_thumb%25255B1%25255D.png?imgmax=800" width="426" height="166" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Adicionalmente, podemos crear una clase que hereda de alguno de estos inicializadores y sobreescribir el método &lt;strong&gt;Seed&lt;/strong&gt; para insertar registros después que la base de datos es creada.&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-LCSbUefvw3o/ThMlUxYHQ_I/AAAAAAAAAOo/mEYD2D4YJxc/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-weV739pesjo/ThMlWK6g12I/AAAAAAAAAOs/K3VtOfCcw6c/image_thumb%25255B3%25255D.png?imgmax=800" width="430" height="222" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Luego, usamos esta clase al iniciar la aplicación:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-5wGjECRTNDM/ThMlWmN0WqI/AAAAAAAAAOw/tnf6hcsxkxk/s1600-h/image%25255B12%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-WIGRGEPJ1BM/ThMlXJYQZdI/AAAAAAAAAO0/bRiUejKsB14/image_thumb%25255B6%25255D.png?imgmax=800" width="430" height="79" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;h4&gt;¿Cómo sería la inicialización de base de datos en un entorno de producción?&lt;/h4&gt;    &lt;p&gt;Bueno, es claro que en el entorno de desarrollo o pruebas, la inicialización de base de datos puede ser muy útil. Pero en un entorno de producción podría ser un problema.&lt;/p&gt;    &lt;p&gt;Simplemente podemos “apagar” la inicialización de base de datos, pasando &lt;strong&gt;null&lt;/strong&gt; como parámetro del método &lt;strong&gt;SetInitializer&lt;/strong&gt;:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-CWYk1Q6SGzg/ThMlXmOUxvI/AAAAAAAAAO4/R0khwev2lVY/s1600-h/image%25255B17%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-OPv8G2xnqQ0/ThMlYd1nh2I/AAAAAAAAAO8/pXtc4zueVmk/image_thumb%25255B9%25255D.png?imgmax=800" width="431" height="88" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;            &lt;h4&gt;Conclusión&lt;/h4&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;Code First&lt;/strong&gt; es el nuevo enfoque soportado por Entity Framework. Permite mapear nuestras clases POCO directamente a la base de datos.&lt;/li&gt;      &lt;li&gt;De forma predeterminada, &lt;strong&gt;el mapeo es por convención&lt;/strong&gt; en lugar de configuración.&lt;/li&gt;      &lt;li&gt;Configuración adicional de mapeo puede especificarse mediante &lt;strong&gt;Data Annotations&lt;/strong&gt; o &lt;strong&gt;Fluent API&lt;/strong&gt;.&lt;/li&gt;      &lt;li&gt;&lt;strong&gt;DbContext API&lt;/strong&gt; nos permite realizar las operaciones de acceso a datos.&lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Espero que esta serie de posts haya aclarado un poco más sobre las alternativas de trabajo con Entity Framework.&lt;/p&gt;    &lt;p&gt;Dedicaré nuevos posts con ejemplos más prácticos de cada uno de estos enfoques, ventajas, desventajas, limitaciones, etc.&lt;/p&gt;    &lt;p&gt;Saludos     &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8463460832681266473?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8463460832681266473/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8463460832681266473&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8463460832681266473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8463460832681266473'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2011/07/entity-framework-code-first.html' title='Entity Framework: Code First'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-_1cSL_T3OYk/ThMlMub1m_I/AAAAAAAAAOM/JAkb5RzU13U/s72-c/image_thumb11_thumb.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-3753161654210007643</id><published>2011-07-01T19:56:00.001-03:00</published><updated>2011-07-01T19:56:59.958-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Entity Framework: Model First</title><content type='html'>&lt;p&gt;Continuando con la serie de posts sobre los enfoques de Entity Framework, ahora intentaré explicar el enfoque &lt;strong&gt;Model First&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;Puedes leer sobre el enfoque &lt;strong&gt;Database First&lt;/strong&gt; en mi &lt;a href="http://gustavoazcona.blogspot.com/2011/06/entity-framework-database-first.html" target="_blank"&gt;post anterior&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Este post es más bien conceptual, puede contener algunos detalles prácticos, pero no pretende mostrar ejemplos ni guías paso a paso. En futuros post intentaré dar ejemplos prácticos sobre cada uno de estos enfoques.&lt;/p&gt;  &lt;h4&gt;Model First&lt;/h4&gt;  &lt;p&gt;La idea aquí es crear primero el modelo conceptual y a partir de este generar la base de datos.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-lemfs8G45VY/Tg5QhygwopI/AAAAAAAAANY/nBwfDO9EqLM/s1600-h/image_thumb42.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image_thumb4" border="0" alt="image_thumb4" src="http://lh3.ggpht.com/-NE_sVjVGFTg/Tg5QjVJzwRI/AAAAAAAAANc/7EIbjSd46Y8/image_thumb4_thumb.png?imgmax=800" width="418" height="237" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Usando &lt;strong&gt;Visual Studio&lt;/strong&gt; podemos arrancar creando un archivo .&lt;strong&gt;edmx&lt;/strong&gt; vacío y utilizamos el diseñador visual para crear nuestras entidades con sus propiedades y relaciones con otras entidades. &lt;/p&gt;  &lt;p&gt;Cuando tenemos nuestro modelo conceptual completo, podemos generar los scripts de SQL para crear el esquema de base de datos.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-buNLeM4Z3NM/Tg5Qktj7WhI/AAAAAAAAANg/dZXzEp5dYdE/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-AovnLiq9D_4/Tg5QmAUF9JI/AAAAAAAAANk/L84UeM-Soug/image_thumb1.png?imgmax=800" width="410" height="393" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;&lt;strong&gt;¿Qué pasa si la base de datos cambia?&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;En realidad, la base de datos debe cambiar como consecuencia de un cambio en el modelo conceptual. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ok ¿Qué pasa si el modelo conceptual cambia?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Habrá que actualizar el modelo conceptual de EntityFramework y generar los scripts SQL de creación de la base de datos.&lt;/p&gt;  &lt;p&gt;Desafortunadamente, los scripts SQL generados a partir del modelo conceptual son solo scripts de creación. Es decir, no son scripts de cambios o actualización de nuestro esquema de base de datos. En consecuencia, deberíamos borrar la base de datos y volver a crearla. Obviamente, esto no será factible en un entorno de producción y deberemos elegir otras alternativas. Por ejemplo:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Actualizar el esquema de datos a través de scripts escritos a manos o generados mediante una herramienta de comparación de esquema de datos. También podríamos alterar el esquema usando el Administrador de base de datos &lt;/li&gt;    &lt;li&gt;Luego deberíamos, actualizar el modelo conceptual de Entity Framework (edmx) y asegurarnos que el mapeo hacia la base de datos es correcto. &lt;/li&gt;    &lt;li&gt;Finalmente, actualizar el código existente en la aplicación. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Ojalá que en un futuro, el equipo de EF pueda incorporar un comparador de esquemas y generar scripts de actualización.&lt;/p&gt;  &lt;h5&gt;Ya tengo mi modelo conceptual creado, como sigo?&lt;/h5&gt;  &lt;p&gt;Bueno, a partir de ahora no difiere del enfoque &lt;strong&gt;Database First&lt;/strong&gt;. Podemos escribir querys contra el modelo conceptual y realizar las operaciones de persistencia necesarias.&lt;/p&gt;  &lt;h4&gt;&lt;strong&gt;¿Las clases de entidades generadas con Model First son POCO?&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;De forma predeterminada NO. Las clases contienen metadata y heredan de clases dependientes de &lt;strong&gt;EntityFramework&lt;/strong&gt;. Al igual que con &lt;strong&gt;Database First&lt;/strong&gt;, disponemos de una clase que hereda de &lt;strong&gt;ObjectContext&lt;/strong&gt; que nos permite interactuar con el modelo.&lt;/p&gt;  &lt;p&gt;Sin embargo, es posible tener clases POCO agregando un ítem de generación de código llamado: &lt;strong&gt;ADO.NET POCO Entity Generator&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-kAgbuW3Utxc/Tg5QnkZhy_I/AAAAAAAAANo/UD3kotg6r6o/s1600-h/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-J0HXASG1giA/Tg5Qo0wQIBI/AAAAAAAAANs/PiVBqV5nlns/image_thumb3.png?imgmax=800" width="420" height="222" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Esto elimina todo el código generado en el archivo .&lt;strong&gt;edmx.designer.cs&lt;/strong&gt; y crea clases &lt;strong&gt;POCO&lt;/strong&gt; basadas en &lt;strong&gt;plantillas T4&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-xsJdkrFvGDg/Tg5QpnBBXaI/AAAAAAAAANw/pR_d_5XpCKY/s1600-h/image10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-ZypPfzAQaRs/Tg5QqSG1U9I/AAAAAAAAAN0/vc9Fph2bnrU/image_thumb41.png?imgmax=800" width="244" height="180" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Otra alternativa para generar clases &lt;strong&gt;POCO&lt;/strong&gt; es eliminar la herramienta de generación de código &lt;strong&gt;EntityModelCodeGenerator&lt;/strong&gt; asociada al archivo .&lt;strong&gt;edmx&lt;/strong&gt; y generar las clases a mano.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-JaEontdcxRs/Tg5Qq9iAjII/AAAAAAAAAN4/CxUBAKjRUAU/s1600-h/image14.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-687ZSSNjGMI/Tg5QsV0QBzI/AAAAAAAAAN8/2-VzKMwNeqE/image_thumb6.png?imgmax=800" width="410" height="256" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-hOpDJLPswYs/Tg5QtHZdSlI/AAAAAAAAAOA/Pr01v-zJ-dE/s1600-h/image18.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-iZPJhQRlKns/Tg5QuthDRgI/AAAAAAAAAOE/RlaXzDQPwUE/image_thumb8.png?imgmax=800" width="414" height="259" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para finalizar este post, es interesante saber que estas técnicas para generar clases POCO, también son aplicables al enfoque &lt;strong&gt;Database First&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Conclusión&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;El enfoque &lt;strong&gt;Model First&lt;/strong&gt; nos permite crear primero un modelo conceptual y generar luego el esquema de base de datos.&lt;/li&gt;    &lt;li&gt;Al igual que &lt;strong&gt;Database First&lt;/strong&gt; se basa en un archivo &lt;strong&gt;edmx&lt;/strong&gt; para almacenar las definiciones XML del modelo conceptual, modelo de datos y mapeo entre ambos.&lt;/li&gt;    &lt;li&gt;Las clases generadas automáticamente no son &lt;strong&gt;POCO&lt;/strong&gt;, pero podemos generar clases POCO usando otras herramientas de generación de código.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;El próximo post estará dedicado al enfoque más reciente soportado por &lt;strong&gt;Entity Framework&lt;/strong&gt;: &lt;strong&gt;Code First&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Espero que sirva.   &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-3753161654210007643?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/3753161654210007643/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=3753161654210007643&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3753161654210007643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3753161654210007643'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2011/07/entity-framework-model-first.html' title='Entity Framework: Model First'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-NE_sVjVGFTg/Tg5QjVJzwRI/AAAAAAAAANc/7EIbjSd46Y8/s72-c/image_thumb4_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8553353269025093011</id><published>2011-06-30T11:21:00.001-03:00</published><updated>2011-07-05T12:08:09.337-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>Entity Framework: Database First</title><content type='html'>&lt;p&gt;En esta serie de post intentaré resumir los enfoques que hoy permite Entity Framework para crear nuestro modelo conceptual y resolver nuestras necesidades de persistencia.&lt;/p&gt;  &lt;p&gt;Este post es más bien conceptual, puede contener algunos detalles prácticos, pero no pretende mostrar ejemplos ni guías paso a paso. En futuros post intentaré dar ejemplos prácticos sobre cada uno de estos enfoques.&lt;/p&gt;  &lt;h4&gt;Introducción&lt;/h4&gt;  &lt;p&gt;Actualmente con&lt;strong&gt; Entity Framework&lt;/strong&gt; podemos elegir entre 3 enfoques diferentes para crear el modelo conceptual:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;Database First&lt;/strong&gt;: El modelo conceptual se crea a partir de una base de datos existente. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Model First&lt;/strong&gt;: se crea el modelo conceptual y se genera la base de datos. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Code First&lt;/strong&gt;: nuevo a partir de EF 4.1. Un enfoque simplificado que permite mapear nuestras clases POCO a la base de datos usando convención, Data Annotations o Fluent API. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Este post estará dedicado al primer enfoque: Database First.&lt;/p&gt;  &lt;h4&gt;Database First&lt;/h4&gt;  &lt;p&gt;Este enfoque permite inferir un modelo de clases a partir del esquema de una base de datos existente. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-mrIb2K05YiM/TgyGVTblytI/AAAAAAAAAMo/VPxaEzXFSkU/s1600-h/image41.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-d7TOsmZrJLc/TgyGWlsSHEI/AAAAAAAAAMs/gzDFcsqEeto/image_thumb1.png?imgmax=800" width="416" height="237" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Usando Visual Studio, podemos agregar un ítem de proyecto llamado &lt;strong&gt;Entity Data Model&lt;/strong&gt; e iniciar un asistente para conectarnos a una base de datos, seleccionar los objetos que queremos incluir en el modelo (tablas, vistas, stored procedures) y generar un archivo .&lt;strong&gt;edmx&lt;/strong&gt; que contiene una representación XML de:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;El &lt;strong&gt;modelo conceptual&lt;/strong&gt; (CSDL – Conceptual Schema Definition Language) &lt;/li&gt;    &lt;li&gt;el &lt;strong&gt;modelo de datos&lt;/strong&gt; (SSDL – Store Schema Definition Language) &lt;/li&gt;    &lt;li&gt;y el &lt;strong&gt;mapeo&lt;/strong&gt; entre ambos modelos (MSL – Mapping Specification Language) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;El siguiente gráfico muestra un ejemplo del contenido XML de un archivo .edmx:&lt;/p&gt;  &lt;p&gt;&lt;img style="margin: 0px 0px 5px" src="http://sankarsan.files.wordpress.com/2010/08/edmx.png" /&gt;&lt;/p&gt;  &lt;p&gt;Es importante entender que el &lt;strong&gt;modelo conceptual&lt;/strong&gt; (CSDL) no debe ser necesariamente igual al &lt;strong&gt;modelo de datos&lt;/strong&gt; (SSDL), y por ello existe el &lt;strong&gt;modelo de mapeo&lt;/strong&gt; (MSL).&lt;/p&gt;  &lt;p&gt;A partir de ese archivo .&lt;strong&gt;edmx&lt;/strong&gt;, se genera automáticamente (usando plantillas T4) un archivo .&lt;strong&gt;edmx.designer.cs&lt;/strong&gt; (.vb en el caso de VB.NET) que contiene las clases que representan a las entidades del &lt;strong&gt;modelo conceptual&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;img style="margin: 0px 0px 5px" src="http://ashishrocks.files.wordpress.com/2010/08/image356cfc25d.png" width="397" height="311" /&gt;&lt;/p&gt;  &lt;p&gt;Puede observarse que estas clases heredan de &lt;strong&gt;EntityObject&lt;/strong&gt; y tienen varios atributos y propiedades dependientes de &lt;strong&gt;EntityFramework&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Típicamente, se crea una clase (entidad) por cada tabla de la base de datos, incluyendo propiedades que se mapean a campos y las relaciones entre las tablas son representadas mediante &lt;strong&gt;propiedades de navegación&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-XnyLPlytwJk/TgyJMUhTMeI/AAAAAAAAANA/LIdubmIMjck/s1600-h/image%25255B11%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-vKN5rKvcjTM/TgyJN4n3F4I/AAAAAAAAANE/iNTx_Z33n78/image_thumb%25255B5%25255D.png?imgmax=800" width="276" height="353" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Además de las clases de entidades se genera también una clase que hereda de &lt;strong&gt;ObjectContext&lt;/strong&gt; y representa el contexto de base de datos. A través de esta clase tendremos acceso a las entidades y colecciones del modelo y podremos realizar todas las operaciones de lectura y escritura de datos desde y hacia la base de datos subyacente.&lt;/p&gt;  &lt;p&gt;En el siguiente ejemplo, &lt;strong&gt;BookstoreEntities&lt;/strong&gt; es la clase generada por EF que hereda de &lt;strong&gt;ObjectContext&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-eVlkkP_Jwho/TgyKy2edoZI/AAAAAAAAANQ/9Chte22yhmo/s1600-h/image%25255B19%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-Npw2euXBgyQ/TgyKz2XlejI/AAAAAAAAANU/pab-R1JM3Vs/image_thumb%25255B9%25255D.png?imgmax=800" width="402" height="281" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Luego podemos usarla para acceder al modelo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-B0yhkofYqMA/TgyJOvMVvuI/AAAAAAAAANI/s_y-lZfDwok/s1600-h/image%25255B15%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-F3H__fFCNA8/TgyJPTBwVFI/AAAAAAAAANM/T8D7_bJB3Wg/image_thumb%25255B7%25255D.png?imgmax=800" width="403" height="185" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;¿Puedo modificar o extender las clases de entidades generadas por EF?&lt;/h4&gt;  &lt;p&gt;Las clases generadas en el archivo .&lt;strong&gt;designer&lt;/strong&gt; son re-generadas cada vez que se actualiza el modelo en el archivo .&lt;strong&gt;edmx&lt;/strong&gt;. En consecuencia, no podemos modificar o agregar código a esas clases. La buena noticia es que son clases parciales y podemos extenderlas en otro archivo o bien podemos usar herencia.&lt;/p&gt;  &lt;h4&gt;¿Qué pasa si la base de datos cambia?&lt;/h4&gt;  &lt;p&gt;Habrá que actualizar el modelo conceptual. Esto puede lograrse fácilmente a través del designer del edmx:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-287MMRIUc4g/TgyGX1dLEsI/AAAAAAAAAMw/oNGn-DL-aOA/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-zrkRHLBtBSE/TgyGa_2XF4I/AAAAAAAAAM0/XZel4Rggotc/image_thumb%25255B1%25255D.png?imgmax=800" width="418" height="397" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Se inicia el asistente de actualización en el cual podemos agregar nuevas tablas, vistas o stored procedures, refrescar las tablas existentes o eliminar otras.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-wJDmduz7nRA/TgyGc1nOVFI/AAAAAAAAAM4/Ry-U6H7BHCY/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-1uCrfobHL2c/TgyGePZ-pJI/AAAAAAAAAM8/Ghmy8bvng9g/image_thumb%25255B3%25255D.png?imgmax=800" width="419" height="379" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Una vez finalizado el asistente, el archivo edmx se actualiza y se re-generan las clases de entidades. Luego habrá que actualizar el código que hace referencia a las entidades modificadas (si corresponde).&lt;/p&gt;  &lt;h4&gt;Conclusión&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;El enfoque &lt;strong&gt;Database First&lt;/strong&gt; nos permite generar rápidamente nuestro modelo de clases y mantenerlo sincronizado cuando el modelo de datos cambia. &lt;/li&gt;    &lt;li&gt;El archivo &lt;strong&gt;edmx&lt;/strong&gt; contiene una definición XML del &lt;strong&gt;modelo conceptual&lt;/strong&gt; (CSDL), el &lt;strong&gt;modelo de datos&lt;/strong&gt; (SSDL) y el &lt;strong&gt;mapeo&lt;/strong&gt; entre ambos. &lt;/li&gt;    &lt;li&gt;Las clases generadas heredan de &lt;strong&gt;EntityObject&lt;/strong&gt; y se utiliza una clase que hereda de &lt;strong&gt;ObjectContext&lt;/strong&gt; para administrar el modelo y realizar las operaciones de persistencia. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;En los próximos post continuaré con los otros dos enfoques de Entity Framework (Model First y Code First), y hablaremos sobre las opciones de generación de entidades POCO, etc.&lt;/p&gt;  &lt;p&gt;Espero que sirva, saludos.    &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8553353269025093011?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8553353269025093011/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8553353269025093011&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8553353269025093011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8553353269025093011'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2011/06/entity-framework-database-first.html' title='Entity Framework: Database First'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-d7TOsmZrJLc/TgyGWlsSHEI/AAAAAAAAAMs/gzDFcsqEeto/s72-c/image_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-3363608058120500905</id><published>2011-06-07T20:42:00.001-03:00</published><updated>2011-06-07T20:53:32.577-03:00</updated><title type='text'>Imperdible el Barcamp NEA 2011!!!</title><content type='html'>&lt;p&gt;Ya está confirmada la fecha para el &lt;strong&gt;&lt;font size="4"&gt;Barcamp NEA 2011&lt;/font&gt;&lt;/strong&gt;. Será el &lt;font size="4"&gt;&lt;strong&gt;sábado 25 de Junio&lt;/strong&gt;&lt;/font&gt; en las instalaciones de la &lt;strong&gt;UTN Resistencia. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Si querés saber de qué se trata todo esto y seguir las novedades ingresá a &lt;a href="http://www.barcampnea.com.ar"&gt;www.barcampnea.com.ar&lt;/a&gt; y registrate!&lt;/p&gt;  &lt;p&gt;También podés leer el post de &lt;a href="http://dtunpoco.com.ar/se-viene-barcamp-nea/" target="_blank"&gt;Luis&lt;/a&gt; que explica todo lo que necesitás saber para participar, colaborar, difundir y asistir a este importante evento.&lt;/p&gt;  &lt;p&gt;Aún faltan muchas cosas para el evento, así que toda colaboración será bienvenida.&lt;/p&gt;  &lt;p&gt;Aprovecho en este post para sumarme a la iniciativa de &lt;a href="http://twitpic.com/58a1oj" target="_blank"&gt;Facundo&lt;/a&gt; y agregar un par de diseños de remeras, uno con el diseño clásico y otro más… nosé…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Wwfm_hatPPc/Te63ajNqQfI/AAAAAAAAAMQ/W3C8euT7Pkk/s1600-h/barcampnea_2011_classic%25255B4%25255D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="barcampnea_2011_classic" border="0" alt="barcampnea_2011_classic" src="http://lh5.ggpht.com/-zuwjfgGd78g/Te63buVAKqI/AAAAAAAAAMU/xbtX2m8UXn0/barcampnea_2011_classic_thumb%25255B2%25255D.png?imgmax=800" width="395" height="309" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(Clic para agrandar)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-ONUVxQnOXH4/Te63dhJUgfI/AAAAAAAAAMY/qhbxAoo2lqo/s1600-h/barcampnea_2011_green%25255B5%25255D.png" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="barcampnea_2011_green" border="0" alt="barcampnea_2011_green" src="http://lh4.ggpht.com/-RNuWoSUKo5g/Te63fAL5hEI/AAAAAAAAAMc/b5OWWkvLSQg/barcampnea_2011_green_thumb%25255B3%25255D.png?imgmax=800" width="395" height="314" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Bueno, quizás estas remeras puedan estar disponibles ese día.&lt;/p&gt;  &lt;p&gt;Seguí todas las novedades del evento en Twitter &lt;a href="http://twitter.com/#%21/barcampnea"&gt;@barcampnea&lt;/a&gt; o &lt;a href="http://www.facebook.com/pages/barcampnea/132964393448453?sk=wall"&gt;Facebook&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Sigan difundiendo, nos veremos allá.    &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-3363608058120500905?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/3363608058120500905/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=3363608058120500905&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3363608058120500905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3363608058120500905'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2011/06/imperdible-el-barcamp-nea-2011.html' title='Imperdible el Barcamp NEA 2011!!!'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-zuwjfgGd78g/Te63buVAKqI/AAAAAAAAAMU/xbtX2m8UXn0/s72-c/barcampnea_2011_classic_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8380656963632138239</id><published>2011-03-25T20:13:00.001-03:00</published><updated>2011-03-25T20:20:11.559-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Tutorial de MVC3</title><content type='html'>&lt;p&gt;Como sabrán hace poco tiempo fue liberada la &lt;strong&gt;versión 3 de ASP MVC&lt;/strong&gt;, y ya se pueden encontrar muchos recursos, tutoriales, videos, etc. acerca de las bondades de MVC3. Un tutorial muy recomendado es el de &lt;a href="http://www.hanselman.com" target="_blank"&gt;Scott Hanselman&lt;/a&gt;: &lt;strong&gt;&lt;a href="http://www.asp.net/mvc/tutorials#Getting-Started-With-MVC3" target="_blank"&gt;Getting started with MVC3&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Si bien este tutorial se encuentra online y disponible para toda la comunidad he decidido compilar el tutorial completo en un documento PDF imprimible y publicarlo para su descarga:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/TY0jJ26uNnI/AAAAAAAAALk/2_8a2PpcA5A/s1600-h/image%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/TY0jKuQ0EFI/AAAAAAAAALo/4ZIqT3uCbV0/image_thumb%5B1%5D.png?imgmax=800" width="344" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Pueden descargar este tutorial desde: &lt;a title="Getting started with MVC3" href="http://www.avanic.com.ar/downloads/docs/getting_started_with_mvc3_cs.pdf" target="_blank"&gt;http://www.avanic.com.ar/downloads/docs/getting_started_with_mvc3_cs.pdf&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Espero lo disfruten!    &lt;br /&gt;Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8380656963632138239?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8380656963632138239/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8380656963632138239&amp;isPopup=true' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8380656963632138239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8380656963632138239'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2011/03/tutorial-de-mvc3.html' title='Tutorial de MVC3'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_apvGJDAiQ0E/TY0jKuQ0EFI/AAAAAAAAALo/4ZIqT3uCbV0/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-93826480309249632</id><published>2010-11-12T13:06:00.001-03:00</published><updated>2010-11-29T12:32:30.860-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social Networks'/><title type='text'>Twitter is over capacity…again!</title><content type='html'>&lt;p&gt;Hoy &lt;strong&gt;Viernes 12 de Noviembre de 2010 a las 12:59hs&lt;/strong&gt;, &lt;strong&gt;Twitter&lt;/strong&gt; está caído. Es la segunda vez que lo veo personalmente. Como esto no es tan frecuente, uno hasta lo mira con aprecio a la pantalla. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/TN1mEEOsEyI/AAAAAAAAAK4/H5yYFC5rGuE/s1600-h/image%5B7%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/TN1mFjjRodI/AAAAAAAAAK8/7-tYL--vJ7M/image_thumb%5B5%5D.png?imgmax=800" width="504" height="355" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hubiera pensado que a estas alturas ya estaban montados sobre alguna plataforma más escalable del estilo PAAS o IAAS, pero parece que no.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;¿Alguien sabe de la infraestructura actual de Twitter?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Nos seguimos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-93826480309249632?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/93826480309249632/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=93826480309249632&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/93826480309249632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/93826480309249632'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/11/twitter-is-over-capacityagain.html' title='Twitter is over capacity…again!'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_apvGJDAiQ0E/TN1mFjjRodI/AAAAAAAAAK8/7-tYL--vJ7M/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-6497495415611564114</id><published>2010-11-08T14:19:00.001-03:00</published><updated>2010-11-08T15:50:24.787-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>IsNullOrWhiteSpace, that’s the question!</title><content type='html'>&lt;p&gt;Seguramente muchos ya lo han observado en &lt;strong&gt;C# 4.0&lt;/strong&gt;. Existe una nueva función aplicable al tipo String: &lt;strong&gt;IsNullOrWhiteSpace&lt;/strong&gt;()&lt;/p&gt;  &lt;p&gt;A la vieja y conocida función &lt;strong&gt;IsNullOrEmpty&lt;/strong&gt;() le faltaba chequear los espacios en blancos o otros caracteres no visibles.&lt;/p&gt;  &lt;p&gt;Esta nueva función agrega justamente eso. Es decir, no solo verifica lo que indica su nombre, sino también cadenas vacías y otros caracteres no visibles que son irrelevantes en muchos procesos.&lt;/p&gt;  &lt;p&gt;Si antes, para considerar los espacios en blanco, teníamos que escribir lo siguiente:&lt;/p&gt;  &lt;p&gt;if (string.IsNullOrEmpty(value) || value.Trim() == string.Empty)&lt;/p&gt;  &lt;p&gt;ahora es suficiente y más eficiente escribir:&lt;/p&gt;  &lt;p&gt;if (string.IsNullOrWhiteSpace(value))&lt;/p&gt;  &lt;p&gt;Hace algún tiempo había escrito un extension method que hacía más o menos esto. Pero ahora esta nueva función integrada, es bienvenida y tendré que jubilar mi extension method (o usar la nueva función internamente).&lt;/p&gt;  &lt;p&gt;Debo reconocer que al principio me guié solo por el nombre y pensé que no consideraba las cadenas vacías. Quizás esperaba un nombre como: &lt;/p&gt;  &lt;p&gt;IsNullOrEmptyOrWhiteSpaceOrAnotherInvisibleChar()&lt;/p&gt;  &lt;p&gt;Pero creo que es mejor el nombre actual. A propósito, esto me hace recordar un viejo método disponible desde las primeras versiones del framework:&lt;/p&gt;  &lt;p&gt;FormsAuthentication.&lt;strong&gt;HashPasswordForStoreInConfigFile&lt;/strong&gt;()&lt;/p&gt;  &lt;p&gt;Lo he usado muchas veces, pero nunca para guardarlo en un archivo de configuración ;-)&lt;/p&gt;  &lt;p&gt;Me pregunto: que habrán estado pensando cuando bautizaron a este método? &lt;/p&gt;  &lt;p&gt;Espero que sirva.   &lt;br /&gt;Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-6497495415611564114?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/6497495415611564114/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=6497495415611564114&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6497495415611564114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6497495415611564114'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/11/isnullorwhitespace-thats-question.html' title='IsNullOrWhiteSpace, that’s the question!'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-3989064993592692272</id><published>2010-10-21T14:36:00.001-03:00</published><updated>2010-10-21T14:36:36.345-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Arquitectura'/><title type='text'>Cuidado! Un copo de nieve</title><content type='html'>&lt;p&gt;Así como un simple copo de nieve puede convertirse en una bola de nieve incontrolable, a menudo en los sistemas ocurren situaciones similares. &lt;/p&gt;  &lt;p&gt;Algo aparentemente tan inofensivo como no cambiar a tiempo el nombre de una tabla/campo de la base de datos o no renombrar una clase o método de la aplicación para que sea más representativo y coherente, puede originar una serie de pequeños inconvenientes y confusiones hasta convertirse en poco tiempo en un problema grave de mantenimiento.&lt;/p&gt;  &lt;p&gt;Muchas veces me he encontrado con pequeñas y medianas empresas y organismos públicos que vienen trabajando con una o más soluciones de software desde hace varios años y han llegado a un punto donde el mantenimiento se ha vuelto tan costoso que dan ganas de tirar todo y empezar de nuevo, lo cual generalmente es inaceptable (aunque muchas veces no quedan muchas alternativas). &lt;/p&gt;  &lt;p&gt;En estos sistemas, tareas habituales como solucionar un bug, agregar una nueva feature o una simple mejora pueden volverse tan complejas que muchas veces se prefiere no hacerlas o (lo que es peor) tratar de resolverlas con alguna artimaña rebuscada, con algún truco o parche. Lo que redunda una vez más en una mayor complejidad aumentando los costos de mantenimiento del sistema.&lt;/p&gt;  &lt;h4&gt;Todo es difícil&lt;/h4&gt;  &lt;p&gt;En estos sistemas todo se ha vuelto difícil.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;La estimación de tareas es difícil&lt;/strong&gt;. Una tarea que debería ser simple y fácil, se convierte en compleja y difícil y lleva mucho más tiempo del estimado. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;No hay tiempo para análisis&lt;/strong&gt;. Se necesita tiempo para analizar el impacto de agregar o cambiar cierta funcionalidad, pero no hay mucho tiempo porque estamos atrasados. Entonces, programemos y listo. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;La programación diaria es frustrante&lt;/strong&gt;. Lidiar todos los días con código difícil de leer, seguir y depurar se convierte en una tarea frustrante.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;No hay tiempo para testing&lt;/strong&gt;. Apenas alcanza el tiempo para desarrollar. Con suerte, el desarrollador alcanza a realizar un testeo superficial, una prueba de humo (Smoke Test) y el producto está listo para producción (Menos mal que no fabricamos autos o aviones).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;La reutilización de componentes es un chiste&lt;/strong&gt;. La complejidad de todo el sistema hace muy difícil crear funciones o componentes reutilizables. Recordemos que tampoco hay mucho tiempo para analizar. Como resultado se crean piezas de software muy similares una y otra vez, extendiendo los tiempos de desarrollo y aumentando aún más la complejidad.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;La incorporación de nuevos desarrolladores es costosa&lt;/strong&gt;. La productividad de los nuevos desarrolladores es muy reducida durante un largo tiempo, pues necesitan mucho más tiempo para entender el código pre-existente y poder hacer algo útil. Un desarrollador Senior se convierte en Junior. Y un desarrollador Junior cambia su color de pelo y religión.&lt;/p&gt;  &lt;h4&gt;Un salvador por aquí&lt;/h4&gt;  &lt;p&gt;En medio de todo el caos, aparece el &lt;strong&gt;desarrollador imprescindible.&lt;/strong&gt; El más experimentado de los desarrolladores suele convertirse en el salvador de la empresa o del producto. Es el único capaz de entender la solución actual. Él sabe que se puede “tocar” y que no, cuándo tocar y cuando no. Él entiende el porqué de las cosas (no siempre). Sin saberlo, esto le genera una alta presión y exigencia, que se transforma en Stress y cuando Él se enferma, la empresa se “enferma”. Si Él se va de vacaciones, la empresa se “sufre”. Y si Él renuncia, la empresa empieza a “agonizar”. Esta situación es muy perjudicial para una empresa.&lt;/p&gt;  &lt;h4&gt;&lt;strong&gt;¿Cómo se llega a esta situación?&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;Como lo decía Pablo en la TV: “Una seguidilla de hechos bochornosos”. Generalmente, el problema principal suele ser una carencia total de arquitectura empresarial. Por diferentes motivos se ha subestimado el valor de construir sistemas basados en una arquitectura sólida. A esto se le suma una serie interminable de vicios: desde el simple desconocimiento de mejores prácticas de programación, al código heredado de diferentes programadores o equipos de programación, y también se puede sumar tecnologías y lenguajes de programación obsoletos. &lt;/p&gt;  &lt;p&gt;Incluso una arquitectura sobredimensionada o exceso de patrones de arquitectura (patronitis aguda) pueden terminar con una solución inmanejable. Aunque esta última “enfermedad” no es muy común, lo más habitual es encontrar “antipatronitis crónica”.&lt;/p&gt;  &lt;h4&gt;¿Qué se puede hacer?&lt;/h4&gt;  &lt;p&gt;Cuando se llega a esta situación, el costo de &lt;strong&gt;intentar arreglar la solución actual puede ser más costosa que empezar de nuevo&lt;/strong&gt;. Y cuando la tecnología en la cual está basada el sistema ha quedado obsoleta, ya no tiene mucho sentido arreglarlo.&lt;/p&gt;  &lt;p&gt;Asumiendo que la tecnología del sistema no es obsoleta, hay que analizar cada caso en forma particular para determinar si todavía existen chances de cambiar la situación actual (cuando no se trata de una situación irreversible).&lt;/p&gt;  &lt;p&gt;Alguien podrá decir: “Los sistemas siempre se pueden corregir”. Si, es verdad, el punto es que en ciertas situaciones el costo de “corregir” puede superar ampliamente el valor del sistema. En estos casos se opta por seguir lidiando con los problemas o empezar de nuevo.&lt;/p&gt;  &lt;h4&gt;¿Se puede evitar esta situación?&lt;/h4&gt;  &lt;p&gt;Absolutamente. Solo es cuestión de tener algunas cosas básicas:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Un equipo de trabajo&lt;/li&gt;    &lt;li&gt;Una metodología de trabajo&lt;/li&gt;    &lt;li&gt;Una arquitectura de software clara y consistente.&lt;/li&gt;    &lt;li&gt;Un diseño de base de datos coherente&lt;/li&gt;    &lt;li&gt;Mejores prácticas de desarrollo&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Pero por sobre todas las cosas hay una que quizás es la más importante: &lt;strong&gt;Ganas de mejorar desde el primer día&lt;/strong&gt;. Esto no incluye solo al equipo de sistemas, sino a toda la empresa.&lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-3989064993592692272?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/3989064993592692272/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=3989064993592692272&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3989064993592692272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/3989064993592692272'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/10/cuidado-un-copo-de-nieve.html' title='Cuidado! Un copo de nieve'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-9066833827726294564</id><published>2010-10-21T13:00:00.001-03:00</published><updated>2010-10-21T14:03:32.352-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Arquitectura'/><title type='text'>Todo el problema no está en la programación</title><content type='html'>&lt;p&gt;Trabajando en muchos proyectos para organismos privados y públicos he visto una y otra vez cómo los sistemas llegan a un punto extremo donde los problemas abundan y las soluciones escasean.&lt;/p&gt;  &lt;p&gt;Desafortunadamente, muchos piensan que el problema de los sistemas inestables y costosos de mantener es solo un tema de programación. &lt;/p&gt;  &lt;p&gt;La realidad es que &lt;strong&gt;el problema casi siempre viene originado por una mala arquitectura, malas prácticas de programación y malos diseños de bases de datos&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;Enfocándome en el diseño de bases de datos, &lt;strong&gt;un mal diseño complejiza enormemente todo el sistema&lt;/strong&gt;. No soy experto en bases de datos, pero como desarrollador de sistemas empresariales, el diseño de bases de datos relacionales debe ser un conocimiento básico y fundamental. &lt;/p&gt;  &lt;p&gt;Me sorprende encontrar continuamente bases de datos con graves problemas de normalización, graves problemas de inconsistencia de datos, nombres de tablas y columnas incomprensibles o totalmente confusas, etc. Ni hablar del mal uso de los tipos de datos o la ausencia de los índices mínimos para acelerar las principales búsquedas. Posiblemente tampoco exista un plan de backup y mucho menos un plan de restauración testeado. ¿Y la seguridad? Nosé, hay un guardia en la entrada del edificio. &lt;/p&gt;  &lt;p&gt;Una situación común es que se crea una tabla o campo con cierto nombre, luego se utiliza en diferentes partes del código. Pasa el tiempo y se le agregan nuevos campos para cubrir nuevos requerimientos. Tiempo después, el equipo se da cuenta que el nombre ya no es representativo. La tabla que se llamaba &lt;strong&gt;Ventas&lt;/strong&gt;, ahora también almacena las &lt;strong&gt;Compras&lt;/strong&gt;, y se prevé que posiblemente también almacene otros comprobantes como Remitos, Notas de crédito, etc.&lt;/p&gt;  &lt;p&gt;Un nombre más representativo debería ser &lt;strong&gt;Comprobantes&lt;/strong&gt;, incluyendo un campo discriminador que determine el &lt;strong&gt;Tipo de comprobante&lt;/strong&gt;. Pero el equipo se resiste a cambiar de nombre o crear una nueva tabla, argumentando que también debería actualizar el código de la aplicación, las vistas y los procedimientos almacenados&amp;#160; dependientes, y eso es una tarea muy compleja.&lt;/p&gt;  &lt;p&gt;Es cierto, es una tarea compleja. Es un cambio que puede “romper” muchas cosas. Pero es un cambio importante para mantener la salud del sistema. Si no lo hacemos, estamos ampliando los problemas futuros de mantenimiento. Empezamos a complicar las cosas. Creamos la primer bola de nieve que irá creciendo.&lt;/p&gt;  &lt;p&gt;Alguien preguntará: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;“¿Qué hago con los sistemas externos que dependen de esa base de datos?”&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;En primer lugar no debería tener sistemas externos que dependen directamente del esquema de la base de datos. &lt;strong&gt;¿Donde quedaron los web services y la interoperabilidad?&lt;/strong&gt; Si este es el caso, quizás las vistas o sinónimos de bases de datos puedan ayudar a disminuir el alto acoplamiento.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;Se necesita coraje y una visión de sistema saludable a largo plazo para saber que ciertos cambios son posibles y necesarios en el momento oportuno y si no se atienden, se convierten en una enfermedad que nosotros mismos creamos.&lt;/p&gt;  &lt;p&gt;También hay que saber que existe mucha bibliografía, documentación, blogs y varias herramientas para refactoring de bases de datos. Es cuestión de conocerlas y saber usarlas cuando se necesitan.&lt;/p&gt;  &lt;p&gt;Incluyo aquí algunos links interesantes sobre refactoring y deployment de bases de datos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;The Process of Database Refactoring: Strategies for Improving Database Quality       &lt;br /&gt;&lt;/strong&gt;&lt;a title="http://www.agiledata.org/essays/databaseRefactoring.html" href="http://www.agiledata.org/essays/databaseRefactoring.html"&gt;http://www.agiledata.org/essays/databaseRefactoring.html&lt;/a&gt;&amp;#160; &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Refactoring Databases: Evolutionary Database Design       &lt;br /&gt;&lt;/strong&gt;&lt;a title="http://www.ambysoft.com/books/refactoringDatabases.html" href="http://www.ambysoft.com/books/refactoringDatabases.html"&gt;http://www.ambysoft.com/books/refactoringDatabases.html&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;First Experience with Visual Studio 2008 Database Edition&lt;/strong&gt;      &lt;br /&gt;&lt;a title="http://peterkellner.net/2009/01/17/visual-studio-database-edition-review-sqlserver2008/" href="http://peterkellner.net/2009/01/17/visual-studio-database-edition-review-sqlserver2008/"&gt;http://peterkellner.net/2009/01/17/visual-studio-database-edition-review-sqlserver2008/&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;En futuros posts intentaré dedicar tiempo a los proyectos de bases de datos para Visual Studio.&lt;/p&gt;  &lt;p&gt;Saludos, Gus.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-9066833827726294564?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/9066833827726294564/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=9066833827726294564&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/9066833827726294564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/9066833827726294564'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/10/todo-el-problema-no-esta-en-la.html' title='Todo el problema no está en la programación'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-801301501862616381</id><published>2010-10-18T18:08:00.001-03:00</published><updated>2010-10-18T19:01:56.250-03:00</updated><title type='text'>Microsoft Sync Framework: 'min_active_rowversion' no es un nombre de función integrada reconocido</title><content type='html'>&lt;p&gt;Me he encontrado con este mensaje de error al intentar sincronizar 2 bases de datos: SQL Server 2005 y SQL Server 2005 Express en una virtual PC con Windows XP.&lt;/p&gt;  &lt;p&gt;Al buscar un poco en la red, encuentro que la función &lt;strong&gt;min_active_rowversion&lt;/strong&gt; está disponible con el &lt;strong&gt;Service Pack 2&lt;/strong&gt; de &lt;strong&gt;SQL Server 2005&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Inmediatamente verifico si lo tengo instalado ejecutando el comando:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;select @@version&lt;/p&gt;    &lt;p&gt;Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)&amp;#160;&amp;#160; Oct 14 2005 00:33:37&amp;#160;&amp;#160; Copyright (c) 1988-2005 Microsoft Corporation&amp;#160; Standard Edition on Windows NT 5.1 (Build 2600: &lt;strong&gt;Service Pack 3&lt;/strong&gt;) &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Una rápida lectura permite ver que tengo instalado el &lt;strong&gt;Service Pack 3&lt;/strong&gt;. Entonces intento ejecutar el comando:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;select min_active_rowversion()&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;y obtengo el mismo mensaje de error inicial.&lt;/p&gt;  &lt;p&gt;Vuelvo a buscar en la documentacion oficial, los foros, blogs, etc. y encuentro una y otra vez que tal función está disponible con el &lt;strong&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=D07219B2-1E23-49C8-8F0C-63FA18F26D3A" target="_blank"&gt;SP2 de SQL Server 2005&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Empiezo a pensar que el SP3 que tengo instalado no incluye al SP2, lo cual me parece raro porque el SP3 es generalmente acumulativo. Empiezo a generar diferentes especulaciones y dudas, sigo buscando en la red, hasta que se me ocurre volver a leer el mensaje de select @@version:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)&amp;#160;&amp;#160; Oct 14 2005 00:33:37&amp;#160;&amp;#160; Copyright (c) 1988-2005 Microsoft Corporation&amp;#160; Standard Edition &lt;strong&gt;on Windows NT 5.1 (Build 2600: Service Pack 3)&lt;/strong&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Bingo! El &lt;strong&gt;service pack 3&lt;/strong&gt; que tengo instalado no es de &lt;strong&gt;SQL Server&lt;/strong&gt; sino de &lt;strong&gt;Windows XP&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Así que decido descargar e instalar el &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ae7387c3-348c-4faa-8ae5-949fdfbe59c4" target="_blank"&gt;SP3 de SQLServer 2005&lt;/a&gt; y también el &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3181842A-4090-4431-ACDD-9A1C832E65A6" target="_blank"&gt;SP3 de SQL Server 2005 Express&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Después de instalar el SP3 (tarda un rato) vuelvo a ejecutar el comando select @@version obtengo el siguiente mensaje:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Microsoft SQL Server 2005 - &lt;strong&gt;9.00.4035.00&lt;/strong&gt; (Intel X86)&amp;#160;&amp;#160; &lt;strong&gt;Nov 24 2008 13:01:59&lt;/strong&gt;&amp;#160;&amp;#160; Copyright (c) 1988-2005 Microsoft Corporation&amp;#160; Standard Edition on Windows NT 5.1 (Build 2600: Service Pack 3) &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ahora veo que tengo una versión mayor y el comando select &lt;strong&gt;min_active_rowversion&lt;/strong&gt;() ya no muestra un error.&lt;/p&gt;  &lt;p&gt;Finalmente, pruebo mi aplicación de sincronización y todo funciona correctamente. Los registros de base de datos se sincronizan sin problemas.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;: &lt;/p&gt;  &lt;p&gt;Yo debo leer mas detenidamente los mensajes. Pero el equipo de SQL Server podría reconocer que es un poco confuso agregar el service pack instalado de Windows al consultar la versión de SQL Server.&lt;/p&gt;  &lt;p&gt;Espero que sirva.   &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-801301501862616381?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/801301501862616381/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=801301501862616381&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/801301501862616381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/801301501862616381'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/10/microsoft-sync-framework-no-es-un.html' title='Microsoft Sync Framework: &amp;#39;min_active_rowversion&amp;#39; no es un nombre de función integrada reconocido'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-395764698524429441</id><published>2010-10-18T14:14:00.001-03:00</published><updated>2010-10-18T14:14:16.920-03:00</updated><title type='text'>Próximamente: IIS Express</title><content type='html'>&lt;p&gt;Nuevamente &lt;strong&gt;&lt;a href="http://weblogs.asp.net/scottgu/" target="_blank"&gt;Scott Guthrie&lt;/a&gt;&lt;/strong&gt; nos comenta en su blog sobre esta novedad interesante para los desarrolladores de ASP.NET que proximamente estará disponible en forma gratuita.&lt;/p&gt;  &lt;p&gt;Pueden ver el &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/06/28/introducing-iis-express.aspx" target="_blank"&gt;post original&lt;/a&gt; o su traducción al español por &lt;a href="http://thinkingindotnet.wordpress.com/2010/09/13/introduccion-a-iis-express/" target="_blank"&gt;Juan María Ramos&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Enjoy it!   &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-395764698524429441?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/395764698524429441/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=395764698524429441&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/395764698524429441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/395764698524429441'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/10/proximamente-iis-express.html' title='Próximamente: IIS Express'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-4182240831555474739</id><published>2010-10-15T12:09:00.001-03:00</published><updated>2010-10-15T12:10:42.905-03:00</updated><title type='text'>SQL Server CE embebido en ASP.NET</title><content type='html'>&lt;p&gt;Estas últimas semanas estoy bastante atareado aprendiendo y creando soluciones con &lt;a href="http://msdn.microsoft.com/en-us/vsto/" target="_blank"&gt;VSTO&lt;/a&gt; (Visual Studio Tools for Office). Ya tengo agendado media docena de posts sobre este tema para compartir. &lt;/p&gt;  &lt;p&gt;Pero ahora quiero compartir otra novedad que me parece muy interesante y útil para muchos.&amp;#160; Hace pocas semanas &lt;strong&gt;&lt;a href="http://weblogs.asp.net/scottgu/" target="_blank"&gt;Scott Guthrie&lt;/a&gt;&lt;/strong&gt; anunciaba que proximamente estará disponible una beta de &lt;strong&gt;SQL Server CE 4&lt;/strong&gt; (Compact Edition). &lt;/p&gt;  &lt;p&gt;Pueden leer el &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/06/30/new-embedded-database-support-with-asp-net.aspx" target="_blank"&gt;post original de Scott&lt;/a&gt; o la &lt;a href="http://thinkingindotnet.wordpress.com/2010/09/14/soporte-de-bases-de-datos-embebidas-en-asp-net/" target="_blank"&gt;traducción al español del bueno de Julian Ramos&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Actualmente pueden descargar el CTP 1 (Community Technology Preview) de SQL CE 4 desde el siguiente link: &lt;a title="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Con &lt;strong&gt;SQL CE 4&lt;/strong&gt; podremos disponer de un motor de base de datos liviano en nuestros sitios web que no requiere la instalación ni configuración de ningún servidor de base de datos. &lt;/p&gt;  &lt;p&gt;Solo hay que copiar los ensamblados de SQL CE 4 en nuestro directorio /bin y ya tenemos un motor de base de datos disponible en nuestra aplicación. Sin permisos especiales, sin cuentas administrativas, sin instalación, sin configuración. SQL CE 4 creará archivos de datos con extensión sdf que podemos alojarlos en nuestra carpeta /App_Data.&lt;/p&gt;  &lt;p&gt;Una buena noticia es que este motor de SQL CE 4 será compatible con nuestras tecnologías de Acceso a datos como ADO.NET u ORMs como Entity Framework o NHibernate. Adicionalente, podremos escalar nuestra base de datos a motores más avanzados como SQL Express, SQL Server o SQL Azure simplemente cambiando nuestra cadena de conexión.&lt;/p&gt;  &lt;p&gt;Un punto a saber es que esta versión de SQL CE no soportará procedimientos almacenados, un feature bastante común en muchos desarrollos, pero muy prescindible para quienes trabajan con ORMs.&lt;/p&gt;  &lt;p&gt;Bueno, espero que sirva.   &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-4182240831555474739?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/4182240831555474739/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=4182240831555474739&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4182240831555474739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4182240831555474739'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/10/sql-server-ce-embebido-en-aspnet.html' title='SQL Server CE embebido en ASP.NET'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1253230609376066693</id><published>2010-09-03T21:52:00.001-03:00</published><updated>2010-09-03T21:54:59.234-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>La familia crece: Nuevo Visual Studio LightSwitch</title><content type='html'>&lt;p&gt;Dicen que con esta nueva tool podremos crear rápidamente aplicaciones de negocio de calidad profesional sin tener que escribir mucho código. Podremos crear aplicaciones de escritorio o en la nube en muy poco tiempo. Podemos elegir C# o VB.NET, SQL Server, SQL Azure o SharePoint. También podemos crear aplicaciones SilverLight dentro o fuera del browser y exportar datos a Excel programando casi nada. Y cuando la aplicación crezca podemos personalizarla en Visual Studio Profesional o Standard o el que sea.&lt;/p&gt;  &lt;p&gt;Estas cosas ya las escuché muchas veces, pero no dejan de llamar la atención. Hay que probarlo: &lt;a title="http://www.microsoft.com/visualstudio/en-us/lightswitch" href="http://www.microsoft.com/visualstudio/en-us/lightswitch"&gt;http://www.microsoft.com/visualstudio/en-us/lightswitch&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Mas adelante les cuento mi experiencia.&lt;/p&gt;  &lt;p&gt;Nos vemos!   &lt;br /&gt;~Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1253230609376066693?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1253230609376066693/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1253230609376066693&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1253230609376066693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1253230609376066693'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2010/09/la-familia-crece-nuevo-visual-studio.html' title='La familia crece: Nuevo Visual Studio LightSwitch'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-4028334243526832444</id><published>2009-12-15T01:34:00.001-03:00</published><updated>2009-12-15T01:35:37.671-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Arquitectura'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>¿Cómo manejar el ciclo de vida del DataContext/ObjectContext en ASP.NET?</title><content type='html'>&lt;p&gt;Si estás trabajando en ASP.NET y LINQ2SQL o ADO.NET EF, te habrás preguntado cual es la mejor estrategia o solución para manejar el &lt;strong&gt;DataContext&lt;/strong&gt; o el &lt;strong&gt;ObjectContext&lt;/strong&gt;. Intentaré responder esta pregunta planteando varias alternativas que he conocido, pero verás que cada una tiene sus ventajas y desventajas, y la elección dependerá del escenario donde necesites aplicarlo. &lt;/p&gt;  &lt;p&gt;Por cuestiones de simplicidad, a continuación hago referencia al &lt;strong&gt;ObjectContext&lt;/strong&gt; de ADO.NET EF, pero la problemática es la misma con el &lt;strong&gt;DataContext&lt;/strong&gt; de LINQ to SQL.&lt;/p&gt;  &lt;h4&gt;1. Un contexto por Session&lt;/h4&gt;  &lt;p&gt;A más de uno se le habrá ocurrido implementar alguna especie de &lt;strong&gt;Singleton&lt;/strong&gt; y almacenar el &lt;strong&gt;ObjectContext&lt;/strong&gt; en el objeto &lt;strong&gt;Session&lt;/strong&gt; de ASP.NET. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Existe un único contexto para toda la sesión del usuario &lt;/li&gt;    &lt;li&gt;Todas las operaciones se realizan usando ese único contexto por usuario. &lt;/li&gt;    &lt;li&gt;No deberían aparecer los problemas de que no se puede actualizar una entidad porque está asociada a otro contexto. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Las opciones como &lt;strong&gt;ObjectTrackingEnabled&lt;/strong&gt; o &lt;strong&gt;DeferredLoadingEnabled&lt;/strong&gt; se aplicarían para todas las operaciones. &lt;/li&gt;    &lt;li&gt;El contexto puede crecer mucho y afectar la escalabilidad de la aplicación. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;2. Un contexto por Request&lt;/h4&gt;  &lt;p&gt;La idea aquí es similar a la anterior, pero en lugar de almacenar el contexto en el objeto &lt;strong&gt;Session&lt;/strong&gt;, lo guardamos en la colección &lt;strong&gt;HttpContext.Items&lt;/strong&gt;. Esta colección se crea para cada Request y solo existe durante la ejecución de la solicitud.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;El contexto solo vive durante el hilo de ejecución de cada &lt;strong&gt;Request&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Las operaciones de diferentes clases de acceso a datos pueden compartir el mismo contexto. &lt;/li&gt;    &lt;li&gt;La escalabilidad de la aplicación no debería verse afectada, pues el contexto se destruye al finalizar el Request. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Las opciones como &lt;strong&gt;ObjectTrackingEnabled&lt;/strong&gt; o &lt;strong&gt;DeferredLoadingEnabled&lt;/strong&gt; siguen afectando a todas las operaciones. &lt;/li&gt;    &lt;li&gt;Existe una sobrecarga de crear el contexto con cada Request. Aunque esa sobrecarga suele ser despreciable. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;3. Un contexto por instancia de acceso a datos&lt;/h4&gt;  &lt;p&gt;En lugar de guardar el contexto en la sesión o en el Thread del Request, lo creamos al instanciar la clase de acceso a datos. Por ejemplo, en el método constructor de la clase.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;El contexto tiene el mismo ciclo de vida que la clase de acceso datos. &lt;/li&gt;    &lt;li&gt;Las operaciones de la misma clase de acceso a datos pueden compartir el contexto. &lt;/li&gt;    &lt;li&gt;La escalabilidad de la aplicación no debería verse afectada, el contexto se destruye cuando se destruye la clase. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Las opciones como &lt;strong&gt;ObjectTrackingEnabled&lt;/strong&gt; o &lt;strong&gt;DeferredLoadingEnabled&lt;/strong&gt; siguen afectando a todas las operaciones en la misma clase. &lt;/li&gt;    &lt;li&gt;Otras clases de acceso a datos no pueden compartir el mismo contexto. &lt;/li&gt;    &lt;li&gt;Existe una sobrecarga de crear el contexto con cada instancia. Esta sobrecarga puede afectar la performance si muchas instancias de acceso a datos se crean con cada request. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;4. Un contexto por operación de acceso a datos&lt;/h4&gt;  &lt;p&gt;Esta sería la forma más atómica de manejar el contexto. Cada operación de acceso a datos crea el contexto, lo usa y lo libera.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;El contexto tiene un ciclo de vida mínimo. &lt;/li&gt;    &lt;li&gt;La escalabilidad de la aplicación no debería verse afectada, el contexto se destruye cuando finaliza el método. &lt;/li&gt;    &lt;li&gt;Las opciones como &lt;strong&gt;ObjectTrackingEnabled&lt;/strong&gt; o &lt;strong&gt;DeferredLoadingEnabled&lt;/strong&gt; solo afectan a todas las operaciones encerradas por el método. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Otros métodos o clases de acceso a datos no pueden compartir el mismo contexto. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Estoy seguro que podemos encontrar otras alternativas o variantes. Aunque no he encontrado ninguna 100% beneficiosa. &lt;/p&gt;  &lt;p&gt;De todas las variantes enumeradas aquí, en mis proyectos suelo utilizar la variante 2 (Un contexto por request) o la 3 (Un contexto por instancia de acceso a datos). Y hasta el momento no he tenido problemas significativos.&lt;/p&gt;  &lt;p&gt;Si tienes una estrategia mejor o más recomendable para manejar el contexto de datos de LINQ2SQL o ADO.NET EF, no dudes en compartirla.&lt;/p&gt;  &lt;p&gt;En un futuro post, intentaré poner algunos ejemplos de código sobre cómo gestiono el contexto de datos en mis proyectos.&lt;/p&gt;  &lt;p&gt;Espero que sirva.   &lt;br /&gt;&lt;strong&gt;Saludos, Gus&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-4028334243526832444?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/4028334243526832444/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=4028334243526832444&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4028334243526832444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4028334243526832444'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/12/como-manejar-el-ciclo-de-vida-del.html' title='¿Cómo manejar el ciclo de vida del DataContext/ObjectContext en ASP.NET?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-902557254215571957</id><published>2009-09-23T10:18:00.001-03:00</published><updated>2009-12-15T01:18:49.831-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='SEO'/><title type='text'>Mejores enlaces en ASP.NET</title><content type='html'>&lt;p&gt;Durante mucho tiempo a la hora de incluir un enlace en mis aplicaciones ASP.NET simplemente utilizaba un control &lt;strong&gt;Hyperlink&lt;/strong&gt; y en su propiedad &lt;strong&gt;NavigateUrl&lt;/strong&gt; escribía la dirección URL. Por ejemplo:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;asp:Hyperlink ID=”ContactLink” runat=”server” NavigateUrl=”~/contact.aspx” Text=”Contacto” /&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Este enlace se crea en el navegador como un elemento &lt;strong&gt;HTML anchor&lt;/strong&gt; similar al siguiente:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a id=&amp;quot;ctl00_MainContainer_ContactLink&amp;quot; href=&amp;quot;../contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Este enlace no está tan mal, pero su atributo &lt;strong&gt;id&lt;/strong&gt; es un poco extraño y en este caso particular, como se trata da una URL estática, es innecesario; en consecuencia podríamos evitarlo en pos de lograr un HTML más limpio.&lt;/p&gt;  &lt;p&gt;Alguien podría decir: &lt;strong&gt;¿por qué no podemos usar simplemente un elemento HTML anchor en lugar de un control Hyperlink?&lt;/strong&gt;. Bien, un simple anchor podría estar bien en muchas situaciones:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a href=&amp;quot;/contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Este enlace funcionaría bien en muchos sitios web, pero trae algunos problemas con los subdominios o subcarpetas. Por ejemplo: si nuestra aplicación ASP.NET está alojada en &lt;a href="http://www.example.com/miapp"&gt;www.example.com/miapp&lt;/a&gt;, el enlace anterior apuntaría incorrectamente a &lt;a href="http://www.example.com/contact.aspx"&gt;www.example.com/contact.aspx&lt;/a&gt; en lugar de &lt;a href="http://www.example.com/miapp/contact.aspx"&gt;www.example.com/miapp/contact.aspx&lt;/a&gt;. Es por ello que preferimos usar &lt;strong&gt;Hyperlinks&lt;/strong&gt; y usar el &lt;strong&gt;carácter de tilde&lt;/strong&gt; “~” que nos asegura una URL correcta desde la raíz de nuestra aplicación.&lt;/p&gt;  &lt;p&gt;Desafortunadamente no podemos usar la tilde “~” con un simple elemento HTML, pues la tilde se procesa y resuelve en el lado servidor. Un enlace como el siguiente no funcionaría:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a href=&amp;quot;~/contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;h3&gt;Escribiendo enlaces correctos y limpios&lt;/h3&gt;  &lt;p&gt;Una alternativa para resolver el problema usando el elemento anchor, es usar el método &lt;strong&gt;ResolveUrl&lt;/strong&gt; de la siguiente forma:&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=&lt;strong&gt;’&amp;lt;%= ResolveUrl(“~/contact.aspx”)’ %&amp;gt;&lt;/strong&gt;Contacto&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;Este tipo de enlaces dá como resultado un HTML anchor sin el atributo ID, y funciona correctamente en cualquier sitio con subdominios y es independiente de la estructura de carpetas de nuestro sitio.&amp;#160; El enlace siempre será correcto!. En el navegador se vería como:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a href=&amp;quot;../contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;h3&gt;Mejorando la escritura de los enlaces&lt;/h3&gt;  &lt;p&gt;Durante un buen tiempo empecé a escribir este tipo de enlaces, pero luego no me sentí muy conforme con la forma de hacerlo. No me parecía muy natural. Otras personas que están aprendiendo ASP.NET les suena complicado o confuso. &lt;/p&gt;  &lt;p&gt;Entonces encontré otra forma de lograr el mismo resultado (HTML más limpio y claro), pero de una forma más intuitiva y elegante. El truco consiste en agregar el atributo &lt;strong&gt;runat=”server”&lt;/strong&gt; al elemento &lt;strong&gt;HTML anchor&lt;/strong&gt; y entonces podemos usar el caracter de tilde “~” en el &lt;strong&gt;href&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&amp;lt;a &lt;strong&gt;href=&amp;quot;~/contact.aspx&amp;quot;&lt;/strong&gt; &lt;strong&gt;runat=”server”&lt;/strong&gt;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;Esto dá como resultado un enlace HTML limpio y correcto:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a href=&amp;quot;../contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;La buena noticia es que esto podemos aplicarlo también con las imágenes e incluso con los elementos &lt;strong&gt;&amp;lt;link&amp;gt;&lt;/strong&gt; que usamos para referenciar archivos CSS o Javascript en el &lt;strong&gt;&amp;lt;head&amp;gt;&lt;/strong&gt; de nuestras páginas. &lt;/p&gt;  &lt;p&gt;Espero les sirva!    &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;Es una costumbre en ASP.NET que al usar controles de servidor proporcionemos un atributo ID al control. Sin embargo, no es obligatorio. Podríamos declarar controles de servidor SIN el atributo ID, como el siguiente:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;asp.HyperLink runat=”server” NavigateUrl=”~/contact.aspx” Text=”Contacto” /&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Esto genera en el lado cliente un elemento anchor limpio sin el atributo ID: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;a href=&amp;quot;../contact.aspx&amp;quot;&amp;gt;Contacto&amp;lt;/a&amp;gt;&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-902557254215571957?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/902557254215571957/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=902557254215571957&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/902557254215571957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/902557254215571957'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/09/mejores-enlaces-en-aspnet.html' title='Mejores enlaces en ASP.NET'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-5878910192016929629</id><published>2009-04-30T15:59:00.001-03:00</published><updated>2009-04-30T16:04:49.137-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Microsoft Web Platform Installer</title><content type='html'>&lt;p&gt;Desde principios de año ya está disponible la versión 1.0 y desde mediados de Marzo la versión 2.0 beta de esta excelente y práctica plataforma que simplifica la descarga e instalación de todo el software que necesitamos en nuestro entorno de desarrollo, pruebas y producción.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/web/downloads/platform.aspx"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="226" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/Sfn1C8McKUI/AAAAAAAAAJQ/aX8MjYC3czI/image%5B34%5D.png?imgmax=800" width="386" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;En esta tool podemos encontrar:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/Sfn1DTSEJ1I/AAAAAAAAAJU/EE5Wafh94Vc/s1600-h/image%5B8%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="52" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/Sfn1Dl-1zZI/AAAAAAAAAJY/Jt7naa3a1FY/image_thumb%5B4%5D.png?imgmax=800" width="78" border="0" /&gt;&lt;/a&gt; &lt;/td&gt;        &lt;td valign="top" width="370"&gt;&lt;strong&gt;.NET Framework           &lt;br /&gt;&lt;/strong&gt;Instala la última versión del .NET Framework. Esto incluye todo lo que necesitas para trabajar con ASP.NET&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/Sfn1EDHix1I/AAAAAAAAAJc/Wh72wstR_5A/s1600-h/image%5B20%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="55" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/Sfn1EfQ-paI/AAAAAAAAAJg/TieKd2NM2xo/image_thumb%5B10%5D.png?imgmax=800" width="66" border="0" /&gt;&lt;/a&gt; &lt;/td&gt;        &lt;td valign="top" width="370"&gt;&lt;strong&gt;IIS y Extensiones           &lt;br /&gt;&lt;/strong&gt;Instala la última versión de IIS, incluyendo las últimas extensiones de IIS como el IIS Media Services.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/Sfn1EzdrksI/AAAAAAAAAJk/Z3tSh3_lFZQ/s1600-h/image%5B19%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="55" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/Sfn1FH2BDQI/AAAAAAAAAJo/-RSnb0j3xrM/image_thumb%5B9%5D.png?imgmax=800" width="63" border="0" /&gt;&lt;/a&gt; &lt;/td&gt;        &lt;td valign="top" width="370"&gt;         &lt;p&gt;&lt;strong&gt;SQL Server             &lt;br /&gt;&lt;/strong&gt;Instala la última versión de SQL Server 2008 Express. Incluye tanto la base de datos como las herramientas. &lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/Sfn1FieOmqI/AAAAAAAAAJs/wZtRDARcA0w/s1600-h/image%5B18%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="45" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/Sfn1FzDte8I/AAAAAAAAAJw/LFYYY3PJ7cA/image_thumb%5B8%5D.png?imgmax=800" width="71" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign="top" width="370"&gt;&lt;strong&gt;Visual Web Developer           &lt;br /&gt;&lt;/strong&gt;Instala la última versión del Visual Web Developer Express, nuestra herramienta completa gratuita para desarrollar sitios web.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/Sfn1GY3VAqI/AAAAAAAAAJ0/Yvj1SXLF3Is/s1600-h/image%5B28%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="54" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/Sfn1Gg1KWqI/AAAAAAAAAJ4/771vr_uHGn8/image_thumb%5B14%5D.png?imgmax=800" width="71" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign="top" width="370"&gt;         &lt;p&gt;&lt;strong&gt;Aplicaciones web populares             &lt;br /&gt;&lt;/strong&gt;Instala las aplicaciones web gratuitas más populares como DotNetNuke y WordPress, Drupal BlogEngine.NET, etc.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="30"&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/Sfn1HBVWBLI/AAAAAAAAAJ8/IdAkpsZ39oM/s1600-h/image%5B27%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="51" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/Sfn1HU3mYtI/AAAAAAAAAKA/NlG0A3_9Sz8/image_thumb%5B13%5D.png?imgmax=800" width="67" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign="top" width="370"&gt;&lt;strong&gt;Extras&lt;/strong&gt;          &lt;br /&gt;Incluye la última versión de PHP para Windows!&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Pueden descargar la última versión en:   &lt;br /&gt;&lt;a title="http://www.microsoft.com/web/downloads/platform.aspx" href="http://www.microsoft.com/web/downloads/platform.aspx"&gt;http://www.microsoft.com/web/downloads/platform.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Enjoy it!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-5878910192016929629?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/5878910192016929629/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=5878910192016929629&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5878910192016929629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5878910192016929629'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/04/microsoft-web-platform-installer.html' title='Microsoft Web Platform Installer'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_apvGJDAiQ0E/Sfn1C8McKUI/AAAAAAAAAJQ/aX8MjYC3czI/s72-c/image%5B34%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-5235801086263368802</id><published>2009-03-17T10:52:00.001-03:00</published><updated>2009-03-17T13:16:19.212-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Open Source'/><title type='text'>Software Libre vs Software Propietario</title><content type='html'>&lt;p&gt;No acostumbro a escribir sobre estos temas, mis posts generalmente son más técnicos. Sin embargo, desde hace tiempo que a veces me preguntan y muchas veces participo, voluntaria o involuntariamente, en desgastantes debates sobre el mundo &lt;strong&gt;Open Source&lt;/strong&gt; y el &lt;strong&gt;Mundo Propietario&lt;/strong&gt;, y la mayoría de las veces, estas discusiones, responden más a cuestiones ideológicas o fundamentalistas que objetivas.&lt;/p&gt;  &lt;p&gt;La verdad es que me gustaría invertir más tiempo en otros temas, pero quise publicar este post para referenciar mi opinión al respecto en futuras e inevitables discusiones sobre este tema inacabable. Espero así en el futuro, cuando me encuentre en estas discusiones y me pidan opinión, pueda decir simplemente: “leé mi post”. ;-)&lt;/p&gt;  &lt;p&gt;Encontrarán que hago muchas referencias y expongo ejemplos de o relacionado a Microsoft y sus tecnologías con las cuales trabajo día a día. Sin embargo, intento ser objetivo y espero ver comentarios objetivos de otras personas que tienen o han tenido experiencias en otras plataformas.&lt;/p&gt;  &lt;h4&gt;Introducción&lt;/h4&gt;  &lt;p&gt;Existe una gran confusión y un eterno debate entre la adopción de tecnologías basadas en &lt;strong&gt;Software Libre versus Software Propietario&lt;/strong&gt;. Sin ánimos de iniciar un nuevo debate, la mayoría de las personas y organizaciones siempre están de acuerdo en que lo que se busca son soluciones de calidad al menor costo posible. Siempre se piensa en la relación Costo/Beneficio o Retorno de la Inversión.&lt;/p&gt;  &lt;p&gt;Yo comparto esa visión, que contiene un amplio sentido común, y he decido evaluar las alternativas y plantear en forma realista diferentes &lt;strong&gt;soluciones en ambos enfoques&lt;/strong&gt;, incluso creando &lt;strong&gt;soluciones combinadas para sacar el mejor provecho de cada una&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;En este sentido, un aspecto fundamental a considerar es la &lt;strong&gt;realidad actual de las empresas y organizaciones&lt;/strong&gt;, sus tecnologías disponibles, personal capacitado, cambios de plataformas, aceptación de los usuarios, etc.&lt;/p&gt;  &lt;p&gt;Antes de estudiar y evaluar las alternativas sobre cada plataforma, veamos algunos &lt;strong&gt;mitos que giran entorno al Software Libre y Software Propietario&lt;/strong&gt;.&lt;/p&gt;  &lt;h4&gt;Mito 1: Si es Software Libre, es Gratis&lt;/h4&gt;  &lt;p&gt;La palabra &lt;strong&gt;Libre&lt;/strong&gt; se refiere a que se le concede a los usuarios &lt;strong&gt;4 libertades básicas&lt;/strong&gt;:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Libertad de usar el programa con cualquier propósito &lt;/li&gt;    &lt;li&gt;Libertad de adaptar el programa a sus necesidades &lt;/li&gt;    &lt;li&gt;Libertad de copiar y distribuir &lt;/li&gt;    &lt;li&gt;Libertad de mejorar y hacer pública las mejoras a toda la comunidad &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Cualquier programa que conceda estas libertades será considerado libre, pero esto no implica que sea gratis&lt;/strong&gt;. Es evidente que para permitir estas libertades se &lt;strong&gt;debe proporcionar el código fuente del programa&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;En la actualidad muchas empresas privadas desarrollan programas, herramientas y componentes y entregan el código fuente correspondiente junto a licencias que permiten su modificación y distribución, sin embargo no todas lo ofrecen en forma gratuita, pero siguen siendo libres.&lt;/p&gt;  &lt;p&gt;Por otro lado, &lt;strong&gt;si un programa se distribuye gratuitamente, no significa que sea libre&lt;/strong&gt;. Existen muchos programas de distribución gratuita que no incluyen su código fuente. Son gratis!, pero no son libres.&lt;/p&gt;  &lt;h4&gt;Mito 2: Si es Software Propietario, no es Libre&lt;/h4&gt;  &lt;p&gt;Cada vez más &lt;strong&gt;las empresas líderes de software reconocen los beneficios que el software libre puede aportar a la comunidad de usuarios y desarrolladores&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;En consecuencia existen iniciativas de dominio público respaldadas por estas empresas que favorecen el uso de software libre y promueven comunidades de usuarios para el desarrollo e intercambio de programas y código fuente. Por el lado de tecnologías &lt;strong&gt;Microsoft&lt;/strong&gt; son muy reconocidas y valiosas las comunidades de intercambio proyectos de código abierto como &lt;strong&gt;CodePlex&lt;/strong&gt; (&lt;a href="http://www.codeplex.com"&gt;www.codeplex.com&lt;/a&gt;), &lt;strong&gt;SourceForge&lt;/strong&gt; (&lt;a href="http://www.sourceforge.net"&gt;www.sourceforge.net&lt;/a&gt;) y &lt;strong&gt;Code Project&lt;/strong&gt; (&lt;a href="http://www.codeproject.com"&gt;www.codeproject.com&lt;/a&gt;). &lt;/p&gt;  &lt;p&gt;Siguiendo con el mito 2, hace un tiempo que &lt;strong&gt;Sun Microsystems&lt;/strong&gt; ha adquirido el famoso gestor de base de datos &lt;strong&gt;MySQL&lt;/strong&gt;, y por ello no ha dejado de ser libre. &lt;/p&gt;  &lt;p&gt;Por su parte, &lt;strong&gt;Microsoft&lt;/strong&gt; también ha liberado el código fuente de su plataforma de desarrollo más preciada: &lt;strong&gt;.NET Framework.&lt;/strong&gt; Y las bases de esta plataforma y&lt;strong&gt; el lenguaje C# se encuentran definidos como estándares internacionales por la ECMA&lt;/strong&gt;; lo que ha permitido el desarrollo de nuevas iniciativas Open Source como el &lt;strong&gt;Proyecto Mono&lt;/strong&gt; (&lt;a href="http://www.mono-project.com/"&gt;http://www.mono-project.com&lt;/a&gt;) y el &lt;strong&gt;Proyecto dotGNU&lt;/strong&gt; (&lt;a href="http://www.dotgnu.org"&gt;http://www.dotgnu.org&lt;/a&gt;)&lt;/p&gt;  &lt;h4&gt;Mito 3: Si es Software Propietario, hay que pagar licencias&lt;/h4&gt;  &lt;p&gt;Hoy en día muchas empresas ofrecen innumerables productos, plataformas y servicios en forma totalmente gratuita. Empresas como &lt;strong&gt;Sun&lt;/strong&gt;, &lt;strong&gt;Adobe&lt;/strong&gt;, &lt;strong&gt;HP&lt;/strong&gt;, &lt;strong&gt;Oracle&lt;/strong&gt; y &lt;strong&gt;Microsoft&lt;/strong&gt; ofrecen desde programas de usuario final hasta completas suites de desarrollo y potentes motores de bases de datos en forma totalmente gratuitas.&lt;/p&gt;  &lt;p&gt;Por ejemplo:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Sun Microsystem&lt;/strong&gt; entrega en forma gratuita su suite de desarrollo &lt;strong&gt;Sun Studio 12&lt;/strong&gt; (&lt;a href="http://developers.sun.com/sunstudio/downloads/"&gt;http://developers.sun.com/sunstudio/downloads/&lt;/a&gt;) y la base de datos &lt;strong&gt;MySql&lt;/strong&gt;.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Por su parte &lt;strong&gt;Microsoft&lt;/strong&gt; ofrece la suite de desarrollo &lt;strong&gt;Visual Studio 2008 Express&lt;/strong&gt; y &lt;strong&gt;SQL Server 2008 Express&lt;/strong&gt; (&lt;a href="http://www.microsoft.com/express/"&gt;http://www.microsoft.com/express/&lt;/a&gt;). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Las prestaciones de estas herramientas son totalmente funcionales y permiten el desarrollo de soluciones completas y de calidad profesional, no hay que pagar licencias para usarlas. &lt;/p&gt;  &lt;h4&gt;Mito 4: Si la licencia de uso es gratis, el costo del sistema es cero&lt;/h4&gt;  &lt;p&gt;Quizás este sea el mito qué más puede confundir y perjudicar. &lt;strong&gt;El costo real de un sistema no está en las licencias de uso&lt;/strong&gt;, sino en el mantenimiento y soporte necesario durante todo el ciclo de vida.&lt;/p&gt;  &lt;p&gt;Cada empresa u organización debe evaluar si dispone y/o puede costear el personal técnico capacitado para dar soporte y mantenimiento a los sistemas antes de implementarlos. También debe evaluar el respaldo tecnológico asociado a la plataforma elegida, la comunidad de usuarios técnicos y no técnicos, etc.&lt;/p&gt;  &lt;p&gt;Hace tiempo que las empresas y el mundo han comprendido que nada es realmente gratis, todo tiene un costo asociado. Y en las soluciones informáticas, generalmente el principal costo reside en el soporte y mantenimiento que asegure el funcionamiento de los sistemas en las condiciones apropiadas.&lt;/p&gt;  &lt;p&gt;Finalmente, &lt;strong&gt;no se encuentra mucho valor al enfocarse solo en el costo de la solución&lt;/strong&gt;, &lt;strong&gt;sino en los beneficios que éste puede brindar&lt;/strong&gt;. Volvemos al principio: la relación costo/beneficio.&lt;/p&gt;  &lt;h4&gt;Usar lo mejor de cada mundo&lt;/h4&gt;  &lt;p&gt;La buena noticia de todo esto es que &lt;strong&gt;existe competitividad y un gran abanico de posibilidades&lt;/strong&gt; para elegir. Además no todo es blanco o negro, existe la interoperabilidad entre plataformas. &lt;/p&gt;  &lt;p&gt;Por ejemplo, existen soluciones en &lt;strong&gt;ASP.NET&lt;/strong&gt; usando como bases de datos &lt;strong&gt;MySql&lt;/strong&gt; o &lt;strong&gt;PostgreSql&lt;/strong&gt;. Lo mismo ocurre con &lt;strong&gt;Java&lt;/strong&gt; y las plataformas de &lt;strong&gt;Sun&lt;/strong&gt;; y desde &lt;strong&gt;PHP&lt;/strong&gt; podemos conectarnos a &lt;strong&gt;Microsoft SQL Server&lt;/strong&gt; u &lt;strong&gt;Oracle&lt;/strong&gt;. Y ni hablar si usando un enfoque &lt;strong&gt;SOA&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;En un proyecto actual en el que estoy trabajando, incluye una solución de escritorio, destinado al sector educativo. Hemos visto que todas las escuelas de la región que intentamos dar cobertura tienen PCs con &lt;strong&gt;Windows XP y Office&lt;/strong&gt;. Analizando este escenario:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;¿Porqué querríamos cambiar a Linux?&lt;/strong&gt; &lt;strong&gt;¿Por las licencias?&lt;/strong&gt;       &lt;br /&gt;&lt;strong&gt;Microsoft&lt;/strong&gt; le ha otorgado &lt;strong&gt;licencias a costo casi cero a todas las escuelas&lt;/strong&gt;.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Y si así no lo fuera, &lt;strong&gt;¿cuál sería el costo de contratar personal capacitado para instalar Linux en todas las escuelas?&lt;/strong&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;¿Cuánto costará y cuánto tiempo llevará capacitar al personal administrativo?&lt;/strong&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;¿Qué costos tendría el cambio radical de sus programas y su forma de trabajo al personal?&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Con esto &lt;strong&gt;no quiero decir que Linux sea una mala opción&lt;/strong&gt;. Sino que siempre hay que evaluar el escenario. Quizás aquí podría ajustarse una solución desktop para Windows basada en &lt;strong&gt;Java&lt;/strong&gt; o &lt;strong&gt;.NET&lt;/strong&gt; usando como motor de datos &lt;strong&gt;MySql&lt;/strong&gt; o &lt;strong&gt;SQL Server Express&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;En definitiva, creo que la clave está en &lt;strong&gt;evaluar y saber elegir las soluciones más convenientes y apropiadas para cada escenario&lt;/strong&gt;. Podemos usar lo mejor de cada mundo y debemos tener siempre presente la relación costo/beneficio y podría destacar entre los beneficios, la &lt;strong&gt;proyección y visión hacia futuro&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Bueno, espero haber aportado algo de claridad sobre este tema tan discutido.    &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-5235801086263368802?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/5235801086263368802/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=5235801086263368802&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5235801086263368802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5235801086263368802'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/03/software-libre-vs-software-propietario.html' title='Software Libre vs Software Propietario'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-5306877237091011137</id><published>2009-03-08T14:20:00.001-02:00</published><updated>2011-07-05T12:11:35.005-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>ADO.NET Entity Framework: The version of SQL Server in use does not support datatype 'datetime2'</title><content type='html'>&lt;p&gt;Trabajando con ADO.NET EF, en mi entorno de desarrollo tengo &lt;strong&gt;SQL Server 2008&lt;/strong&gt; y en producción está &lt;strong&gt;SQL Server 2005&lt;/strong&gt;. Al publicar mi aplicación, en algunas páginas obtengo el siguiente error:&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" face="Consolas"&gt;The version of SQL Server in use does not support datatype 'datetime2'&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;SQL Server 2008&lt;/strong&gt; dispone de un nuevo tipo de datos &lt;strong&gt;Datetime2&lt;/strong&gt; que agrega soporte mejorado de fechas y horas. &lt;/p&gt;  &lt;p&gt;Por ejemplo, &lt;strong&gt;Datetime2&lt;/strong&gt; soporta fechas y horas desde &lt;strong&gt;0001-01-01 00:00:00&lt;/strong&gt; hasta &lt;strong&gt;9999-12-31 23:59:59.9999999&lt;/strong&gt; (nanosegundos de precisión), mientras que el conocido &lt;strong&gt;Datetime&lt;/strong&gt; solo acepta rangos desde &lt;strong&gt;1753-01-01 00:00:00&lt;/strong&gt; hasta &lt;strong&gt;9999-12-31 23-59:59.999&lt;/strong&gt; (solo milisegundos de precisión). Pueden leer más sobre esto en el siguiente enlace (en inglés): &lt;a href="http://aartemiou.blogspot.com/2008/12/datetime2-vs-datetime-in-sql-server.html"&gt;DATETIME2 vs DATETIME in SQL Server 2008&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para resolver el problema de incompatibilidad usando ADO.NET Entity Framework hay que abrir el archivo .edmx con el editor de XML y cambiar el valor del atributo &lt;strong&gt;ProviderManifestToken&lt;/strong&gt; a 2005.&lt;/p&gt;  &lt;p&gt;&lt;font color="#004080" face="consolas"&gt;&amp;lt;edmx:Runtime&amp;gt;      &lt;br /&gt;&amp;lt;edmx:StorageModels&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;Schema Alias=&amp;quot;Self&amp;quot; Provider=&amp;quot;System.Data.SqlClient&amp;quot; &lt;strong&gt;ProviderManifestToken=&amp;quot;2005&amp;quot;&lt;/strong&gt;&amp;gt;       &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Luego guardamos los cambios en el modelo y recompilamos la aplicación. Esto resolverá el error de versiones.&lt;/p&gt;  &lt;p&gt;Algo importante a saber es que si posteriormente actualizamos el modelo en nuestro entorno de desarrollo el atributo &lt;strong&gt;ProviderManifestToken&lt;/strong&gt; volverá a establecerse al valor 2008 y deberemos cambiarlo manualmente antes de publicar nuestra aplicación.&lt;/p&gt;  &lt;p&gt;Quizás con una tarea postbuild podríamos hacer este cambio automáticamente. Si alguien se anima a crear una tarea como esta será bienvenida.&lt;/p&gt;  &lt;p&gt;Espero que sirva.    &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-5306877237091011137?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/5306877237091011137/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=5306877237091011137&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5306877237091011137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5306877237091011137'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/03/adonet-entity-framework-version-of-sql.html' title='ADO.NET Entity Framework: The version of SQL Server in use does not support datatype &amp;#39;datetime2&amp;#39;'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1716887144017335235</id><published>2009-03-06T14:24:00.001-02:00</published><updated>2009-03-06T14:42:23.349-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Paginación y Ordenamiento del lado servidor con GridView y ADO.NET Entity Framework</title><content type='html'>&lt;p&gt;Esta vez quiero mostrarles como actualmente estoy implementando paginación y ordenamiento del lado servidor, usando &lt;strong&gt;GridView&lt;/strong&gt;, &lt;strong&gt;ObjectDataSource&lt;/strong&gt; y &lt;strong&gt;ADO.NET EF&lt;/strong&gt;. Aunque de una forma muy similar también es aplicable a &lt;strong&gt;LINQ2SQL&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Creando los métodos en la capa de negocio o servicios&lt;/h4&gt;  &lt;p&gt;El primer paso consiste en crear en nuestra capa de negocios o servicios un par de métodos que luego serán invocados por el control &lt;strong&gt;ObjectDataSource&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Básicamente necesito 2 métodos para lograr mi objetivo:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Un método que me devuelva la cantidad total de registros&lt;/li&gt;    &lt;li&gt;Y otro método que me devuelva los registros paginados&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Para el ejemplo voy a crear en una clase &lt;strong&gt;CatalogService&lt;/strong&gt;, un método &lt;strong&gt;FindProducts&lt;/strong&gt;() y otro método &lt;strong&gt;FindProductsCount&lt;/strong&gt;().&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;public IList&amp;lt;Product&amp;gt; &lt;strong&gt;FindProducts&lt;/strong&gt;(int? code, string description, int? categoryID, string sortExpression, int startRows, int maxRows)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; using (var db = new StoreEntities())      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var query = from p in db.Products select p; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = FindProductsFilter(query, code, description, categoryID);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = FindProductsSort(query, sortExpression); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return query.Skip(startRows).Take(maxRows).ToList();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Aquí vemos que &lt;strong&gt;FindProducts&lt;/strong&gt;() llamá a 2 métodos &lt;strong&gt;FindProductsFilter&lt;/strong&gt;() y &lt;strong&gt;FindProductsSort&lt;/strong&gt;() que se encargan de aplicar los filtros necesarios y ordenar los registros, y luego usa los métodos &lt;strong&gt;Skip&lt;/strong&gt; y &lt;strong&gt;Take&lt;/strong&gt; para paginar los resultados.&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;private static IQueryable&amp;lt;Product&amp;gt; &lt;strong&gt;FindProductsFilter&lt;/strong&gt;(IQueryable&amp;lt;Product&amp;gt; query, int? code, string description, int? categoryID)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (code.HasValue)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = query.Where(p =&amp;gt; p.Code== code); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160; if (!string.IsNullOrEmpty(description))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = query.Where(p =&amp;gt; p.Description== description); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160; if (categoryID.HasValue)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = query.Where(p =&amp;gt; p.Category.ID== categoryID); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160; return query;     &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;private IQueryable&amp;lt;Product&amp;gt; &lt;strong&gt;FindProductsSort&lt;/strong&gt;(IQueryable&amp;lt;Product&amp;gt; query, string sortExpression)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (string.IsNullOrEmpty(sortExpression))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return query.OrderBy(p =&amp;gt; p.Description); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160; return query.&lt;strong&gt;OrderBy&lt;/strong&gt;(sortExpression);      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Es importante saber que el método &lt;strong&gt;OrderBy&lt;/strong&gt;() no acepta un parámetro string para realizar el ordenamiento. Sin embargo, aquí estoy usando unas extensiones de LINQ conocidas como &lt;strong&gt;Dynamic Query &lt;/strong&gt;para lograr este objetivo. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Pueden leer un artículo de Scot Guthrie traducido al español sobre &lt;/em&gt;&lt;a href="http://thinkingindotnet.wordpress.com/2008/01/08/dynamic-linqparte-1-usando-la-libreria-de-linq-dynamic/"&gt;&lt;em&gt;Dynamic Query&lt;/em&gt;&lt;/a&gt;&lt;em&gt; y descargar el código fuente.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Sin &lt;strong&gt;Dynamic Query&lt;/strong&gt;, tendría que parsear el parámetro &lt;strong&gt;sortExpression&lt;/strong&gt; y escribir un switch o multiples ifs para aplicar el &lt;strong&gt;OrderBy&lt;/strong&gt; correspondiente según el campo. En pocas palabras, tendría que escribir muuucho más código, entonces prefiero Dynamic Query.&lt;/p&gt;  &lt;p&gt;Y ahora el método &lt;strong&gt;FindProductsCount&lt;/strong&gt;() que no hace otra cosa más que contabilizar el total de productos. Este método lo utiliza el &lt;strong&gt;ObjectDataSource&lt;/strong&gt; y la &lt;strong&gt;grilla&lt;/strong&gt; para poder calcular el total de páginas necesarias, sin tener que traer todos los registros para luego paginarlos.&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas" color="#004080"&gt;public int &lt;strong&gt;FindProductsCount&lt;/strong&gt;(int? code, string description, int? categoryID)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; using (var db = new StoreEntities())      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var query = from p in db.Products select p; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; query = FindProductsFilter(query, code, description, categoryID); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas" color="#004080"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return query.&lt;strong&gt;Count&lt;/strong&gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Consumiendo los métodos desde la UI&lt;/h4&gt;  &lt;p&gt;Ahora creo una página aspx con unos &lt;strong&gt;campos para filtrar&lt;/strong&gt;, un &lt;strong&gt;botón&lt;/strong&gt; y una &lt;strong&gt;grilla asociada a un ObjectDataSource&lt;/strong&gt; para los resultados. El formulario se vería mas o menos así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SbFOITpbRgI/AAAAAAAAAI4/GIeIFDWO_Dc/s1600-h/image%5B3%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="463" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SbFOI4t5DAI/AAAAAAAAAI8/QGO1-YQIM0I/image_thumb%5B1%5D.png?imgmax=800" width="485" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;No deseo explicar cómo enlazar la grilla con un &lt;strong&gt;ObjectDataSource&lt;/strong&gt;, solo bastaría con decir que debemos asociar al método &lt;strong&gt;FindProducts&lt;/strong&gt;() creado anteriormente y asociar los parámetros del método con los controles de la página. Y luego hay que habilitar &lt;strong&gt;Paging&lt;/strong&gt; y &lt;strong&gt;Sorting&lt;/strong&gt; en la grilla.&lt;/p&gt;  &lt;p&gt;Las propiedades establecidas para el &lt;strong&gt;ObjectDataSource&lt;/strong&gt; aparecen en &lt;strong&gt;negrita&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/SbFOKeYVUSI/AAAAAAAAAJA/yJiWXoniPis/s1600-h/image%5B7%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="553" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SbFOLBkcuxI/AAAAAAAAAJE/WUqx60uhWW8/image_thumb%5B3%5D.png?imgmax=800" width="511" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Las propiedades &lt;strong&gt;sortExpression&lt;/strong&gt;, &lt;strong&gt;startRows&lt;/strong&gt; y &lt;strong&gt;maxRows&lt;/strong&gt; serán pobladas y pasadas al método &lt;strong&gt;FindProducts&lt;/strong&gt; y/o &lt;strong&gt;FindProductsCount&lt;/strong&gt; automáticamente.&lt;/p&gt;  &lt;p&gt;La última pieza es escribir código para el botón Buscar:&lt;/p&gt;  &lt;p&gt;protected void &lt;strong&gt;FindButton_Click&lt;/strong&gt;(object sender, EventArgs e)    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (!Page.IsValid) return; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; try   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; ProductsGridView.&lt;strong&gt;DataSourceID&lt;/strong&gt; = &lt;strong&gt;ProductsDataSource.ID&lt;/strong&gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ProductsGridView.&lt;strong&gt;DataBind&lt;/strong&gt;();      &lt;br /&gt;}      &lt;br /&gt;catch (Exception ex)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ShowError(ex.Message);      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;}&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Debe observarse que solo en runtime estoy enlazando la grilla con el control ObjectDataSource. Es decir, después de configurar la grilla y el ObjectDataSource, en tiempo de diseño, &lt;strong&gt;quito la referencia al ObjectDataSource en la propiedad DataSourceID de la grilla&lt;/strong&gt;. De esta forma, cuando la página se carga no se hace una búsqueda automática, sino solo cuando se completan los filtros de búsqueda y se presiona el botón &lt;strong&gt;Buscar&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Pero esto es una particularidad que quise implementar y no tiene ningún efecto sobre la paginación y ordenamiento, motivo de este post.&lt;/p&gt;  &lt;p&gt;Bueno creo que ya está todo, ahora hay que probar.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SbFOMUA-hnI/AAAAAAAAAJI/IrG0P4k4WUI/s1600-h/image%5B15%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="426" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SbFONqrAWfI/AAAAAAAAAJM/L_PuGgJ2r-g/image_thumb%5B9%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;A mí me funcionó de maravillas ;-). &lt;/p&gt;  &lt;p&gt;Mirando con el &lt;strong&gt;SQL Profiler&lt;/strong&gt; veo que solo se consultan 10 registros por página. Las consultas al &lt;strong&gt;SQL Server&lt;/strong&gt; devuelven solo los registros que el usuario quiere ver. Esto permite que &lt;strong&gt;nuestras aplicaciones sean mucho más escalables&lt;/strong&gt;, pues solo traemos los registros necesarios y se minimiza la carga de trabajo en la BD.&lt;/p&gt;  &lt;p&gt;Bueno espero que sirva.   &lt;br /&gt;Comentarios son bienvenidos!&lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1716887144017335235?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1716887144017335235/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1716887144017335235&amp;isPopup=true' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1716887144017335235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1716887144017335235'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/03/paginacion-y-ordenamiento-del-lado.html' title='Paginación y Ordenamiento del lado servidor con GridView y ADO.NET Entity Framework'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_apvGJDAiQ0E/SbFOI4t5DAI/AAAAAAAAAI8/QGO1-YQIM0I/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-902767393848424988</id><published>2009-03-06T12:32:00.001-02:00</published><updated>2009-03-06T12:34:31.953-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><title type='text'>RUN09</title><content type='html'>&lt;p&gt;Este es el nombre que finalmente fue bautizado al antes llamado &lt;strong&gt;Buenos Aires Briefing&lt;/strong&gt;. Hoy &lt;strong&gt;&lt;a href="http://blogs.msdn.com/masaez"&gt;Miguel Saez&lt;/a&gt;&lt;/strong&gt; nos avisa que ya está disponible el site del evento en &lt;a title="http://www.puertadeenlace.net/run09" href="http://www.puertadeenlace.net/run09"&gt;http://www.puertadeenlace.net/run09&lt;/a&gt;. Desde este sitio podrán registrarse, ver los oradores y revisar la Agenda del evento, y quizás descubrir algunas perlitas del site.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SbEz7KGA0EI/AAAAAAAAAIw/Wsg-Y29ZrbY/s1600-h/image%5B3%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="254" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SbEz7vdi_LI/AAAAAAAAAI0/9_NaIGsaHJU/image_thumb%5B1%5D.png?imgmax=800" width="323" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Es de destacar que el site tiene una &lt;strong&gt;UI inspirada en Windows 1.0&lt;/strong&gt;, pero está desarrollado con las últimas tecnologías de MS. Incluso mike nos comenta en su &lt;a href="http://blogs.msdn.com/masaez/archive/2009/03/05/run09-services.aspx"&gt;blog&lt;/a&gt; que está disponible un servicio de WCF (&lt;a title="http://www.puertadeenlace.net/run09/Models/Service.svc/" href="http://www.puertadeenlace.net/run09/Models/Service.svc/"&gt;http://www.puertadeenlace.net/run09/Models/Service.svc/&lt;/a&gt;) que se puede usar para construir otro cliente para el evento en &lt;strong&gt;Silverlight&lt;/strong&gt;, &lt;strong&gt;WPF&lt;/strong&gt; o &lt;strong&gt;Gadget de Vista&lt;/strong&gt; y quizás ganar un poco de publicidad durante el evento.&lt;/p&gt;  &lt;p&gt;Bueno, a tomarse un respiro y aprovechar este evento. Seguramente nos encontramos allí.   &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-902767393848424988?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/902767393848424988/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=902767393848424988&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/902767393848424988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/902767393848424988'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/03/run09.html' title='RUN09'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_apvGJDAiQ0E/SbEz7vdi_LI/AAAAAAAAAI0/9_NaIGsaHJU/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-4021245750434597408</id><published>2009-02-04T23:58:00.001-02:00</published><updated>2009-02-04T23:58:07.742-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><title type='text'>Buenos Aires Briefing 09 o busquemos un nuevo nombre</title><content type='html'>&lt;p&gt;La gente de Microsoft Argentina y Uruguay est&amp;#225;n trabajando en la organizaci&amp;#243;n del pr&amp;#243;ximo evento &amp;quot;&lt;strong&gt;Buenos Aires Briefing 09&lt;/strong&gt;&amp;quot; con fecha &lt;strong&gt;25 de Marzo&lt;/strong&gt;. Se espera contar con la presencia de m&amp;#225;s &lt;strong&gt;de 1000 profesionales &lt;/strong&gt;al evento entre &lt;strong&gt;desarrolladores&lt;/strong&gt; y &lt;strong&gt;profesionales de IT&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Se invita a toda la comunidad a &lt;strong&gt;sumar sus aportes con ideas, sugerencias y comentarios&lt;/strong&gt; a trav&amp;#233;s del sitio &lt;a href="http://www.puertadeenlace.net"&gt;www.puertadeenlace.net&lt;/a&gt;: un espacio para compartir con la comunidad de Desarrolladores y Profesionales IT en tecnolog&amp;#237;as Microsoft. Pronto se estar&amp;#225; definiendo la agenda y los oradores.&lt;/p&gt;  &lt;p&gt;Desde ahora podemos empezar a colaborar:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.puertadeenlace.net/post/Ponele-nombre-al-evento.aspx"&gt;Poniendo un nuevo nombre al evento&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.puertadeenlace.net/post/Que-temas-queres-ver-en-el-evento.aspx"&gt;Definiendo qu&amp;#233; temas nos interesa para el evento&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Difundiendo el evento en sus blogs, sites, amigos, vecinos, etc.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Bueno, la invitaci&amp;#243;n ya est&amp;#225; hecha y seguiremos los avances del evento. Estoy seguro que ser&amp;#225; uno de los grandes eventos del a&amp;#241;o. &lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-4021245750434597408?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/4021245750434597408/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=4021245750434597408&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4021245750434597408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4021245750434597408'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/02/buenos-aires-briefing-09-o-busquemos-un.html' title='Buenos Aires Briefing 09 o busquemos un nuevo nombre'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-7391791337936678922</id><published>2009-01-29T09:42:00.001-02:00</published><updated>2011-07-05T12:13:44.035-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>ADO.NET Entity Framework: ¿Cómo actualizar un objeto desconectado?</title><content type='html'>&lt;p&gt;Un escenario común es el siguiente:&lt;/p&gt;  &lt;p&gt;&amp;quot;Al enviar un formulario web, creo una entidad &lt;strong&gt;Pedido&lt;/strong&gt; con los datos proporcionados por el usuario y lo entrego a mi capa de negocios o servicios para que se valide y persista en el almacén de datos.&amp;quot;&lt;/p&gt;  &lt;p&gt;En este escenario la entidad &lt;strong&gt;Pedido&lt;/strong&gt; enviada desde la página web (o enviada desde un Web Service), se encuentra en estado &lt;strong&gt;Deattached&lt;/strong&gt;. Para que podamos persistir sus cambios necesitamos asociarla a un contexto y luego llamar al método &lt;strong&gt;SaveChanges&lt;/strong&gt;().&lt;/p&gt;  &lt;p&gt;Si la entidad aún no existe en el almacén de datos, debemos agregarla. Esto es muy simple, usando los métodos &lt;strong&gt;AddTo*&lt;/strong&gt; generados en el modelo:&lt;/p&gt;  &lt;p&gt;context.&lt;strong&gt;AddToOrders&lt;/strong&gt;(order);     &lt;br /&gt;context.&lt;strong&gt;SaveChanges&lt;/strong&gt;();&lt;/p&gt;  &lt;p&gt;En cambio si la entidad ya existe en el almacén de datos, entonces debemos asociarla al contexto y guardar los cambios. Esta tarea parece ser simple y podríamos intentar resolverla de la siguiente manera:&lt;/p&gt;  &lt;p&gt;context.&lt;strong&gt;AttachTo&lt;/strong&gt;(&amp;quot;Orders&amp;quot;, order);     &lt;br /&gt;context.&lt;strong&gt;SaveChanges&lt;/strong&gt;();&lt;/p&gt;  &lt;p&gt;Sin embargo, esto no funciona, pues el objeto &lt;strong&gt;order&lt;/strong&gt; se asocia exitosamente al contexto pero en el estado &lt;strong&gt;Unchanged&lt;/strong&gt;. Luego el método &lt;strong&gt;SaveChanges&lt;/strong&gt;() no persiste ningún cambio.&lt;/p&gt;  &lt;p&gt;La forma de resolver este problema es recuperando la entidad original desde el almacén de datos, aplicar los cambios, y volver a guardarla.&lt;/p&gt;  &lt;p&gt;Buscando en la web encontré diferentes enfoques para resolver este problema. Muchos utilizan &lt;strong&gt;Reflection&lt;/strong&gt; para recorrer todas las propiedades y asignar las que han cambiado. La que más me ha interesado la encontré en el &lt;a href="http://blogs.msdn.com/cesardelatorre/archive/2008/09/04/updating-data-using-entity-framework-in-n-tier-and-n-layer-applications-short-lived-ef-contexts.aspx"&gt;blog de Cesar de la Torre&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Se trata de un extension method llamado &lt;strong&gt;AttachUpdated&lt;/strong&gt;() aplicado al &lt;strong&gt;ObjectContext&lt;/strong&gt;. Me he tomado el atrevimiento de renombrar le método &lt;strong&gt;AttacheUpdated&lt;/strong&gt;() por &lt;strong&gt;UpdateObject&lt;/strong&gt;(), pues me pareció más consistente con otros métodos que ya existen en el ObjectContext como &lt;strong&gt;AddObject&lt;/strong&gt;() y &lt;strong&gt;DeleteObject&lt;/strong&gt;(). El código es el siguiente:&lt;/p&gt;  &lt;p&gt;public static void &lt;strong&gt;UpdateObject&lt;/strong&gt;(this &lt;strong&gt;ObjectContext&lt;/strong&gt; context, string entitySetName, EntityObject entity)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var key = context.&lt;strong&gt;CreateEntityKey&lt;/strong&gt;(entitySetName, entity); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; object originalEntity;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (context.&lt;strong&gt;TryGetObjectByKey&lt;/strong&gt;(key, out originalEntity))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.&lt;strong&gt;ApplyPropertyChanges&lt;/strong&gt;(entitySetName, entity);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; context.&lt;strong&gt;ApplyReferencePropertyChanges&lt;/strong&gt;(entity, (IEntityWithRelationships)originalEntity);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ObjectNotFoundException();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Este método primero crea la &lt;strong&gt;EntityKey&lt;/strong&gt; asociada al objeto usando el método &lt;strong&gt;CreateEntityKey&lt;/strong&gt;() y luego intenta recuperar el objeto desde el almacén de datos usando el método &lt;strong&gt;TryGetObjectByKey&lt;/strong&gt;(). A continuación aplica los cambios usando el método &lt;strong&gt;ApplyPropertyChanges&lt;/strong&gt;() y luego llama al método &lt;strong&gt;ApplyReferencePropertyChanges&lt;/strong&gt;() que se encarga de aplicar los cambios a las entidades relacionadas. Este último método se trata de otro extension method:&lt;/p&gt;  &lt;p&gt;private static void &lt;strong&gt;ApplyReferencePropertyChanges&lt;/strong&gt;(this ObjectContext context, IEntityWithRelationships newEntity, IEntityWithRelationships oldEntity)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; foreach (var relatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds())     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var oldRef = relatedEnd as EntityReference; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (oldRef != null)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var newRef = newEntity.RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (newRef != null) oldRef.EntityKey = newRef.EntityKey;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Aquí no solo se resuelve el problema de aplicar los cambios a las propiedades del objeto en cuestión sino también los cambios en sus objetos relacionados.&lt;/p&gt;  &lt;p&gt;Luego de crear estos extensions methods, el código final para actualizar una entidad desconectada quedaría como:&lt;/p&gt;  &lt;p&gt;context.&lt;strong&gt;UpdateObject&lt;/strong&gt;(&amp;quot;Orders&amp;quot;, order); //Extension method     &lt;br /&gt;context.&lt;strong&gt;SaveChanges&lt;/strong&gt;();&lt;/p&gt;  &lt;p&gt;He probado esto y funcionó para mí. Espero que también les sea de utilidad.&lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-7391791337936678922?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/7391791337936678922/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=7391791337936678922&amp;isPopup=true' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7391791337936678922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7391791337936678922'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/adonet-entity-framework-como-actualizar.html' title='ADO.NET Entity Framework: ¿Cómo actualizar un objeto desconectado?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-6851507486303594474</id><published>2009-01-28T10:09:00.001-02:00</published><updated>2011-07-05T12:14:58.152-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>ADO.NET Entity Framework: Nuevos proveedores de datos</title><content type='html'>&lt;p&gt;En el &lt;a href="http://blogs.msdn.com/adonet/"&gt;blog del equipo de ADO.NET Entity Framework&lt;/a&gt; se anuncia que están disponibles nuevos proveedores para ADO.NET EF, incluyendo versiones Beta.&lt;/p&gt;  &lt;p&gt;Pueden leer más y descargar estos providers desde el siguiente link:    &lt;br /&gt;&lt;a title="http://msdn.microsoft.com/en-us/data/dd363565.aspx" href="http://msdn.microsoft.com/en-us/data/dd363565.aspx"&gt;http://msdn.microsoft.com/en-us/data/dd363565.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SYBLABTEQmI/AAAAAAAAAIo/06Y0K8F6XaA/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/SYBLBPg4F5I/AAAAAAAAAIs/Uxj404gpfgo/image_thumb%5B1%5D.png?imgmax=800" width="416" height="627" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-6851507486303594474?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/6851507486303594474/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=6851507486303594474&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6851507486303594474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6851507486303594474'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/adonet-entity-framework-lista-de.html' title='ADO.NET Entity Framework: Nuevos proveedores de datos'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_apvGJDAiQ0E/SYBLBPg4F5I/AAAAAAAAAIs/Uxj404gpfgo/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-4211936399927405042</id><published>2009-01-28T09:49:00.001-02:00</published><updated>2011-07-05T12:25:49.034-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><title type='text'>ADO.NET Entity Framework: ¿Cómo cambiar la ForeignKey de un objeto?</title><content type='html'>&lt;p&gt;Tengo un formulario de edición de un &lt;strong&gt;Producto&lt;/strong&gt;, y entre muchos otros datos, se debe seleccionar, por ejemplo, la &lt;strong&gt;Categoría&lt;/strong&gt; desde un DropDownList. Al guardar el producto, se debe establecer el ID de la categoría asociada.&lt;/p&gt;  &lt;p&gt;La intuición nos llevaría a escribir el siguiente código:    &lt;br /&gt;    &lt;br /&gt;product.&lt;strong&gt;Category.Id&lt;/strong&gt; = Convert.ToInt32(CategoryDropDownList.SelectedValue);&lt;/p&gt;  &lt;p&gt;Desafortunadamente, esto provocará un error, porque la propiedad &lt;strong&gt;Category&lt;/strong&gt; es &lt;strong&gt;null&lt;/strong&gt;, o bien porque no se puede cambiar la propiedad Id.&lt;/p&gt;  &lt;p&gt;Para resolver el problema podemos escribir lo siguiente:&lt;/p&gt;  &lt;p&gt;var categoryId = Convert.ToInt32(CategoryDropDownList.SelectedValue);    &lt;br /&gt;product.&lt;strong&gt;CategoryReference.EntityKey = &lt;/strong&gt;new EntityKey(&amp;quot;ContosoEntities.Categories&amp;quot;, &amp;quot;Id&amp;quot;, categoryId);     &lt;br /&gt;    &lt;br /&gt;En lugar de la propiedad &lt;strong&gt;Category&lt;/strong&gt; estamos usando la propiedad &lt;strong&gt;CategoryReference&lt;/strong&gt; y estamos asignando una nueva &lt;strong&gt;EntityKey&lt;/strong&gt;. Esto permitirá que cuando ejecutemos el método &lt;strong&gt;SaveChanges&lt;/strong&gt;, los cambios de la categoría asociada al producto se persistan en el almacén de datos.&lt;/p&gt;  &lt;p&gt;Particularmente esta forma de resolver el problema me parece poco intuitiva y elegante. Algo tan simple como cambiar una clave externa implica escribir todo ese código. Sin embargo, hasta ahora, parece ser la única forma de resolver el problema.&lt;/p&gt;  &lt;p&gt;Si nos interesa mejorar un poco nuestro código, y escribir algo más simple, podríamos crear una clase &lt;strong&gt;Partial&lt;/strong&gt; de &lt;strong&gt;Product&lt;/strong&gt;, y agregar una propiedad &lt;strong&gt;CategoryId&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;public int &lt;strong&gt;CategoryId&lt;/strong&gt;     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160; get     &lt;br /&gt;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Convert.ToInt32(CategoryReference.&lt;strong&gt;EntityKey.EntityKeyValues[0].Value&lt;/strong&gt;);     &lt;br /&gt;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; set    &lt;br /&gt;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var qualifiedEntitySet = &amp;quot;ContosoEntities.Categories&amp;quot;;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;CategoryReference.EntityKey&lt;/strong&gt; &lt;strong&gt;=&lt;/strong&gt; new EntityKey(qualifiedEntitySet, &amp;quot;Id&amp;quot;, value);     &lt;br /&gt;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Esta propiedad adicional, permitirá escribir algo como:&lt;/p&gt;  &lt;p&gt;product.&lt;strong&gt;CategoryId&lt;/strong&gt; = Convert.ToInt32(CategoryDropDownList.SelectedValue);&lt;/p&gt;  &lt;p&gt;Muy similar a los que habíamos intentado al principio!&lt;/p&gt;  &lt;p&gt;Antes de terminar, alguien podrá decir: &lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;Usando LINQ TO SQL, estas propiedades se generan automáticamente cuando se crea el modelo.&amp;quot;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Es cierto! Pueden dirigir sus comentarios y sugerencias al &lt;a href="http://blogs.msdn.com/adonet/"&gt;Blog del Equipo de ADO.NET Entity Framework&lt;/a&gt;, y quizás tengamos suerte para la siguiente versión.&lt;/p&gt;  &lt;p&gt;Hasta la próxima! Espero que sirva.    &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-4211936399927405042?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/4211936399927405042/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=4211936399927405042&amp;isPopup=true' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4211936399927405042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4211936399927405042'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/adonet-entity-framework-como-cambiar-la.html' title='ADO.NET Entity Framework: ¿Cómo cambiar la ForeignKey de un objeto?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1408180299502006111</id><published>2009-01-28T09:04:00.001-02:00</published><updated>2009-01-28T09:06:03.349-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>ASP.NET Performance Tip: Eliminar HttpModules innecesarios</title><content type='html'>&lt;p&gt;En cada solicitud de ASP.NET se ejecutan una serie de m&amp;#243;dulos para completar diferentes tareas. Por ejemplo, el m&amp;#243;dulo &lt;strong&gt;SessionStateModule&lt;/strong&gt; intercepta cada solicitud, recupera la cookie de sesi&amp;#243;n&amp;#160; y carga los datos de sesi&amp;#243;n en el &lt;strong&gt;HttpContext&lt;/strong&gt;. No siempre son necesarios todos los m&amp;#243;dulos, por ejemplo, si est&amp;#225;s usando FormsAuthentication entonces quiz&amp;#225;s no necesites los m&amp;#243;dulos de &lt;strong&gt;WindowsAuthentication&lt;/strong&gt; o &lt;strong&gt;PassportAuthenticacion&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;De forma predeterminada, el archivo machine.config define los siguientes m&amp;#243;dulos:&lt;/p&gt;  &lt;p&gt;&amp;lt;httpModules&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;OutputCache&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Caching.OutputCacheModule&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;Session&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.SessionState.SessionStateModule&amp;quot; /&amp;gt;    &lt;br /&gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;WindowsAuthentication&lt;/strong&gt;&amp;quot;    &lt;br /&gt;type=&amp;quot;System.Web.Security.WindowsAuthenticationModule&amp;quot; /&amp;gt;    &lt;br /&gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;FormsAuthentication&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Security.FormsAuthenticationModule&amp;quot; /&amp;gt;    &lt;br /&gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;PassportAuthentication&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Security.PassportAuthenticationModule&amp;quot; /&amp;gt;    &lt;br /&gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;UrlAuthorization&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Security.UrlAuthorizationModule&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;FileAuthorization&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Security.FileAuthorizationModule&amp;quot; /&amp;gt;    &lt;br /&gt;    &lt;br /&gt;&amp;lt;add name=&amp;quot;&lt;strong&gt;ErrorHandlerModule&lt;/strong&gt;&amp;quot; type=&amp;quot;System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;/httpModules&amp;gt;&lt;/p&gt;  &lt;p&gt;Los m&amp;#243;dulos que no utilizamos en nuestra aplicaci&amp;#243;n ASP.NET, podemos removerlos desde el web.config:&lt;/p&gt;  &lt;p&gt;&amp;lt;httpModules&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;remove name=&amp;quot;WindowsAuthentication&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;remove name=&amp;quot;PassportAuthentication&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;remove name=&amp;quot;AnonymousIdentification&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;remove name=&amp;quot;UrlAuthorization&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;remove name=&amp;quot;FileAuthorization&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;/httpModules&amp;gt;&lt;/p&gt;  &lt;p&gt;Esto reducir&amp;#225; carga de trabajo innecesaria en cada solicitud ASP.NET, y nuestras aplicaciones estar&amp;#225;n un poco m&amp;#225;s optimizadas.&lt;/p&gt;  &lt;p&gt;Pueden encontrar este y otros tips de performance en el siguiente enlace:   &lt;br /&gt;&lt;a title="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx" href="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx"&gt;http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;En futuros posts, continuar&amp;#233; sumando m&amp;#225;s tips de performance, como Compresi&amp;#243;n Http, Optimizaci&amp;#243;n del ViewState, Combinaci&amp;#243;n de Scripts y Css, etc. Incluir&amp;#233; c&amp;#243;digo fuente y herramientas para hacer que nuestras aplicaciones ASP.NET se ejecuten cada vez m&amp;#225;s r&amp;#225;pido.&lt;/p&gt;  &lt;p&gt;Espero que sirva.   &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1408180299502006111?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1408180299502006111/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1408180299502006111&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1408180299502006111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1408180299502006111'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/aspnet-performance-tip-eliminar.html' title='ASP.NET Performance Tip: Eliminar HttpModules innecesarios'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-2444370474024168549</id><published>2009-01-26T18:04:00.001-02:00</published><updated>2009-01-26T18:05:33.178-02:00</updated><title type='text'>Silverlight y PhotoSynth en la presidencia de Obama</title><content type='html'>&lt;p&gt;Como lo dice Scott G. en su &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/01/19/silverlight-and-the-2009-presidential-inauguration.aspx"&gt;blog&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;El d&amp;#237;a de la toma de posesi&amp;#243;n de Barack Obama fue un evento hist&amp;#243;rico. &lt;a href="http://silverlight.net/"&gt;Silverlight&lt;/a&gt; se ha usado como la tecnolog&amp;#237;a que ha permitido asistir a tal evento online.&amp;quot;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Me result&amp;#243; interesante el trabajo armado con &lt;a href="http://photosynth.net/"&gt;PhotoSynth&lt;/a&gt; que nos permite tener una vista 3D del acto de inauguraci&amp;#243;n a partir de fotos 2D tomadas por miles de personas que asistieron al evento. Pueden apreciarlo en el siguiente enlace:    &lt;br /&gt;&lt;a title="http://edition.cnn.com/SPECIALS/2009/44.president/inauguration/themoment/" href="http://edition.cnn.com/SPECIALS/2009/44.president/inauguration/themoment/"&gt;http://edition.cnn.com/SPECIALS/2009/44.president/inauguration/themoment/&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SX4XQ5vnu2I/AAAAAAAAAIg/dnr-QfAPrDA/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SX4XUqHLGKI/AAAAAAAAAIk/YAPL6zjVsco/image_thumb%5B6%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;     &lt;br /&gt;Enjoy It!    &lt;br /&gt;Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-2444370474024168549?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/2444370474024168549/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=2444370474024168549&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2444370474024168549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2444370474024168549'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/silverlight-y-photosynth-en-la.html' title='Silverlight y PhotoSynth en la presidencia de Obama'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_apvGJDAiQ0E/SX4XUqHLGKI/AAAAAAAAAIk/YAPL6zjVsco/s72-c/image_thumb%5B6%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-2111450433248607773</id><published>2009-01-26T17:23:00.001-02:00</published><updated>2009-01-28T09:55:03.225-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ADO.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ADO.NET Entity Framework: ¿Cómo incluir los objetos relacionados?</title><content type='html'>&lt;p&gt;Una tarea com&amp;#250;n en el desarrollo con &lt;a href="http://msdn.microsoft.com/en-us/library/bb399572.aspx"&gt;ADO.NET Entity Framework&lt;/a&gt; es escribir una consulta que incluya una o m&amp;#225;s entidades relacionadas. Por ejemplo, quiero obtener todas las fotos de un autor incluyendo los datos del autor:&lt;/p&gt;  &lt;p&gt;var photos = from p in db.Photos.&lt;strong&gt;Include&lt;/strong&gt;(&amp;quot;Author&amp;quot;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where (p.AuthorId == authorId)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select p;&lt;/p&gt;  &lt;p&gt;El m&amp;#233;todo &lt;strong&gt;Include&lt;/strong&gt; especifica que se incluya la entidad &lt;strong&gt;Author&lt;/strong&gt; asociada a cada &lt;strong&gt;Photo&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Si adem&amp;#225;s del autor, quisiera incluir otra entidad relacionada a la foto como su Categor&amp;#237;a, podr&amp;#237;a agregar otro include:&lt;/p&gt;  &lt;p&gt;var photos = from p in db.Photos.&lt;strong&gt;Include&lt;/strong&gt;(&amp;quot;Author&amp;quot;).&lt;strong&gt;Include&lt;/strong&gt;(&amp;quot;Category&amp;quot;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where (p.AuthorId == authorId)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select p;&lt;/p&gt;  &lt;p&gt;En este caso se incluir&amp;#225; tambi&amp;#233;n la categor&amp;#237;a asociada a cada &lt;strong&gt;Photo&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Otro m&amp;#233;todo que tambi&amp;#233;n permite cargar entidades relacionadas es el m&amp;#233;todo &lt;strong&gt;Load&lt;/strong&gt;(). Supongamos que deseo obtener los datos de una foto y sus palabras claves asociadas, podr&amp;#237;a escribir algo como:&lt;/p&gt;  &lt;p&gt;var photo = db.Photos.First(p =&amp;gt; p.Id == photoId);    &lt;br /&gt;photo.Tags.&lt;strong&gt;Load&lt;/strong&gt;();&lt;/p&gt;  &lt;p&gt;En otro escenario, podr&amp;#237;a interesarme verificar primero, antes de ejecutar el m&amp;#233;todo Load():&lt;/p&gt;  &lt;p&gt;var photo = service.GetPhoto(id);    &lt;br /&gt;if (!photo.Tags.&lt;strong&gt;IsLoaded&lt;/strong&gt;) photo.Tags.Load();&lt;/p&gt;  &lt;p&gt;La propiedad &lt;strong&gt;IsLoaded&lt;/strong&gt; permite comprobar si se han cargado o no los objetos relacionados en la colecci&amp;#243;n de &lt;strong&gt;Tags&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Para simplificar este trabajo, he creado un extension method &lt;strong&gt;EnsureLoad&lt;/strong&gt;() que aplica a &lt;strong&gt;EntityCollection&lt;/strong&gt;, as&amp;#237; el c&amp;#243;digo anterior se reduce a:&lt;/p&gt;  &lt;p&gt;var photo = service.GetPhoto(id);    &lt;br /&gt;photo.Tags.&lt;strong&gt;EnsureLoad&lt;/strong&gt;();&lt;/p&gt;  &lt;p&gt;El c&amp;#243;digo del extension method es el siguiente:&lt;/p&gt;  &lt;p&gt;public static void EnsureLoad&amp;lt;T&amp;gt;(&lt;strong&gt;this&lt;/strong&gt; EntityCollection&amp;lt;T&amp;gt; entityCollection)     &lt;br /&gt;where T: EntityObject     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (!entityCollection.IsLoaded)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; entityCollection.Load();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Bueno, espero que sirva.    &lt;br /&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-2111450433248607773?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/2111450433248607773/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=2111450433248607773&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2111450433248607773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2111450433248607773'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/cmo-incluir-los-objetos-relacionados.html' title='ADO.NET Entity Framework: ¿Cómo incluir los objetos relacionados?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-146487448518635276</id><published>2009-01-26T16:12:00.001-02:00</published><updated>2009-01-26T16:20:55.210-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>Session Timeout vs FormsAuthentication Timeout</title><content type='html'>&lt;p&gt;Muchas veces me preguntan: &lt;strong&gt;&amp;#191;C&amp;#243;mo hago para aumentar el tiempo de sesi&amp;#243;n en una aplicaci&amp;#243;n ASP.NET, y evitar que los usuarios vuelvan a la p&amp;#225;gina de login luego de cierto per&amp;#237;odo de inactividad?&lt;/strong&gt;. Que ya han probado seteando el session timeout en el web.config, setarlo por c&amp;#243;digo, etc. y ASP.NET simplemente ignora esos valores.&lt;/p&gt;  &lt;p&gt;Se trata de un tema que ya tiene unos a&amp;#241;os, pero a&amp;#250;n es bastante recurrente y muchas veces confuso. Por ello, he decido postear un poco al respecto. &lt;/p&gt;  &lt;p&gt;Para comprenderlo mejor hay que considerar al menos 2 timeout independientes:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Session Timeout&lt;/li&gt;    &lt;li&gt;Forms Authentication Timeout&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;b&gt;Session Timeout&lt;/b&gt; define cuanto tiempo debe durar la &lt;b&gt;cookie de sesi&amp;#243;n&lt;/b&gt; en el cliente. Cada vez que el usuario navega en el sitio se guarda una cookie de sesi&amp;#243;n, para identificar las solicitudes del cliente. Esto es independiente de si el usuario se autentic&amp;#243; o no. El valor predeterminado es de 20 minutos, pero puede modificarse con el elemento system.web/&lt;b&gt;sessionState&lt;/b&gt; en el &lt;b&gt;web.config&lt;/b&gt;:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;&lt;strong&gt;sessionState&lt;/strong&gt; mode=&amp;quot;InProc&amp;quot; &lt;strong&gt;timeout=&amp;quot;60&amp;quot;&lt;/strong&gt; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Forms Authentication Timeout&lt;/b&gt; define cuanto tiempo debe durar la &lt;b&gt;cookie de autenticaci&amp;#243;n&lt;/b&gt; en el cliente. Expirada la cookie de authenticaci&amp;#243;n el usuario deber&amp;#225; autenticarse nuevamente. El valor predeterminado es de 30 minutos, pero puede modificarse con el elemento system.web/&lt;b&gt;authentication&lt;/b&gt; en el &lt;b&gt;web.config&lt;/b&gt;:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;authentication mode=&amp;quot;Forms&amp;quot;&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;&lt;strong&gt;forms&lt;/strong&gt; loginUrl=&amp;quot;~/Security/Login.aspx&amp;quot; &lt;strong&gt;timeout=&amp;quot;60&amp;quot;&lt;/strong&gt; /&amp;gt;    &lt;br /&gt;&amp;lt;/authentication&amp;gt;&lt;/p&gt;  &lt;p&gt;Siempre complican estas cosas porque uno confunde la sesi&amp;#243;n con la autenticaci&amp;#243;n. Son dos cosas independientes. Uno puede crear un sitio basado en &lt;strong&gt;Forms Authentication&lt;/strong&gt; sin usar variables de &lt;b&gt;Session&lt;/b&gt;, o viceversa, o combinando ambos (lo m&amp;#225;s com&amp;#250;n).&lt;/p&gt;  &lt;p&gt;Normalmente, no hay problemas con los valores predeterminados de &lt;b&gt;session&lt;/b&gt; y &lt;b&gt;authentication&lt;/b&gt;, pero en aplicaciones donde el usuario puede pasarse bastante tiempo leyendo o escribiendo hasta finalmente presionar un link o bot&amp;#243;n, estos valores predeterminados pueden expirar y entonces necesitaremos aumentarlos.&lt;/p&gt;  &lt;p&gt;Finalmente, otro &lt;strong&gt;timeout&lt;/strong&gt; que a veces se quiere ajustar es el &lt;strong&gt;executionTimeout&lt;/strong&gt; del elemento &lt;strong&gt;HttpRuntine&lt;/strong&gt;. Este atributo define el tiempo m&amp;#225;ximo que puede durar la ejecuci&amp;#243;n de una solicitud. El valor predeterminado es 90 segundos, tiempo suficiente para la mayor&amp;#237;a de las aplicaciones. Sin embargo, existen escenarios donde se necesita un tiempo mayor, por ejemplo, para subir archivos de gran tama&amp;#241;o. En estos escenarios, seguramente tambi&amp;#233;n habr&amp;#225; que aumentar el atributo &lt;strong&gt;maxRequestLength&lt;/strong&gt;. Pueden leer m&amp;#225;s sobre el tema en &lt;a href="http://www.microsoft.com/spanish/msdn/articulos/archivo/270306/voices/UploadASP2.mspx"&gt;Carga de archivos ASP.NET&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Ahora que hay un poco m&amp;#225;s de luz en el asunto, pueden continuar investigando y profundizar m&amp;#225;s sobre estos temas.    &lt;br /&gt;Espero que sirva.&lt;/p&gt;  &lt;p&gt;Saludos, Gus.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-146487448518635276?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/146487448518635276/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=146487448518635276&amp;isPopup=true' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/146487448518635276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/146487448518635276'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/session-timeout-vs-formsauthentication.html' title='Session Timeout vs FormsAuthentication Timeout'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-7550527068245253532</id><published>2009-01-20T23:03:00.001-02:00</published><updated>2009-01-26T15:48:15.483-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Control Extensions</title><content type='html'>&lt;p&gt;Continuando con los mini-aportes sobre extensions methods, en esta oportunidad quiero compartir algunos que simplifican la carga de datos en controles de lista como &lt;strong&gt;DropDownList&lt;/strong&gt;, &lt;strong&gt;CheckBoxList&lt;/strong&gt; o &lt;strong&gt;RadioButtonList&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;El c&amp;#243;digo habitual para llenar una lista desplegable con datos obtenidos desde alg&amp;#250;n origen de datos es el siguiente:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;var countries = GlobalServices.GetCountries();&lt;br /&gt;CountryDropDownList.DataValueField = &lt;span class="str"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;; &lt;br /&gt;CountryDropDownList.DataTextField = &lt;span class="str"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;; &lt;br /&gt;CountryDropDownList.DataSource = countries; &lt;br /&gt;CountryDropDownList.DataBind();&lt;/pre&gt;&lt;p&gt;Habitualmente solemos agregar un item m&amp;#225;s al principio que diga, por ejemplo: (Seleccione). Entonces, al c&amp;#243;digo anterior podemos agregar:&lt;/p&gt;&lt;pre class="csharpcode"&gt;CountryDropDownList.Items.Insert(0, &lt;span class="kwrd"&gt;new&lt;/span&gt; ListItem(&lt;span class="str"&gt;&amp;quot;(Seleccione)&amp;quot;&lt;/span&gt;, String.Empty)); &lt;/pre&gt;&lt;p&gt;Si bien esto no es muy complejo, se vuelve tedioso cuando hay que repetirlo para llenar otras listas adicionales. Un simple extension method puede reducir todo esto a solo 1 l&amp;#237;nea de c&amp;#243;digo:&lt;/p&gt;&lt;pre class="csharpcode"&gt;CountryDropDownList.Fill(countries, &lt;span class="str"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;p&gt;Si quisieramos agregar el item adicional de (Seleccione), podr&amp;#237;amos usar una sobrecarga de este m&amp;#233;todo:&lt;/p&gt;&lt;pre class="csharpcode"&gt;CountryDropDownList.Fill(countries, &lt;span class="str"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;(Seleccione)&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;p&gt;El c&amp;#243;digo del extension method &lt;strong&gt;Fill&lt;/strong&gt;() es muy simple:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Fill(&lt;span class="kwrd"&gt;this&lt;/span&gt; ListControl list, &lt;span class="kwrd"&gt;object&lt;/span&gt; dataSource, &lt;span class="kwrd"&gt;string&lt;/span&gt; valueField, &lt;span class="kwrd"&gt;string&lt;/span&gt; textField) &lt;br /&gt;{ &lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (list == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;    list.DataValueField = valueField; &lt;br /&gt;    list.DataTextField = textField; &lt;br /&gt;    list.DataSource = dataSource; &lt;br /&gt;    list.DataBind(); &lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Como se puede observar, el extension method se aplica a los controles de tipo &lt;strong&gt;ListControl&lt;/strong&gt;, esto incluye, adem&amp;#225;s del control &lt;strong&gt;DropDownList&lt;/strong&gt;, los controles &lt;strong&gt;CheckBoxList&lt;/strong&gt;, &lt;strong&gt;RadioButtonList&lt;/strong&gt;, &lt;strong&gt;BulletedList&lt;/strong&gt;, y cualquier otro control que herede de &lt;strong&gt;ListControl&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Es un peque&amp;#241;o aporte que puede reducir, de una forma sencilla y elegante, una cantidad considerable de c&amp;#243;digo y el consecuente ahorro de tiempo.&lt;/p&gt;&lt;p&gt;Pueden descargar la clase ControlExtensions.cs con estos m&amp;#233;todos desde el siguiente link. M&amp;#225;s adelante intentar&amp;#233; agregar nuevos m&amp;#233;todos aplicables a otros controles. &lt;br /&gt;  &lt;br /&gt;Espero que sirva.&lt;/p&gt;&lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-22f4637e568decd8.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/ExtensionsMethods/ControlExtensions.zip" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-7550527068245253532?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/7550527068245253532/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=7550527068245253532&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7550527068245253532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7550527068245253532'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2009/01/control-extensions.html' title='Control Extensions'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-4630915921297150541</id><published>2008-12-15T23:15:00.001-02:00</published><updated>2008-12-17T10:15:55.348-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Propiedades y métodos públicos en la MasterPage</title><content type='html'>&lt;p&gt;Este truco ya es un poco viejo, sin embargo, a&amp;#250;n puede ser &amp;#250;til para muchos.&lt;/p&gt;  &lt;p&gt;En muchas situaciones deseamos exponer propiedades y m&amp;#233;todos p&amp;#250;blicos en la p&amp;#225;gina maestra o p&amp;#225;gina principal para accederlas desde las p&amp;#225;ginas de contenido. Sin embargo, al hacerlo vemos que no son accesibles. No aparecen en la lista de Intellisense.&lt;/p&gt;  &lt;p&gt;Existe una directiva poco conocida llamada &lt;strong&gt;MasterType&lt;/strong&gt; que podemos agregar f&amp;#225;cilmente en nuestras p&amp;#225;ginas de contenido y as&amp;#237; poder acceder a las propiedades y m&amp;#233;todos p&amp;#250;blicos definidos en nuestra p&amp;#225;gina maestra.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SUcBSd2JzPI/AAAAAAAAAIQ/JKbhI9FQwl8/s1600-h/image%5B7%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="118" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SUcBS0YMBiI/AAAAAAAAAIU/4LTZmJaCiFs/image_thumb%5B3%5D.png?imgmax=800" width="567" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Una vez definida esta directiva podemos acceder en el c&amp;#243;digo por detr&amp;#225;s de nuestras p&amp;#225;ginas de contenido, a las propiedades y m&amp;#233;todos p&amp;#250;blicos de la &lt;strong&gt;MasterPage&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SUcBTPHDJqI/AAAAAAAAAIY/xQpEf6Nxg_A/s1600-h/image%5B11%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="146" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SUcBTgOEYcI/AAAAAAAAAIc/J2vWda8TlJg/image_thumb%5B5%5D.png?imgmax=800" width="439" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Enjoy it!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-4630915921297150541?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/4630915921297150541/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=4630915921297150541&amp;isPopup=true' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4630915921297150541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/4630915921297150541'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/12/propiedades-y-mtodos-en-la-masterpage.html' title='Propiedades y métodos públicos en la MasterPage'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_apvGJDAiQ0E/SUcBS0YMBiI/AAAAAAAAAIU/4LTZmJaCiFs/s72-c/image_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1640598706083748093</id><published>2008-12-15T22:53:00.001-02:00</published><updated>2008-12-17T10:16:16.384-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>¿Cómo recuperar el objeto DataItem del control ListView?</title><content type='html'>&lt;p&gt;Cada elemento o fila de los controles de datos como &lt;em&gt;GridView&lt;/em&gt;, &lt;em&gt;DataList&lt;/em&gt; o &lt;em&gt;Repeater&lt;/em&gt; disponen de una propiedad &lt;strong&gt;DataItem&lt;/strong&gt; que permite recuperar el registro de datos enlazado a la lista. Esta propiedad es muy &amp;#250;til para procesar los elementos y controles durante el evento de enlace de datos. &lt;/p&gt;  &lt;p&gt;Sin embargo, al trabajar con el control &lt;strong&gt;ListView&lt;/strong&gt; inclu&amp;#237;do en ASP.NET 3.5 habr&amp;#225;n notado que no existe una propiedad similar o equivalente para recuperar los datos del &amp;#237;tem enlazado para procesarlos durante el evento &lt;strong&gt;ItemDataBound&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;Investigando un poco sobre c&amp;#243;mo resolver esta ausencia, encontr&amp;#233; una forma poco intuitiva:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SUb8jTBpMGI/AAAAAAAAAII/D-1IIzUahN0/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="181" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SUb8kC8dM9I/AAAAAAAAAIM/2LDL8gkXXYE/image_thumb%5B5%5D.png?imgmax=800" width="696" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;El truco es que el elemento &lt;strong&gt;e.Item&lt;/strong&gt; de tipo &lt;strong&gt;ListViewItem&lt;/strong&gt; se puede castear a &lt;strong&gt;ListViewDataItem&lt;/strong&gt; y entonces ah&amp;#237; podemos acceder a la propiedad &lt;strong&gt;DataItem&lt;/strong&gt; para luego castearlo nuevamente a la clase de datos que estamos enlazando.&lt;/p&gt;  &lt;p&gt;Este doble casting no me agrada mucho, pero es la &amp;#250;nica forma que encontr&amp;#233; para recuperar el elemento de datos que est&amp;#225; siendo enlazado al control ListView.&lt;/p&gt;  &lt;p&gt;Bueno, espero que sirva y ahorre algunos dolores de cabeza.&lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1640598706083748093?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1640598706083748093/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1640598706083748093&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1640598706083748093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1640598706083748093'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/12/cmo-recuperar-el-objeto-dataitem-del.html' title='¿Cómo recuperar el objeto DataItem del control ListView?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_apvGJDAiQ0E/SUb8kC8dM9I/AAAAAAAAAIM/2LDL8gkXXYE/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-6535339600663351552</id><published>2008-11-30T19:58:00.001-02:00</published><updated>2008-11-30T21:40:05.178-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>String Extensions</title><content type='html'>&lt;p&gt;Como sabemos, los &lt;strong&gt;Extensions Methods&lt;/strong&gt; son una de las nuevas caracter&amp;#237;sticas de C# 3.0. Podemos verlos como m&amp;#233;todos est&amp;#225;ticos que permiten agregar nuevas funcionalidades a clases ya existentes. No es mi intenci&amp;#243;n explicar c&amp;#243;mo crear Extensions Methods (pueden aprender m&amp;#225;s &lt;a href="http://msdn.microsoft.com/es-es/library/bb383977.aspx" target="_blank"&gt;aqu&amp;#237;&lt;/a&gt; y &lt;a href="http://www.koalab.es/blog/extension-methods-en-c-30-y-su-aplicacion-practica.html" target="_blank"&gt;aqu&amp;#237;&lt;/a&gt;), sino compartir varios extensions methods que uso habitualmente en mis proyectos de desarrollo. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Convirtiendo Strings&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Convertir cadenas de texto a un n&amp;#250;mero o fecha es una necesidad habitual en todos los proyectos. El c&amp;#243;digo t&amp;#237;pico es el siguiente:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int number = &lt;strong&gt;int.Parse&lt;/strong&gt;(NumberTextBox.Text);       &lt;br /&gt;DateTime date = &lt;strong&gt;DateTime.Parse&lt;/strong&gt;(DateTextBox.Text); &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;El mismo resultado podr&amp;#237;amos obtener usando la clase &lt;strong&gt;Convert&lt;/strong&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int number = &lt;strong&gt;Convert.ToInt32&lt;/strong&gt;(NumberTextBox.Text);       &lt;br /&gt;DateTime date = &lt;strong&gt;Convert.ToDateTime&lt;/strong&gt;(DateTextBox.Text); &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;En este caso tenemos la ventaja de que &lt;strong&gt;si el argumento es null&lt;/strong&gt;, &lt;strong&gt;el valor devuelto es cero&lt;/strong&gt;. Esto puede comprobarse con &lt;a href="http://reflector.red-gate.com/"&gt;Reflector&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/STMQH0LSqoI/AAAAAAAAAHg/eWec0E026HE/image%5B25%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="165" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/STMMZIPcEII/AAAAAAAAAHk/eCT2SMUl7t8/image_thumb%5B13%5D.png" width="312" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ninguno de los m&amp;#233;todos anteriores resuelve el problema de conversi&amp;#243;n de datos cuando el usuario ingresa letras donde se esperaba n&amp;#250;meros o fechas con formatos no v&amp;#225;lidos.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/STMQIqtijyI/AAAAAAAAAHo/WaPXqAnGXx8/image%5B31%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="270" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/STMQJ3eOUDI/AAAAAAAAAHs/3dkQ8LVJg-o/image_thumb%5B17%5D.png" width="515" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Para evitar esta situaci&amp;#243;n podemos usar validators de ASP.NET, controles de m&amp;#225;scara o bien el m&amp;#233;todo &lt;strong&gt;TryParse&lt;/strong&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int number;      &lt;br /&gt;if (int.&lt;strong&gt;TryParse&lt;/strong&gt;(NumberTextBox.Text, out number))       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; //TODO: Do something       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;El &amp;#250;nico problema con esta soluci&amp;#243;n es que implica escribir mucho m&amp;#225;s c&amp;#243;digo, generando rutinas m&amp;#225;s extensas y dif&amp;#237;ciles de leer.&lt;/p&gt;  &lt;p&gt;La situaci&amp;#243;n se complica un poco m&amp;#225;s con los &lt;strong&gt;Guid&lt;/strong&gt;, pues no disponen de un m&amp;#233;todo TryParse, entonces habr&amp;#237;a que usar &lt;strong&gt;Try/Catch&lt;/strong&gt;, lo que complica a&amp;#250;n m&amp;#225;s el c&amp;#243;digo resultante.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;String Extensions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Es aqu&amp;#237; donde los Extensions M&amp;#233;todos pueden proporcionar una soluci&amp;#243;n efectiva, elegante e intuitiva. La siguiente figura muestra c&amp;#243;mo convertir una cadena a un n&amp;#250;mero usando un extension method:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/STMMbeXXq5I/AAAAAAAAAHw/upHYJK7XYuw/image%5B32%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="277" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/STMMcCz4ufI/AAAAAAAAAH0/RQDsBEKXSq8/image_thumb%5B18%5D.png" width="700" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;La implementaci&amp;#243;n del extension method es muy simple:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/STMMcgSd6OI/AAAAAAAAAH4/p_CxbEjd6kk/image%5B39%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="138" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/STMMdGSYNqI/AAAAAAAAAH8/fUuMqYT3nms/image_thumb%5B25%5D.png" width="353" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;He creado una clase &lt;strong&gt;StringExtensions.cs&lt;/strong&gt; con varios extensions methods para convertir a byte, short, long, float, double, decimal, boolean, datetime, guid, etc. Inclu&amp;#237; tambi&amp;#233;n versiones compatibles con tipos nullables. Seguir&amp;#233; agregando nuevos m&amp;#233;todos en la medida que encuentre aplicaci&amp;#243;n pr&amp;#225;ctica y aporten simplicidad en el c&amp;#243;digo.&lt;/p&gt;  &lt;p&gt;A continuaci&amp;#243;n les dejo el link para descargar la clase &lt;strong&gt;StringExtensions.cs&lt;/strong&gt;. En pr&amp;#243;ximos post, publicar&amp;#233; otros extensions methods aplicables a controles de ASP.NET. Espero que sirva.&lt;/p&gt; &lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-22f4637e568decd8.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/ExtensionsMethods/StringExtensions.zip" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-6535339600663351552?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/6535339600663351552/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=6535339600663351552&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6535339600663351552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/6535339600663351552'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/11/extensions-methods.html' title='String Extensions'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_apvGJDAiQ0E/STMMZIPcEII/AAAAAAAAAHk/eCT2SMUl7t8/s72-c/image_thumb%5B13%5D.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8640112454410041519</id><published>2008-11-27T16:48:00.001-02:00</published><updated>2008-11-27T17:22:56.919-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Nuevo control de Chart en ASP.NET</title><content type='html'>&lt;p&gt;La gente de Microsoft ha liberado un nuevo control para ASP.NET 3.5 SP1 y Windows Forms para resolver nuestras necesidades de charting. Thanks!!!&lt;/p&gt;  &lt;p&gt;Pueden leer el &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx"&gt;art&amp;#237;culo de Scott Guthrie&lt;/a&gt; (en ingl&amp;#233;s) dando la noticia o si lo prefieren pueden leer la &lt;a href="http://thinkingindotnet.wordpress.com/2008/11/27/nuevo-control-de-aspnet/"&gt;traducci&amp;#243;n en espa&amp;#241;ol&lt;/a&gt; de &lt;strong&gt;Juan Mar&amp;#237;a La&amp;#243; Ramos&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Pueden arrancar con los siguientes links:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c&amp;amp;DisplayLang=en"&gt;Descargar los controles.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=1D69CE13-E1E5-4315-825C-F14D33A303E9&amp;amp;displaylang=en"&gt;Descargar el soporte para VS 2008 para estos controles.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=1591"&gt;Descargar los ejemplos.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=EE8F6F35-B087-4324-9DBA-6DD5E844FD9F&amp;amp;displaylang=en"&gt;Descargar la documentaci&amp;#243;n.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/MSWinWebChart/threads/"&gt;Visitar el foro.&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Finalmente pueden descargar los recursos en espa&amp;#241;ol para estos controles: &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=es&amp;amp;FamilyID=581ff4e3-749f-4454-a5e3-de4c463143bd"&gt;Paquete de idioma de Microsoft Chart Control para Microsoft .NET Framework 3.5&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Y aqu&amp;#237; les dejo unos screenshots de los ejemplos. Se ven muy bien!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SS7rbWomVTI/AAAAAAAAAGc/GfGCw189T5k/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="169" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/SS7rcP96rbI/AAAAAAAAAGg/nNDbH8qWbWI/image_thumb%5B1%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/SS7reJ6lbAI/AAAAAAAAAGk/6J13DNN9AcM/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="215" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SS7re_gJCNI/AAAAAAAAAGo/YMciOo1MY0k/image_thumb%5B2%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SS7ricuj8rI/AAAAAAAAAGs/o3rCZQ0MROc/s1600-h/image%5B11%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="224" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SS7rjRxb3TI/AAAAAAAAAGw/Z3ci8wbWmlo/image_thumb%5B3%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SS7zjLNiMwI/AAAAAAAAAG0/szcYPpt5E_8/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="53" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SS7zj77mbQI/AAAAAAAAAG4/VE7uoGkOfX4/image_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Saludos, Gus&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8640112454410041519?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8640112454410041519/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8640112454410041519&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8640112454410041519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8640112454410041519'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/11/nuevo-control-de-chart-en-aspnet.html' title='Nuevo control de Chart en ASP.NET'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_apvGJDAiQ0E/SS7rcP96rbI/AAAAAAAAAGg/nNDbH8qWbWI/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1136073874549125340</id><published>2008-11-20T13:25:00.001-02:00</published><updated>2008-11-27T16:51:51.701-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Live'/><title type='text'>Descubriendo Live Mesh</title><content type='html'>&lt;p&gt;Como comentaba en un post anterior, &lt;strong&gt;Live Mesh&lt;/strong&gt; es una de las aplicaciones de Microsoft que, basado en los servicios de &lt;strong&gt;&lt;a href="http://dev.live.com/liveframework/"&gt;Live Framework&lt;/a&gt;&lt;/strong&gt;, permite en principio una sincronizaci&amp;#243;n de archivos simple, segura y transparente entre m&amp;#250;ltiples dispositivos. Desde computadoras personales, port&amp;#225;tiles y dispositivos m&amp;#243;viles a c&amp;#225;maras digitales e impresoras, entre otras. Pero Mesh es mucho m&amp;#225;s que sincronizaci&amp;#243;n de datos e ir&amp;#233; comentando m&amp;#225;s en la medida que vaya probando y descubriendo sus bondades.&lt;/p&gt;  &lt;p&gt;Por el momento estoy empezando a usar las &lt;strong&gt;capacidades de sincronizaci&amp;#243;n de archivos&lt;/strong&gt; de Mesh con amigos y compa&amp;#241;eros de proyecto y realmente es muy &amp;#250;til, si bien hoy no es una herramienta de control de versiones con capacidades de merge, etc., la simple posibilidad de tener archivos y carpetas distribuidos y sincronizados entre diferentes dispositivos ya tiene un gran valor.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Instalando Live Mesh&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;El primer paso consiste en ingresar al sitio &lt;a title="https://www.mesh.com" href="https://www.mesh.com"&gt;https://www.mesh.com&lt;/a&gt; y conectarse a &lt;strong&gt;Live Mesh&lt;/strong&gt; usando alguna cuenta de &lt;strong&gt;Live ID&lt;/strong&gt; (por ejemplo una cuenta de Hotmail). &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWA8BAN_oI/AAAAAAAAAEs/YQNJ2gXTR4Y/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="118" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWA86T2wbI/AAAAAAAAAEw/MX4oD670SKk/image_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Esto significa que no necesito registrarme, completar formularios, etc. Simplemente utilizo mi cuenta de Live ID para Live Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWA9mk1yyI/AAAAAAAAAE0/JXBRt21DPOw/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWA-Gb1RKI/AAAAAAAAAE4/1XqkuiU_zAI/image_thumb%5B2%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Despu&amp;#233;s del login en Windows Live, ver&amp;#233; la p&amp;#225;gina de dispositivos de Mesh. Desde aqu&amp;#237; podr&amp;#233; agregar mis dispositivos a Mesh. De forma predeterminada, ya existe un &lt;strong&gt;Live Desktop&lt;/strong&gt; listo para usar. Se trata de un escritorio virtual online, donde podr&amp;#233; acceder y administrar mis archivos y carpetas disponibles a trav&amp;#233;s de Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWA_nLzSeI/AAAAAAAAAE8/t09gCw1WwZc/s1600-h/image%5B23%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="189" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBAUoIHxI/AAAAAAAAAFA/tDys9QokBHE/image_thumb%5B7%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Para agregar mi equipo a Mesh, selecciono &lt;strong&gt;Add device&lt;/strong&gt;, y podr&amp;#233; descargar e instalar el cliente de Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWBBWaaDqI/AAAAAAAAAFE/O7DemzOfk5Q/s1600-h/image%5B20%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="142" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SSWBB5irQiI/AAAAAAAAAFI/vK2z1gnksR8/image_thumb%5B6%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;El cliente de Mesh est&amp;#225; disponible para Windows XP y Windows Vista; existe una versi&amp;#243;n para Mac y, si bien en la p&amp;#225;gina oficial no encontr&amp;#233; referencias, me enter&amp;#233; que ya existe una versi&amp;#243;n para &lt;strong&gt;Windows Mobile&lt;/strong&gt; que pueden descargarla desde &lt;a title="https://m.mesh.com" href="https://m.mesh.com"&gt;https://m.mesh.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Continuando con la instalaci&amp;#243;n, debemos seleccionar la plataforma correcta y al presionar el bot&amp;#243;n &lt;strong&gt;Install&lt;/strong&gt;, iniciaremos la descarga de LiveMesh.exe. Su instalaci&amp;#243;n no tiene inconvenientes y dura unos 3 a 5 minutos.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBCYR4V1I/AAAAAAAAAFM/RmkROvuifwA/s1600-h/image%5B17%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="145" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBCwq2ORI/AAAAAAAAAFQ/rKFec7vMarE/image_thumb%5B5%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Finalizada la instalaci&amp;#243;n encontraremos en el &amp;#225;rea de notificaciones el icono de Mesh y deberemos iniciar una sesi&amp;#243;n con nuestra cuenta Live ID para agregar nuestro dispositivo a la red.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBDRyAQEI/AAAAAAAAAFU/p6OW0zxX-xk/s1600-h/image%5B26%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="144" alt="image" src="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBDzp6nMI/AAAAAAAAAFY/bUfVNX23_Sw/image_thumb%5B8%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;El siguiente paso es darle un nombre a nuestro equipo para conectarlo a la red de Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWBED87NNI/AAAAAAAAAFc/9633cAtiwcQ/s1600-h/image%5B29%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="180" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SSWBE-OXsYI/AAAAAAAAAFg/wRIPYat6AHE/image_thumb%5B9%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;En pocos segundos tendremos nuestro equipo conectado a Mesh y podremos verlo junto a los dem&amp;#225;s equipos y dispositivos. En este caso solo encuentro mi equipo portatil y el Live Desktop.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBF-oe8QI/AAAAAAAAAFk/7AxcauRjavQ/s1600-h/image%5B32%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBGUgXjeI/AAAAAAAAAFo/msQoRrRKY8A/image_thumb%5B10%5D.png?imgmax=800" width="163" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Y si volvemos a la p&amp;#225;gina de dispositivos de Mesh en la web (&lt;a title="https://www.mesh.com/Web/Devices.aspx" href="https://www.mesh.com/Web/Devices.aspx"&gt;https://www.mesh.com/Web/Devices.aspx&lt;/a&gt;), veremos nuestro dispositivo agregado al anillo de Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBHlsS_2I/AAAAAAAAAFs/L3_sayKBMrg/s1600-h/image%5B35%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="186" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBIVnr4JI/AAAAAAAAAFw/kV6GRJvnBjM/image_thumb%5B11%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Compartiendo archivos y carpetas&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ahora quiero crear una carpeta y compartirla entre mis equipos de Mesh. Para lograr esto podr&amp;#237;a crear una carpeta en Live Desktop y luego sincronizarla con mi equipo portatil y viceversa.&lt;/p&gt;  &lt;p&gt;A modo de ejemplo, voy a crear una carpeta &lt;strong&gt;Test&lt;/strong&gt; en mi escritorio local y agregarla a Live Mesh.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_apvGJDAiQ0E/SSWBJeFwTBI/AAAAAAAAAF0/vuy-jVR-Ztk/s1600-h/image%5B41%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="211" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBKSY_fLI/AAAAAAAAAF4/ZpV_CfMxhg0/image_thumb%5B13%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Como se muestra en la imagen es muy simple, gracias a la integraci&amp;#243;n de &lt;strong&gt;Live Mesh&lt;/strong&gt; con el Escritorio, Mi PC, el Explorador de Windows, etc.&lt;/p&gt;  &lt;p&gt;Al seleccionar Add folder to Live Mesh veremos una ventana de di&amp;#225;logo donde podremos indicar el nombre de la carpeta a compartir y cuando debe sincronizarse con los dem&amp;#225;s dispositivos. Presionamos Ok y listo!.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_apvGJDAiQ0E/SSWBKqiIytI/AAAAAAAAAF8/b2fvuOojsAk/s1600-h/image%5B44%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="225" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SSWBLJAasTI/AAAAAAAAAGA/fsqFD6kWBFY/image_thumb%5B14%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ahora nuestra carpeta &lt;strong&gt;Live Mesh&lt;/strong&gt; cambi&amp;#243; a un color azulado y ya tenemos disponible la misma carpeta en el &lt;strong&gt;Live Desktop&lt;/strong&gt; (y otros dispositivos conectados). Observen tambi&amp;#233;n que &lt;strong&gt;el sitio de Mesh usa un protocolo HTTPS que nos proporciona seguridad de encriptaci&amp;#243;n de datos en la transferencia de nuestros bytes&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWBNPX3-jI/AAAAAAAAAGE/Ekgnn4G4Rxc/s1600-h/image%5B47%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="221" alt="image" src="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBOC9oCLI/AAAAAAAAAGI/InkGH4QpYZI/image_thumb%5B15%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Para terminar las pruebas, abrimos la carpeta &lt;strong&gt;Test&lt;/strong&gt; de nuestro equipo local y creamos un simple archivo de texto &lt;strong&gt;Prueba.txt&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWBPcCukwI/AAAAAAAAAGM/GUMmMDwtnBM/s1600-h/image%5B50%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="158" alt="image" src="http://lh4.ggpht.com/_apvGJDAiQ0E/SSWBQNIaErI/AAAAAAAAAGQ/4gsnG7tVlXA/image_thumb%5B16%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Esperamos unos segundos y listo! Este archivo &lt;strong&gt;Prueba.txt&lt;/strong&gt; ahora tambi&amp;#233;n esta replicado en nuestro &lt;strong&gt;Live Desktop&lt;/strong&gt; (y otros dispositivos, si existiesen). Podemos verificarlo ingresando a nuestro &lt;strong&gt;Live Desktop&lt;/strong&gt;, haciendo doble clic en la carpeta &lt;strong&gt;Test&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_apvGJDAiQ0E/SSWBSSU3ZtI/AAAAAAAAAGU/mBxCcho6rlY/s1600-h/image%5B53%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="image" src="http://lh5.ggpht.com/_apvGJDAiQ0E/SSWBS46wy7I/AAAAAAAAAGY/_GPahxbFToc/image_thumb%5B17%5D.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conclusiones&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Es muy simple el uso de &lt;strong&gt;Live Mesh&lt;/strong&gt; para compartir y sincronizar archivos y carpetas entre diferentes equipos y dispositivos. Su &lt;strong&gt;integraci&amp;#243;n con el Shell de Windows&lt;/strong&gt; lo hace muy amigable. Adem&amp;#225;s podemos invitar a amigos y colaboradores para compartir archivos o documentos de trabajo y mantenernos sincronizados. Basta de diferentes versiones de archivo en diferentes lugares, tendremos &lt;strong&gt;una sola versi&amp;#243;n en todos los lugares&lt;/strong&gt; que necesitemos.&lt;/p&gt;  &lt;p&gt;En futuros post comentar&amp;#233; mi experiencia con Remote Desktop de Live Mesh.    &lt;br /&gt;Hasta la pr&amp;#243;xima!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1136073874549125340?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1136073874549125340/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1136073874549125340&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1136073874549125340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1136073874549125340'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/11/descubriendo-live-mesh.html' title='Descubriendo Live Mesh'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_apvGJDAiQ0E/SSWA86T2wbI/AAAAAAAAAEw/MX4oD670SKk/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-2924040888660546990</id><published>2008-11-19T09:20:00.001-02:00</published><updated>2008-11-19T10:29:21.996-02:00</updated><title type='text'>PDC 2008 Buenos Aires</title><content type='html'>&lt;p&gt;&lt;img src="http://www.microsoftpdc.com/Images/Themes/Hero/PDC_logo.png" /&gt; &lt;/p&gt;  &lt;p&gt;Ayer martes 18 de Noviembre tuve la oportunidad de asistir a este importante evento realizado aqu&amp;#237; en Buenos Aires. El evento inici&amp;#243; con unas keynotes de la mano de &lt;a href="http://blogs.msdn.com/masaez/"&gt;Miguel Saez&lt;/a&gt;, &lt;a href="http://eglinsky.spaces.live.com/"&gt;Ezequiel Glinsky&lt;/a&gt;, &lt;a href="http://jladetto.spaces.live.com/"&gt;Juan Ladetto&lt;/a&gt; y &lt;a href="http://blogs.technet.com/ponicke/"&gt;Alejandro Ponicke&lt;/a&gt; que nos comentaron un poco sobre el PDC 2008 de Los Angeles, realizado hace apenas 2 semanas, y lo que se viene: &lt;a href="http://www.microsoft.com/azure/"&gt;Windows Azure&lt;/a&gt;, Cloud Computing, &lt;a href="http://www.microsoft.com/windows/windows-7/"&gt;Windows 7&lt;/a&gt;, etc.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://jladetto.spaces.live.com/"&gt;Juan&lt;/a&gt; y &lt;a href="http://blogs.msdn.com/masaez/"&gt;Miguel&lt;/a&gt;, como ya nos tienen acostumbrados, en una excelente presentaci&amp;#243;n en tiempo y forma, nos mostraron algunas bondades muy interesantes y &amp;#250;tiles de &lt;a href="https://www.mesh.com/"&gt;Live Mesh&lt;/a&gt;. En siguientes posts comentar&amp;#233; mis experiencias con estas aplicaciones, su API, etc.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://eglinsky.spaces.live.com/"&gt;Ezequiel&lt;/a&gt; nos mostr&amp;#243; unas fotos de los impresionantes DataCenters de Microsoft, particularmente el DataCenter de Quincy. Con inversiones de miles de millones Microsoft demuestra su fuerte apuesta en el futuro de los servicios basados en la nube.&lt;/p&gt;  &lt;p&gt;Finalmente, &lt;a href="http://blogs.technet.com/ponicke/"&gt;Alejandro&lt;/a&gt; nos di&amp;#243; un preview de &lt;a href="http://www.microsoft.com/windows/windows-7/"&gt;Windows 7&lt;/a&gt;, si bien no fue una presentaci&amp;#243;n en profundidad, destac&amp;#243; algunas caracter&amp;#237;sticas interesantes como una TaskBar mucho m&amp;#225;s rica, desde donde podemos lanzar aplicaciones, acceder a documentos recientes, alternar aplicaciones en ejecuci&amp;#243;n e incluso interactuar con las aplicaciones en runtime directamente desde la taskbar.&lt;/p&gt;  &lt;p&gt;Luego de las 2 horas que duraron las keynotes tuvimos un break de 30 minutos donde aprovechamos unos caf&amp;#233;s con ricas medialunas.&lt;/p&gt;  &lt;p&gt;Las siguientes charlas se dividieron en 3 salas: una sala dedicada a &lt;strong&gt;Servicios en la nube&lt;/strong&gt;, otra donde hablaron de &lt;strong&gt;Aplicaciones Clientes y Presentaci&amp;#243;n&lt;/strong&gt; (WPF, Silverlight, ASP.NET 4.0) y en la tercer sala se dedicaron a &lt;strong&gt;Herramientas, Lenguajes y Framework&lt;/strong&gt; (F#, C#, Oslo, VS2010, etc.). Todas las charlas eran muy interesantes, pero hab&amp;#237;a que decidir cual asistir. Mi amigo Mariano Noguera y yo nos inclinamos por la nube.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Servicios en la nube&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Arrancamos con un recorrido por &lt;a href="http://www.microsoft.com/azure/"&gt;Cloud Services&lt;/a&gt; de la mano de &lt;a href="http://jladetto.spaces.live.com/"&gt;Juan Ladetto&lt;/a&gt;, donde empezamos a ver un poco m&amp;#225;s de qu&amp;#233; se trata Windows Azure. En nuevos posts intentar&amp;#233; hablar sobre lo que vaya conociendo de esta nueva plataforma que se perfila como una excelente y novedosa alternativa para hostear nuestras aplicaciones.&lt;/p&gt;  &lt;p&gt;A continuaci&amp;#243;n, con &lt;a href="http://blogs.southworks.net/mwoloski/"&gt;Mat&amp;#237;as Woloski&lt;/a&gt; y &lt;a href="http://blogs.southworks.net/erossetto/"&gt;Edgardo Rosetto&lt;/a&gt;, desplegamos un servicio en la nube. La experiencia fue muy simple. Creamos una t&amp;#237;pica aplicaci&amp;#243;n Hola Mundo en ASP.NET y lo desplegamos en &lt;a href="http://www.microsoft.com/azure/"&gt;Windows Azure&lt;/a&gt;, todo lo que hicimos fue seguir un asistente web que nos permiti&amp;#243; hostear la aplicaci&amp;#243;n, primeramente en un estado de &lt;strong&gt;Stagging&lt;/strong&gt; para luego pasarla a &lt;strong&gt;Production&lt;/strong&gt;. Si bien la aplicaci&amp;#243;n hac&amp;#237;a exactamente nada, lo interesante fue ver c&amp;#243;mo ponerla en la nube y ver c&amp;#243;mo esta aplicaci&amp;#243;n puede escalar a voluntad en tiempo record simplemente cambiando valores en configuraci&amp;#243;n. Este es un punto sin precedentes que permitir&amp;#237;a que una aplicaci&amp;#243;n pueda escalar horizontalmente en cuesti&amp;#243;n de segundos.&lt;/p&gt;  &lt;p&gt;Nuevamente, &lt;a href="http://blogs.msdn.com/masaez/"&gt;Miguel Saez&lt;/a&gt; nos di&amp;#243; un paseo m&amp;#225;s program&amp;#225;tico sobre &lt;strong&gt;&lt;a href="http://dev.live.com/liveframework/"&gt;Live Framework&lt;/a&gt;&lt;/strong&gt;&amp;#160; y &lt;strong&gt;&lt;a href="https://www.mesh.com/"&gt;Mesh Services&lt;/a&gt;&lt;/strong&gt;. Obviando los aspectos te&amp;#243;ricos, Miguel nos mostr&amp;#243; a trav&amp;#233;s de una aplicaci&amp;#243;n WPF, como interactuar con la API de &lt;a href="https://www.mesh.com/"&gt;Live Mesh&lt;/a&gt; y Live Contact. La verdad que es una API muy simple e interesante que m&amp;#225;s de uno puede encontrarle usos pr&amp;#225;cticos en las aplicaciones del mundo real. Podr&amp;#225;n encontrar ppts y ejemplos en su &lt;a href="http://blogs.msdn.com/masaez/"&gt;blog&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Para terminar, y ya un poco agotados con esta marat&amp;#243;n de charlas y novedades, &lt;strong&gt;Nicol&amp;#225;s&lt;/strong&gt; y &lt;strong&gt;Maximiliano&lt;/strong&gt; de &lt;a href="http://www.huddle.com.ar/"&gt;Huddle Group&lt;/a&gt; nos dieron una muy prolija y perfectamente sincronizada presentaci&amp;#243;n de &lt;strong&gt;SQL Data Services&lt;/strong&gt;. Nos mostraron el actual estado del arte, vimos un par de aplicaciones Windows y Web haciendo uso de las APIs, posibilidades y limitaciones actuales, y la intenci&amp;#243;n de MS de llevar toda la potencia de SQL Server en la nube. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fin del PDC&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Pasadas las 22hs, terminaron las charlas y luego de un agradecimento de la gente de MS, se hizo un r&amp;#225;pido sorteo de Libros, MS Mouses y algunas gorritas MSDN. No tuve la suerte de llevarme ning&amp;#250;n libro, y hab&amp;#237;a varios interesantes (Silverlight 2, Application = Markup + Code, ASp.NET 3.5, etc.), as&amp;#237; que tuve que conformarme con la pulsera de la registraci&amp;#243;n :-(&lt;/p&gt;  &lt;p&gt;La verdad fue una jornada muy enriquecedora que mostr&amp;#243; a las claras la intenci&amp;#243;n de MS de posicionarse fuertemente en el negocio del Cloud Computing, las plataformas y herramientas que ofrecer&amp;#225; y c&amp;#243;mo nosotros podemos beneficiarnos de estas nuevas plataformas que se hablan hoy y reinar&amp;#225;n en los pr&amp;#243;ximos 5 a 10 a&amp;#241;os.&lt;/p&gt;  &lt;p&gt;Bueno, seguir&amp;#233; comentando sobre estas nuevas plataformas y tecnolog&amp;#237;as en futuros posts.    &lt;br /&gt;Byes!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-2924040888660546990?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/2924040888660546990/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=2924040888660546990&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2924040888660546990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/2924040888660546990'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/11/pdc-2008-buenos-aires.html' title='PDC 2008 Buenos Aires'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-7762996678208059855</id><published>2008-01-22T10:50:00.000-02:00</published><updated>2008-12-11T10:15:18.979-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OOXML'/><title type='text'>Libro de OpenXML</title><content type='html'>&lt;a href="http://blogs.code-counsel.net/Wouter/default.aspx"&gt;&lt;strong&gt;Wouter Van Vugt&lt;/strong&gt; &lt;/a&gt;ha escrito el primer libro sobre &lt;strong&gt;OpenXML&lt;/strong&gt; "&lt;em&gt;Open XML Explained&lt;/em&gt;". En este libro de 128 páginas cubre los aspectos básicos del desarrollo con OpenXML. El autor es un especialista en los formatos de &lt;a href="http://gustavoazcona.blogspot.com/2008/01/por-qu-office-open-xml.html"&gt;OpenXML&lt;/a&gt;, podrán ver su participación en los foros de &lt;a href="http://www.openxmldeveloper.org/"&gt;OpenXmlDeveloper.org&lt;/a&gt; y en su &lt;a href="http://blogs.code-counsel.net/Wouter/default.aspx"&gt;blog &lt;/a&gt;encontrarán algunos posts sobre OpenXML y otras tecnologías de .Net Framework.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_apvGJDAiQ0E/R5XqGCvvbaI/AAAAAAAAAB0/IBhmEG3qHOU/s1600-h/OpenXMLExplained.JPG"&gt;&lt;/a&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://www.hirethings.co.nz/photo/image/978/large/openxml.png" border="0" /&gt;&lt;br /&gt;Podrán descargar el libro en formato PDF desde &lt;a href="http://openxmldeveloper.org/attachment/1970.ashx"&gt;aquí&lt;/a&gt;.&lt;br /&gt;Y podrán acceder a un versión en formato docx desde &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6f264d0b-23e8-43fe-9f82-9ab627e5eaa3&amp;amp;displaylang=en"&gt;aquí&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-7762996678208059855?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/7762996678208059855/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=7762996678208059855&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7762996678208059855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/7762996678208059855'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/01/libro-de-openxml.html' title='Libro de OpenXML'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8649406921392673275</id><published>2008-01-22T10:29:00.000-02:00</published><updated>2008-01-22T11:09:00.084-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Limpiar los items recientes en Visual Studio 2005</title><content type='html'>No es una novedad, pero muchos me han preguntado si conocía una forma fácil de eliminar las entradas de los proyectos recientes en Visual Studio 2005, sin tener que editar/borrar manualmente entradas en el registro de Windows. Googleando un poco encontré una respuesta: &lt;strong&gt;&lt;a href="http://www.csharper.net/blog/mru_cleaner_v1_0_0_5___now_serving_your_file_cleaning_needs.aspx"&gt;MRU Cleaner&lt;/a&gt;&lt;/strong&gt;.&lt;br /&gt;Se trata de un add-in para borrar las entradas de los proyectos recientes en Visual Studio 2005, y no solo de los proyectos, sino también la lista de archivos recientes. La siguiente imagen muestra su uso:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csharper.net/resources/blog_media/mru_cleaner_screen.gif"&gt;&lt;img style="WIDTH: 400px; CURSOR: hand" alt="" src="http://www.csharper.net/resources/blog_media/mru_cleaner_screen.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lo he probado y funciona muy bien. Pueden descargar una versión de este complemento para Visual Studio 2005 &lt;a href="http://www.csharper.net/download.aspx?f=MRUCleanerSetup.exe"&gt;aquí&lt;/a&gt;. Y pueden obtener una versión beta para &lt;strong&gt;Orcas&lt;/strong&gt; &lt;a href="http://www.csharper.net/blog/mru_cleaner_v1_0_0_5___now_serving_your_file_cleaning_needs.aspx#mru_cleaner_for_orcas_beta_1.aspx"&gt;aquí&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8649406921392673275?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8649406921392673275/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8649406921392673275&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8649406921392673275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8649406921392673275'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/01/limpiar-los-items-recientes-en-visual.html' title='Limpiar los items recientes en Visual Studio 2005'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-5918725435682451398</id><published>2008-01-16T13:02:00.000-02:00</published><updated>2008-12-11T10:14:13.703-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OOXML'/><title type='text'>Los documentos WordprocessingML</title><content type='html'>Ya hemos visto &lt;a href="http://gustavoazcona.blogspot.com/2008/01/por-qu-office-open-xml.html"&gt;qué es y por qué nos interesaría usar OOXML&lt;/a&gt;, y presentamos sus &lt;a href="http://gustavoazcona.blogspot.com/2008/01/conociendo-office-open-xml.html"&gt;componentes principales y tecnologías asociadas&lt;/a&gt;. Ahora vamos a explorar uno de sus tres lenguajes de marcas principales: &lt;strong&gt;WordprocessingML&lt;/strong&gt;. Veremos su estructura, sus partes, elementos y relaciones; y cómo se almacena un documento de &lt;em&gt;WordprocessingML&lt;/em&gt; dentro del contenedor.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Partes de un documento WordprocessingML&lt;br /&gt;&lt;/strong&gt;Como ya hemos dicho, un documento &lt;em&gt;WordprocessingML&lt;/em&gt; tiene muchas partes relacionadas que se almacenan dentro de un contenedor. Actualmente se utiliza el formato ZIP para empaquetar y contener un documento &lt;em&gt;WordprocessingML&lt;/em&gt;. Si renombramos un documento .docx a .zip podremos descomprimirlo y explorar internamente cada una de las partes del documento.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp0.blogger.com/_apvGJDAiQ0E/R44evSvvbSI/AAAAAAAAAAs/Mwc_1ydgKx4/s1600-h/WordprocessingML_Zip.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156092421220560162" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_apvGJDAiQ0E/R44evSvvbSI/AAAAAAAAAAs/Mwc_1ydgKx4/s400/WordprocessingML_Zip.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 1: Estructura de un documento WordprocessingML&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Ests estructura es definida por la especificación &lt;strong&gt;Open Packaging Conventions&lt;/strong&gt; del formato OOXML. Como se muestra en la figura, el archivo.zip contiene una estructura de carpetas y archivos XML que forman las partes del documento. El contenido principal del documento se almacena en el archivo &lt;strong&gt;document.xml&lt;/strong&gt; de la carpeta &lt;strong&gt;word&lt;/strong&gt; y los demás archivos .xml (&lt;em&gt;fontTable.xml, settings.xml, styles.xml, webSettings.xml&lt;/em&gt;) contienen información de estilos, fuentes, configuración, etc. El siguiente gráfico muestra un esquema de documento WordprocessingML y sus partes relacionadas:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp0.blogger.com/_apvGJDAiQ0E/R44e8SvvbTI/AAAAAAAAAA0/xkgBAQuw1QM/s1600-h/WordprocessingML_Parts.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156092644558859570" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_apvGJDAiQ0E/R44e8SvvbTI/AAAAAAAAAA0/xkgBAQuw1QM/s400/WordprocessingML_Parts.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 2: Partes de un documento WordprocessingML&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;En la raíz del paquete .zip existe un archivo llamado &lt;strong&gt;[Content_Types].xml &lt;/strong&gt;que describe todos los tipos de contenido para cada una de las partes dentro del paquete. El &lt;em&gt;Content Type&lt;/em&gt; indica al consumidor del documento qué tipo de contenido debe ser esperado dentro del paquete.&lt;br /&gt;Si continuamos explorando el archivo .zip, veremos una carpeta llamada &lt;strong&gt;_rels&lt;/strong&gt;. Esta carpeta contiene un archivo XML con extensión &lt;strong&gt;.rels&lt;/strong&gt; que describe las relaciones entre las diferentes partes del documento y permite unir el documento y sus partes.&lt;br /&gt;&lt;br /&gt;En la carpeta &lt;strong&gt;docProps&lt;/strong&gt;, encontraremos varios archivos XML como &lt;strong&gt;core.xml&lt;/strong&gt;, &lt;strong&gt;app.xml&lt;/strong&gt; y &lt;strong&gt;custom.xml&lt;/strong&gt;. Estos archivos almacenan las propiedades del documento. Por ejemplo, el archivo &lt;em&gt;core.xml&lt;/em&gt; contiene las propiedades generales aplicacables a todos los documentos de OOXML como &lt;em&gt;Título&lt;/em&gt;, &lt;em&gt;Asunto&lt;/em&gt;, &lt;em&gt;Autor&lt;/em&gt;, etc. EL archivo &lt;em&gt;app.xml&lt;/em&gt; contiene propiedades específicas del documento como &lt;em&gt;Número de páginas&lt;/em&gt;, &lt;em&gt;Número de líneas de texto&lt;/em&gt;, &lt;em&gt;Versión de la aplicación&lt;/em&gt;, etc. Finalmente, el archivo &lt;em&gt;custom.xml&lt;/em&gt; contiene propiedades personalizadas agregadas por el autor o usuario del documento.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Archivos binarios&lt;/strong&gt;&lt;br /&gt;El formato XML no soporta nativamente los datos binarios como imágenes u objetos OLE. OOXML almacena los datos binarios en como partes binarias en su formato nativo. Si examinamos la carpeta &lt;strong&gt;media&lt;/strong&gt; encontraremos las imágenes y objetos binarios que han sido incluidos en el documento.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Un documento WordprocessingML básico&lt;br /&gt;&lt;/strong&gt;Si quisiéramos crear un documento WordprocessingML básico, necesitaríamos al menos 3 partes:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Un archivo &lt;strong&gt;document.xml&lt;/strong&gt; que contiene el cuerpo principal del documento.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Un archivo &lt;strong&gt;[Content_Types].xml&lt;/strong&gt; que describe los tipos de contenidos incluidos en el paquete.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Un archivo &lt;strong&gt;.rels&lt;/strong&gt; que define las relaciones entre las diferentes partes y permite ubicar cada parte dentro del paquete.&lt;/li&gt;&lt;/ol&gt;&lt;a href="http://bp0.blogger.com/_apvGJDAiQ0E/R47KISvvbZI/AAAAAAAAABo/mv-s3SDViUw/s1600-h/WordprocessingML_docx.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156280867205639570" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_apvGJDAiQ0E/R47KISvvbZI/AAAAAAAAABo/mv-s3SDViUw/s400/WordprocessingML_docx.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 3: Documento Wordprocessing básico&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;La parte de inicio, document.xml&lt;/strong&gt;&lt;br /&gt;El primer elemento al crear un documento de OOXML es la parte de inicio (&lt;strong&gt;start-part&lt;/strong&gt;). Este es el lugar donde los consumidores empezarán a parsear el contenido del documento. Los 3 lenguajes de marcas principales de OOXML (&lt;em&gt;WordprocessingML&lt;/em&gt;, &lt;em&gt;SpreadsheetML&lt;/em&gt;, &lt;em&gt;PresentationML&lt;/em&gt;) contienen dentro del archivo ZIP una parte considerada como la parte de inicio. En WordprocessingML la parte de inicio es el archivo document.xml y es usado para almacenar el contenido principal del documento.&lt;br /&gt;&lt;br /&gt;La siguiente figura muestra un ejemplo del contenido de un archivo document.xml:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_apvGJDAiQ0E/R44gbyvvbWI/AAAAAAAAABM/wPrVSEJYmaA/s1600-h/WordprocessingML_Document.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156094285236366690" style="CURSOR: hand" alt="" src="http://bp2.blogger.com/_apvGJDAiQ0E/R44gbyvvbWI/AAAAAAAAABM/wPrVSEJYmaA/s400/WordprocessingML_Document.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 4: Contenido de document.xml&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Se puede observar una estructura XML bastante sencilla para formar un documento. Dentro del elemento &lt;em&gt;document&lt;/em&gt; se puede crear los bloques de construcción del documento como párrafos, tablas y gráficos. Muchos de estos elementos utilizan el mismo identificador de espacio de nombres XML. &lt;strong&gt;Microsoft Office 2007&lt;/strong&gt; utiliza el prefijo &lt;em&gt;w&lt;/em&gt;. Podemos usar cualquier otro prefijo, pero debemos mantener el espacio de nombres XML de WordprocessingML:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://schemas.openxmlformats.org/wordprocessingml/2006/main"&gt;&lt;strong&gt;http://schemas.openxmlformats.org/wordprocessingml/2006/main&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Los tipos de contenidos, [Content_Types].xml&lt;/strong&gt;&lt;br /&gt;Los consumidores de OOXML necesitan saber qué tipos de contenidos existen dentro del paquete. La lista de tipos de contenidos está definida dentro del archivo &lt;strong&gt;[Content_Types].xml&lt;/strong&gt; que debe estar ubicado en la raíz del contenedor.&lt;br /&gt;Los tipos de contenidos se identifican de dos formas:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Utilizando la extensión del archivo de partes dentro del paquete.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Especificando la ubicación y tipo de contenido del archivo dentro del paquete.&lt;/li&gt;&lt;/ol&gt;La siguiente figura muestra el contenido de un archivo [Content_Types].xml:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_apvGJDAiQ0E/R44fpCvvbVI/AAAAAAAAABE/zSZR0H3hW1w/s1600-h/WordprocessingML_ContentTypes.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156093413358005586" style="CURSOR: hand" alt="" src="http://bp3.blogger.com/_apvGJDAiQ0E/R44fpCvvbVI/AAAAAAAAABE/zSZR0H3hW1w/s400/WordprocessingML_ContentTypes.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 5: Contenido de [Content_Types].xml&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Se puede ver claramente las dos estrategias utilizadas para identificar y definir los tipos de contenidos de cada parte dentro del paquete. Dentro del elemento &lt;strong&gt;Types&lt;/strong&gt; se puede crear dos elementos, &lt;em&gt;Default&lt;/em&gt; y &lt;em&gt;Override&lt;/em&gt;. En el ejemplo, el elemento Default asocia la extensión &lt;em&gt;xml&lt;/em&gt; con el tipo de contenido &lt;em&gt;application/xml&lt;/em&gt;, y de forma similar puede observarse el tipo de contenido asociado a los archivos &lt;em&gt;rels&lt;/em&gt; y los archivos &lt;em&gt;png&lt;/em&gt;.&lt;br /&gt;&lt;p&gt;Anteriormente, hablamos del archivo &lt;strong&gt;document.xml&lt;/strong&gt; , que es la parte de inicio y contiene el cuerpo principal del documento. Como la extensión de este archivo es &lt;em&gt;xml&lt;/em&gt;, el elemento &lt;em&gt;default&lt;/em&gt;, del archivo de tipos de contenidos, indicaría que se trata de un simple archivo de tipo &lt;em&gt;application/xml&lt;/em&gt;, sin embargo este archivo es especial y debe ser definido como tal. Para ello se utiliza el elemento &lt;strong&gt;Override&lt;/strong&gt;, para sobrescribir la asociación de tipos por defecto y especificar el tipo de contenido asociado en forma explícita.&lt;/p&gt;&lt;p&gt;En el ejemplo, existe un elemento &lt;em&gt;Override&lt;/em&gt; que asocia el archivo &lt;strong&gt;/word/document.xml&lt;/strong&gt; con el tipo de contenido &lt;strong&gt;application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml&lt;/strong&gt;. Este mismo enfoque se utiliza para definir el tipo de contenido de las partes restantes del documento.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Las relaciones entre partes&lt;/strong&gt;&lt;br /&gt;Otro elemento requerido en un documento Wordprocessing, es el archivo de relaciones entre partes. En el archivo .zip existe una carpeta _&lt;strong&gt;rels&lt;/strong&gt; que contiene un archivo &lt;strong&gt;.rels&lt;/strong&gt;. Este es un archivo XML que define las relaciones y ubicación de las partes principales del paquete.&lt;/p&gt;&lt;p&gt;La siguiente figura muestra el contenido del archivo .rels:&lt;/p&gt;&lt;a href="http://bp1.blogger.com/_apvGJDAiQ0E/R44g0ivvbXI/AAAAAAAAABU/2paCTm_yWuM/s1600-h/WordprocessingML_Relationships.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156094710438129010" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_apvGJDAiQ0E/R44g0ivvbXI/AAAAAAAAABU/2paCTm_yWuM/s400/WordprocessingML_Relationships.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 6: Contenido del archivo .rels&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;El elemento &lt;em&gt;Relationship&lt;/em&gt; contiene tres piezas básicas de información:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;ID&lt;/strong&gt;: Un identificador único para la relación.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Type&lt;/strong&gt;: define el tipo de relación.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Target&lt;/strong&gt;: especifica la ubicación del elemento o parte relacionada.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Debe observarse que no hay información sobre el origen (Source) de la relación. En este caso, el origen de la relación es implícito y relativo a la raíz del paquete.&lt;/p&gt;&lt;p&gt;Además del archivo &lt;em&gt;.rels&lt;/em&gt; principal, dentro de la carpeta &lt;em&gt;word/_rels&lt;/em&gt; existe un archivo &lt;em&gt;document.xml.rels&lt;/em&gt; que define las partes relacionadas al &lt;em&gt;documento.xml&lt;/em&gt; como el encabezado, pie, estilos y fuentes.&lt;/p&gt;&lt;p&gt;Utilizando el attributo &lt;em&gt;type&lt;/em&gt; y &lt;em&gt;target &lt;/em&gt;del archivo &lt;em&gt;.rels&lt;/em&gt;, los consumidores de documentos OOXML pueden localizar el documento principal (start-part), y, luego, usando el archivo de relaciones asociado al documento principal (&lt;em&gt;document.xml.rels&lt;/em&gt;), es posible ubicar el encabezado y pie, encontrar las imágenes y otras partes relacionadas al documento.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Hasta aquí hemos visto las partes principales de un documento de &lt;strong&gt;WordprocessingML&lt;/strong&gt;, su formato y estructura. En la próxima entrega empezaremos a hacer ejercicios y veremos cómo crear y empaquetar esas partes en forma manual y en forma programatica, utilizando la &lt;strong&gt;API de Packaging&lt;/strong&gt; (System.IO.Packaging) incluida en &lt;strong&gt;.NET 3.0&lt;/strong&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-5918725435682451398?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/5918725435682451398/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=5918725435682451398&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5918725435682451398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/5918725435682451398'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/01/los-documentos-wordprocessingml.html' title='Los documentos WordprocessingML'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_apvGJDAiQ0E/R44evSvvbSI/AAAAAAAAAAs/Mwc_1ydgKx4/s72-c/WordprocessingML_Zip.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-8798434137409186979</id><published>2008-01-15T18:11:00.000-02:00</published><updated>2008-12-11T10:14:44.528-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='S+S'/><category scheme='http://www.blogger.com/atom/ns#' term='OOXML'/><title type='text'>Conociendo Office Open XML</title><content type='html'>&lt;a href="http://gustavoazcona.blogspot.com/2008/01/por-qu-office-open-xml.html"&gt;Anteriormente&lt;/a&gt;, comenté acerca de OOXML, la idea de Software + Servicios y cómo podemos beneficiar nuestros desarrollos con estos nuevos enfoques. En este post vamos conocer un poco más sobre OOXML, sus elementos y su estructura.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Componentes de OOXML&lt;/strong&gt;&lt;br /&gt;Como vimos en el &lt;a href="http://gustavoazcona.blogspot.com/2008/01/por-qu-office-open-xml.html"&gt;post anterior&lt;/a&gt;, Office Open XML es una especificación basada en XML para documentos digitales como planillas de cálculo, gráficos, presentaciones y documentos de procesamiento de texto. La especificación fue desarrollada por Microsoft para suceder al formato binario de Microsoft Office y fue &lt;a href="http://openxmldeveloper.org/archive/2006/12/07/Ecma_standard_approved.aspx"&gt;estandarizada por la ECMA en diciembre de 2006&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;En la especificación actual aparecen tres lenguajes de marcas principales:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;WordprocessingML&lt;/strong&gt;: para documentos.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;SpreadsheetML&lt;/strong&gt;: para hojas de cálculo.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;PresentationML&lt;/strong&gt;: para presentaciones&lt;/li&gt;&lt;/ul&gt;Además de estos lenguajes de marcas, existen otros lenguajes subyacentes como DrawingML usado para dar soporte a gráficos, tablas y diagramas.&lt;br /&gt;Las partes de un documento OOXML son empaquetadas dentro de un contenedor. Hoy se utiliza el formato ZIP para empaquetar y contener los archivos y recursos que componen un documento, sin embargo, podría utilizarse una base de datos como contenedor de documentos OOXML.&lt;br /&gt;Finalmente, además de los lenguajes de marcas, la estructura interna dentro del paquete o contenedor también ha sido estandarizada. Esta estructura se conoce como Open Packaging Convention.&lt;br /&gt;El siguiente gráfico resume los elementos principales de la especificación OOXML. ZIP y XML + Unicode no son parte de la especificación.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_apvGJDAiQ0E/R40WRSvvbQI/AAAAAAAAAAc/r-JEHgXBZu4/s1600-h/OOXML_Components.JPG"&gt;&lt;/a&gt;&lt;a href="http://bp1.blogger.com/_apvGJDAiQ0E/R43xwyvvbRI/AAAAAAAAAAk/xK-zxR9z6E0/s1600-h/OOXML_Components.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5156042968967114002" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_apvGJDAiQ0E/R43xwyvvbRI/AAAAAAAAAAk/xK-zxR9z6E0/s400/OOXML_Components.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Figura 1: Componentes de Office Open XML&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;En el siguiente post exploraremos el formato y estructura de documentos &lt;strong&gt;WordprocessingML&lt;/strong&gt; y comprenderemos mejor la relación entre los componentes de OOXML.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-8798434137409186979?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/8798434137409186979/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=8798434137409186979&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8798434137409186979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/8798434137409186979'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/01/conociendo-office-open-xml.html' title='Conociendo Office Open XML'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_apvGJDAiQ0E/R43xwyvvbRI/AAAAAAAAAAk/xK-zxR9z6E0/s72-c/OOXML_Components.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7202343029566820509.post-1762490281112916602</id><published>2008-01-15T17:21:00.000-02:00</published><updated>2008-12-11T10:15:01.601-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='S+S'/><category scheme='http://www.blogger.com/atom/ns#' term='OOXML'/><title type='text'>¿Por qué Office Open XML?</title><content type='html'>También conocida como &lt;strong&gt;OOXML&lt;/strong&gt;, es una de las nuevas siglas que inspiran cientos de posts en los blogs de tecnología. &lt;strong&gt;Office Open XML&lt;/strong&gt; es una especificación basada en XML para documentos digitales como planillas de cálculo, gráficos, presentaciones y documentos de procesamiento de texto. La especificación fue desarrollada por &lt;strong&gt;Microsoft&lt;/strong&gt; para suceder al formato binario de &lt;strong&gt;Microsoft Office&lt;/strong&gt;. Esta especificación fue &lt;a href="http://openxmldeveloper.org/archive/2006/12/07/Ecma_standard_approved.aspx"&gt;estandarizada por la ECMA en diciembre de 2006&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Actualmente, la especificación está siendo evaluada por la &lt;strong&gt;ISO&lt;/strong&gt; referida como &lt;strong&gt;DIS 29500&lt;/strong&gt; (Draft International Standard 29500) y se ha generado una polémica en su entorno que escapa los fines de este post.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Software + Servicios&lt;/strong&gt;&lt;br /&gt;Más allá de la polémica suscitada sobre la estandarización, muchos desarrolladores se preguntarán por qué o para qué necesito aprender OOXML. Bueno, existen muchas motivaciones para usarlo. En los siguientes enlaces encontrarán dos artículos en español interesantes que hablan acerca de los fundamentos del nuevo mundo de documentos y los formatos de Open XML: &lt;a href="http://www.microsoft.com/spain/interop/openxml/new_world_of_docs.mspx"&gt;http://www.microsoft.com/spain/interop/openxml/new_world_of_docs.mspx&lt;/a&gt; &lt;a href="http://www.microsoft.com/spain/interop/openxml/ds_open_xml.mspx"&gt;http://www.microsoft.com/spain/interop/openxml/ds_open_xml.mspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;De las diferentes oportunidades que OOXML puede generar, la que más me ha interesado como desarrollador fue la posibilidad de construir e implementar soluciones &lt;a href="http://msdn2.microsoft.com/en-us/architecture/aa699384.aspx"&gt;S+S (Software + Services)&lt;/a&gt; combinando las soluciones de clientes ricos y soluciones móviles con servicios de Internet.&lt;br /&gt;&lt;br /&gt;Por ejemplo, crear una solución basada en planillas de cálculo que permita generar una orden de compra y publicarla en el sistema de gestión de compras a través de Internet; o escribir un artículo en el procesador de texto y publicarlo en la web con un solo clic.&lt;br /&gt;&lt;br /&gt;Se trata de aprovechar la flexibilidad y experiencia de usuario enriquecida proporcionada por las aplicaciones de escritorio y móbiles y combinarlas con servicios de Internet basados, por ejemplo, en el modelo &lt;strong&gt;SaaS&lt;/strong&gt;. De hecho, podría arriesgar a decir que &lt;em&gt;S+S&lt;/em&gt; intenta cubrir los aspectos que se pierden en un enfoque &lt;em&gt;SaaS&lt;/em&gt; puro, como la experiencia de usuario enriquecida basada en soluciones de escritorio ricas, capacidad de trabajo offline, mayor aprovechamiento de la plataforma subyacente, etc.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;El papel de OOXML en S+S&lt;br /&gt;&lt;/strong&gt;Resulta interesante la idea de S+S, pero ¿qué papel juega OOXML?. En el pasado ya se han construido aplicaciones capaces de generar o capturar información a través de planillas de cálculo y documentos de texto utilizando los formatos binarios de Microsoft Office y otras suites.&lt;br /&gt;Entiendo que un aspecto interesante de OOXML para los desarrolladores es, por ejemplo, el soporte que ofrece Microsoft a través de &lt;strong&gt;.NET Framework&lt;/strong&gt; para crear y manipular documentos de OOXML, facilitando la integración y construcción de soluciones S+S.&lt;br /&gt;&lt;br /&gt;Muchos aún discuten que OOXML no es estándar, que no es abierto, que no es XML, etc. Pero la realidad es que la mayoría de las empresas en el mundo centran su trabajo en el uso de documentos electrónicos. Aplicaciones como &lt;strong&gt;Excel&lt;/strong&gt; y &lt;strong&gt;Word&lt;/strong&gt;, se han convertido en la herramienta principal o preferida para registrar, visualizar, manipular y publicar datos. Estos escenarios basados en documentos representan nuevas oportunidades para complementar, interoperar y extender nuestros productos y servicios.&lt;br /&gt;&lt;br /&gt;En los próximos post empezaré a explorar este nuevo mundo de Open XML desde la perspectiva del desarrollador; veremos la teoría y crearemos ejemplos en .NET.&lt;br /&gt;Hasta la próxima!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7202343029566820509-1762490281112916602?l=gustavoazcona.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gustavoazcona.blogspot.com/feeds/1762490281112916602/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7202343029566820509&amp;postID=1762490281112916602&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1762490281112916602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7202343029566820509/posts/default/1762490281112916602'/><link rel='alternate' type='text/html' href='http://gustavoazcona.blogspot.com/2008/01/por-qu-office-open-xml.html' title='¿Por qué Office Open XML?'/><author><name>Gustavo Azcona</name><uri>http://www.blogger.com/profile/01669356856597985462</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
