Micro publicaciones guía para Power Apps, Power Automate, SharePoint y ademas algunos temas de Azure Dev Ops, Desarrollo Web, SQL Server, Asp.net.
martes, 25 de diciembre de 2007
Dependency Injection DI
viernes, 30 de noviembre de 2007
Reunion del 21 de noviembre del 2007 en la comunidad
Tema: Principios de OOP con .NET Framework 2.0
Expositor: Manolo Herrera(MVP Client Application 2007).
Fecha: Miércoles 21 de Noviembre de 2007
Horario: 6:30 P.M. – 8:30 P.M.
Lugar: Hotel Intercontinental Salón Rosul
Costo: Gratis
Otros: Habrá Coffee Break, Parqueo y Premios
Invita: Comunidad de Desarrolladores .NET en Guatemala, con Apoyo de Microsoft de Guatemala
Atentamente,
Manolo Herrera
Coordinador de La Comunidad de Desarrolladores .NET en Guatemala (http://groups.google.com/group/LaComunidadNET/web/memorias-de-las-reuniones-de-la-comunidad)
jueves, 22 de noviembre de 2007
Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies. The system cannot find the file specified.
Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies.
The system cannot find the file specified.
Este error me dio cuando abri un proyecto vs 2005 en VS2008 y mantuve la compatibilidad al framework 2.0, al parecer no solo me convierte la solucion sino que me agrega unos nuevos dlls del engine de crystal para aplicaciones web y me convierte los archivos de reportes rpt de Crystal.
Que hay que hacer:
agregar en el web config la referencia de los assemblies viejos de 2005 en la seccion runtime como se muestra aquí:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.CrystalReports.Engine " publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.CrystalReports.Shared" publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion=" 10.2.3600.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.Shared" publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
y luego se reemplaza las referencias de los dlls viejos por los nuevos y se copia los archivos rpt del proyecto de 2005 original, Se compila la solución y listo todo funciona como debe.
Por lo demas VS 2008 parece muy estable y si corre lado a lado con las versiones anteriores de 2005. Si intentan instalar el runtime de crystal 2008 necesitan una produc key misterioso que no se sabe cual es o si instalar los de redistribución que viene en la media de VS 2008, les cambia el error por este:
Aquí la referencia de la solución parcial:
http://tim.mackey.ie/default,month,2007-05.aspx (Lo que no incluye me imagino porque no era sobre la version RTM que cambia los archivos rpt de crystal y es necesario copiar los originales a los que le hace backup).
Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 800736b1.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 800736b1.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. |
Stack Trace:
|
Y allí no le he encontrado ninguna solución. Si la encuentran me avisan.
Code4Fun!,
Manolo Herrera
miércoles, 21 de noviembre de 2007
VS 2008 RTM una Version Estable
--
Code4Fun!,
Manolo Herrera
viernes, 16 de noviembre de 2007
Que paso con el buen uso del TryParse(string, out int variable)
En la version 2.0 del framework con el arribo de Generics, vino los nullables y los TryParse que cada tipo de dato que lo que pretenden es que evitemos el overhead del try catch para castear un valor que normalmente esta en string a un tipo de dato como un entero. Este sencillo método que lo tienen todos los tipos primitivos de datos del framework 2.0 en adelante me dan una solución elegante y menos cargada para los tipicos casteos de controles que reciben valores string y es necesario convertirlo a un tipo primitivo como entero, decimal, double, etc.
Manolo Herrera
Failed to update database because the database is read-only.
Code4Fun!
viernes, 12 de octubre de 2007
Proxima reunion de la comunidad VS2008 en Vivo!!!
Tema: Un vistazo a Visual Studio 2008 Beta 2
Expositor: Manolo Herrera (Coordinador de la comunidad .NET en Guatemala).
Fecha : Miércoles 24 de Octubre de 2007
Horario: 6:30 P.M. – 8:30 P.M.
Lugar: Hotel Intercontinental Salón Rosul
Costo: Gratis
Otros: Habrá Coffee Break, Parqueo y Premios
Invita: Comunidad de Desarrolladores .NET en Guatemala, con Apoyo de Microsoft de Guatemala
Atentamente,
Manolo Herrera
Coordinador de La Comunidad de Desarrolladores .NET en Guatemala (Blog: http://jmhogua.blogspot.com/)
viernes, 5 de octubre de 2007
Imaginese poder depurar la Class Library del .net framework
Releasing the Source Code for the .NET Framework Libraries
http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx
Ademas informa que a finales de este año ya se tendrá disponible la version RTM del VS 2008, otra gran noticia!!.
Que lo disfruten y seguramente aprenderemos mucho a comprender mejor el .net framework y su poder.
Hasta la proxima.
jueves, 27 de septiembre de 2007
Como saber si una columna existe en una tabla desde T-SQL
Como saber si una columna existe en una tabla
select
*FROM
INFORMATION_SCHEMA.COLUMNS AS c1where
c1.column_name = 'ValorCYBRegimenRetencionTributaria'and
c1.table_name = 'cybFactura'Mire esto como saber en que tablas utiliza esta columna
select
Table_NameFROM
INFORMATION_SCHEMA.COLUMNS AS c1where
c1.column_name = 'CodigoEmpresa'
Hasta le proximo consejo o artículo. CODE4FUN!
miércoles, 15 de agosto de 2007
Meaningful
Según el significado encontrado en google esta palabra significa: having a meaning or purpose; "a meaningful explanation"; "a meaningful discussion"; "a meaningful pause"
En español podríamos traducir como: Que tiene un significado o propósito. Esto nos da una mejor idea del significado de esta palabra que dentro del desarrollo ágil el desarrollo guiado por pruebas de sus siglas en inglés TDD (Test Driven Development), acuña el termino Meaningful o Significativo para el nombramiento de los métodos (ver pagina 42 del libro Test-Driven Development in Microsoft .NET de James W. Newkirk y Alexei A. Vorontsov).
Veamos literalmente el comentario: "Meaningful method names are important for code readability and in turn its overall maintainnability. In short, method names should convey their intentions." Que parafraseado diriamos lo siguiente: los nombres de los metodos deben de comunicar un significado o su propósito para la legilibidad del codigo y mantenimiento. En resumen los nombres de los métodos deberían transmitir sus intenciones.
Y para ser justos haremos una referencia al libro de Refactoring de Martin Fowler que acuño el concepto de Refactorización del código y que luego surgió el concepto de desarrollo ágil. De hecho en el libro de TDD la referencia de la página hace mención de la refactorización como una disciplina importante a tomar en cuenta en el desarrollo guiado por pruebas o TDD.
En la página 273 del libro de Martin Fowler "Refactoring". Una técnica de la refactorización es el renombrar los métodos y explica: La Motivación es los métodos deberían nombrarse en un forma que comunica su intención. Recuerde su código es para humanos primero y luego para la computadora. Termina diciendo los buenos nombres, es una habilidad que requiere práctica: mejorar esta habilidad es la llave para empezar ha ser un verdadero programador hábil.
Y para finalizar esta introducción al termino Meaningful vamos acuñar el concepto de la disciplina llamada "Refactoring", no es mas que: El proceso de cambiar un sistema de software de tal manera que este no altera el comportamiento externo del código pero mejora su estructura interna (Pagina XVI del libro en mención).
Esta breve introducción da pie al siguiente ejemplo:
Escenario:
Es una aplicación Web y tenemos un control de usuario que hace la búsqueda de proveedores por tres filtros que serán controles de texto o Textbox identificados de la siguiente manera: NITProveedor, NombreProveedor y CodigoInternoProveedor. Deseamos darle el comportamiento de tal forma que si el usuario ingresa un valor en alguno de los controles de entrada los otros controles nos aseguremos que es eliminado cualquier valor de los demás controles para que al buscar por cualquiera de ellos y no por la combinación de varios de ellos nos traiga la información requerida por el usuario.
Para ir directo al grano y delimitar de alguna forma el alcance de este ejemplo no nos detendremos a redactar la parte de búsqueda de la información requerida por el usuario, sino únicamente el comportamiento que deseamos que tenga los controles para mostrar un ejemplo del concepto Meaningful que es la motivación de una de las técnicas de Refactoring de renombrar métodos. El ejemplo esta hecho en Visual Studio 2005 y en C# 2.0 para los que preguntan.
Veamos por una mera referencia o idea visual el código html de la página en la cual vamos a trabajar:
<%@ Page Language="C#" AutoEventWireup="true" Codebehind="TeachingTheConceptMeaningFul.aspx.cs" Inherits ="TeachingTheConceptMeaningFul" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml"> < head runat="server"> <title>Busqueda de Proveedores</title > </ head > < body > <form id="form1" runat ="server"> <div>
</ div> </form> </ body> </ html>
|
Veamos la parte remarcada donde esta el caso de nuestro ejemplo, Tenemos los tres controles y cada uno de ellos tiene un evento que se ejecuta cada vez que cambia el valor ingresado en cada uno de los controles de texto la propiedad AutoPostBack nos indica que hará un postbak al servidor cada vez que cambie el texto al perder el foco del control, esto sucede asi por el ambiente Web en que estamos trabajando y la orientación de las aplicaciones asp.net que fueron diseñadas para validar del lado del servidor preferiblemente y no del lado del cliente, aunque se puede. Y por ultimo el útil Tooltip que aparece un recuadro en amarillo que aparece al acercar el cursor sobre el control en el cual estamos navegando.
Ahora veamos el código del lado del servidor que es el que realmente nos interesa.
public partial class TeachingTheConceptMeaningFul : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void NITProveedor_Cambio(object sender, EventArgs e)
{
this.NombreProveedor.Text = null;
this.CodigoInternoProveedor.Text = null;
}
protected void NombreProveedor_Cambio(object sender, EventArgs e)
{
this.NITProveedor.Text = null;
this.CodigoInternoProveedor.Text = null;
}
protected void CodigoInternoProveedor_Cambio(object sender, EventArgs e)
{
this.NITProveedor.Text = null;
this.NombreProveedor.Text = null;
}
}
Al apreciar este código parece que todo esta muy claro y que no es difícil que comprender, pero que pasa si tenemos que agregar otros filtros digamos unos 2 o 3 o tal vez 5 filtros mas deberemos repetir el código y tener el cuidado de no limpiar el contenido del control en el que el usuario. Pero ver asignar null al contenido de cada control de texto verdaderamente comunica el propósito de lo que estamos haciendo?. Bueno no me conteste ahora apliquemos la refactorización a nuestro código para hacerlo mas legible o por lo menos para centralizar las mismas operaciones.
Digamos que vamos a tener un solo método que se conecta a todos los controles y desde allí centralizamos el comportamiento de cada control.
Para ello comentamos el código html original para regresar al código anterior si todo nos sale mal (esto es una buena practica no eliminar el código hasta estar seguro que el cambio quedo bien. Y luego indicamos que el método al cual se pegará el disparar el evento del cambio del texto de cada control es el mismo y lo llamaremos "FiltroProveedor_Cambio". Veamos el código:
< div > Proveedor: <asp :TextBox ID="NITProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." /> <asp :TextBox ID="NombreProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." /> <asp:TextBox ID ="CodigoInternoProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." /> </ div>
|
Veamos ahora el código del lado del servidor:
protected void FiltroProveedor_Cambio(object sender, EventArgs e)
{
TextBox ControlTexto = (TextBox)sender;
switch (ControlTexto.ID)
{
case "NITProveedor":
this.NombreProveedor.Text = null;
this.CodigoInternoProveedor.Text = null;
break;
case "NombreProveedor":
this.NITProveedor.Text = null;
this.CodigoInternoProveedor.Text = null;
break;
case "CodigoInternoProveedor":
this.NITProveedor.Text = null;
this.NombreProveedor.Text = null;
break;
default :
break;
}
}
Que hicimos ahora, no mucho solo centralizamos el problema, no nos comunica mucho, es prácticamente el mismo código pero así es en la refactorización empezamos con pequeños cambios, para prepararnos para mejorar nuestro código. Es importante mencionar que aunque es valido utilizar el switch como una estructura de selección es muy rígida y que dentro de los patrones de diseño (Gof Design Patterns ) sugiere evitar su uso lo mas posible, con el objetivo que nuestro código sea mas adaptable y extensible con el menor cambio posible. Aplicando este concepto e implementando una solución posible y sencilla modificaremos nuestro código para hacerlo extensible y adaptable a los futuros cambios sin alterar nuestro código luego de estos cambios:
Primero vamos a convertir el div que agrupa los controles como un control de servidor y lo utilizaremos como un contenedor de controles para utilizar un loop para recorrer los controles dentro del div. Así como aparece a continuación:
<div id="ContenedorFiltrosProveedor" runat ="server"> Proveedor: <asp:TextBox ID ="NITProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." /> <asp:TextBox ID ="NombreProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." /> <asp:TextBox ID="CodigoInternoProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio" AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." /> </ div>
|
Ahora veamos el código del lado del servidor:
protected void FiltroProveedor_Cambio(object sender, EventArgs e)
{
TextBox ControlTexto = (TextBox)sender;
foreach (Control control in this.ContenedorFiltrosProveedor.Controls)
{
TextBox texto = control as TextBox;
if (texto != null)
{
if (texto.ID != ControlTexto.ID)
texto.Text = null;
}
}
}
Esto cambio completamente la rigidez de la estructura switch y nos permitirá agregar otros filtros tipo TextBox sin alterar el código. Veamos un ejemplo, digamos que vamos agregar un nuevo filtro tipo TextBox veamos lo que necesitamos hacer en el código html:
<div id="ContenedorFiltrosProveedor" runat ="server"> Proveedor: <asp:TextBox ID ="NITProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." /> <asp:TextBox ID ="NombreProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." /> <asp:TextBox ID ="CodigoInternoProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." /> <asp:TextBox ID="RazonSocialProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio" AutoPostBack="true" ToolTip="Ingrese el nombre de la razón social del proveedor." /> </ div>
|
Y del lado del servidor, absolutamente nada. Pero un minuto no hemos terminado ser recuerdo el objetivo del ejemplo es aprender a darle un nombre a los métodos que expliquen su propósito o significado, para ello vamos a utilizar la opción de Visual Studio 2005 Refactor (click derecho sobre el código seleccionado( y Seleccionaremos la opción ExtratMethod y ahora si colocaremos el nombre del método, como aparece a continuación:
protected void FiltroProveedor_Cambio(object sender, EventArgs e)
{
TextBox ControlTexto = (TextBox)sender;
LimpiarValorControlesTexto(ControlTexto);
}
private void LimpiarValorControlesTexto(TextBox ControlTexto)
{
foreach (Control control in this.ContenedorFiltrosProveedor.Controls)
{
TextBox texto = control as TextBox;
if (texto != null)
{
if (texto.ID != ControlTexto.ID)
texto.Text = null;
}
}
}
De alguna manera encapsulamos la funcionalidad y explicamos claramente lo que hace nuestro codigo sin decirlo como lo hace ya que esto no es el objetivo de la encapsulación y si del Concepto Meaningful Method Name.
Hasta la próxima. Write Code For Fun!,
Manolo