Me acaba de suceder un comportamiento frustrante del Visual Studio 2005, por alguna extraña razón que aun no acierto a comprender, me dejó de mostrar el diseño de las paginas web. Me explico: tengo una pagina web con un formulario, el Source(html) se muestra bien pero si le doy clic en Desing se pega un rato, termina no mostrando nada y queda inestable en general el Visual Studio (combinación de teclas que no funcionan, etc...)
Después de desesperados intentos de resucitación sin resultado, di con la solución:
- Cerramos el VS2005.
- Abrimos el Command Prompt de VS 2005.
- Digitamos lo siguiente:
devenv /resetsettings
devenv /setup
y Gloria! Aleluya! ya volvió a servir la vista de diseño. Que raros estos achaques que le dan a Visual Studio algunos son realmente frustrantes....
17 jun 2010
Update con valores de otra tabla
Algunas cosillas se nos va cómo es que hay que hacerlas, a veces son un tanto lógicas y nos parece que son sencillas pero por una u otra no le llegamos.
Eso me pasó recientemente cuando necesitaba actualizar la tabla1 con valores de la tabla2 (en realidad debía pasar los datos de una a otra y borrar la tabla2).
Para ser este tipo de Update una sintaxis que funciona en SQL server 2005 es la siguiente
En la tabla 2 lo lógico es que debe haber un solo registro devuelto por la sentencia Join con respecto a la Tabla1.
Eso me pasó recientemente cuando necesitaba actualizar la tabla1 con valores de la tabla2 (en realidad debía pasar los datos de una a otra y borrar la tabla2).
Para ser este tipo de Update una sintaxis que funciona en SQL server 2005 es la siguiente
UPDATE T1 SET T1.campo1 = T2.campo1, T1.cammpo2 = T2.campo2 FROM Tabla1 T1 INNER JOIN Tabla2 T2 ON T2.campoLlave = T1.campoLlave
En la tabla 2 lo lógico es que debe haber un solo registro devuelto por la sentencia Join con respecto a la Tabla1.
26 abr 2010
__doPostBack
ASP.Net 2.0. Me imagino que se habrán dado cuenta de que en las páginas de asp.net se implementa un curioso metodo llamado __doPostBack, de hecho nosotros lo podemos utilizar dentro de las funciones del lado del cliente de los controles de .Net como por ejemplo en el OnClientClick de un botón. Pero ¿que es lo que hace? y ¿cómo lo hace?
Básicamente realiza un submit de la página, ó sea, dispara el postback, como claramente indica su nombre. El método recibe dos parámetros: __EVENTTARGET y __EVENTARGUMENT El primero de los cuales recibe el nombre del control que dispara el postback y el segundo el método de dicho control.
Ahora, ¿cómo hace esta función para hacer el postback? El código que se genera automáticamente es mas o menos este:
Ahora bien, nosotros podemos hacen uso del método con los parámetros vacíos __doPostBack("",""); Esto dispara el submit y se hubiera algún método del lado del servidor que no se hayan ejecutado (por tener el AutoPostBack en False, por ejemplo) entonces ahora también se dispararán. Este método se usa en los treeview que no disponen de método de postback, cuando se utilizan con checkboxes, para que cuando hagan click en alguno de ellos se ejecute el método postback correspondiente.
Pero hay algo más. La realización de un simple Submit con controles ocultos significa que podemos capturar los valores de los parámetros(valores del los controles ocultos) del lado del servidor y por ende, ejecutar lo que nos parezca más conveniente en determinadas circunstancias. Así por ejemplo podemos hacer una función javascript como esta:
Básicamente realiza un submit de la página, ó sea, dispara el postback, como claramente indica su nombre. El método recibe dos parámetros: __EVENTTARGET y __EVENTARGUMENT El primero de los cuales recibe el nombre del control que dispara el postback y el segundo el método de dicho control.
Ahora, ¿cómo hace esta función para hacer el postback? El código que se genera automáticamente es mas o menos este:
< input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" / >
< input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" / >
function __doPostBack(eventTarget, eventArgument)
{
if (!theForm.onsubmit || (theForm.onsubmit() != false))
{
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
Como se puede ver, son simplemente dos textbox ocultos y una función que los utiliza para el disparar el submit. Como lo dije antes, este código es generado automáticamente siempre y cuando haya al menos un control en la página que tenga al atributo “AutoPostBack” en True. Si lo queremos es usar la funcion sin que haya controles con el AutoPostBack en True, pues manualmente ponemos el código anterior en la página y listo.Ahora bien, nosotros podemos hacen uso del método con los parámetros vacíos __doPostBack("",""); Esto dispara el submit y se hubiera algún método del lado del servidor que no se hayan ejecutado (por tener el AutoPostBack en False, por ejemplo) entonces ahora también se dispararán. Este método se usa en los treeview que no disponen de método de postback, cuando se utilizan con checkboxes, para que cuando hagan click en alguno de ellos se ejecute el método postback correspondiente.
Pero hay algo más. La realización de un simple Submit con controles ocultos significa que podemos capturar los valores de los parámetros(valores del los controles ocultos) del lado del servidor y por ende, ejecutar lo que nos parezca más conveniente en determinadas circunstancias. Así por ejemplo podemos hacer una función javascript como esta:
function MiPostBack ()
{
var o = window.event.srcElement;
if ( o.tagName == "INPUT" && o.type == "checkbox")
{
__doPostBack("MiControl","MiEvento");
}
}
La cual la podemos usar en el OnClick de un treeview para indicar de que si hace clic sobre un checkbox del treeview haga submit con estos parámetros. Y en el método Page_Load del lado del servidor tener algo similar a esto
string controlName = Request.Params.Get("__EVENTTARGET");
string controlEvent = Request.Params.Get("__EVENTARGUMENT");
if ((controlName=="MiControl")&&(controlEvent=="MiEvento"))
{
UnMetodoCualquiera();
}
Así podemos ejecutar UnMetodoCualquiera(); cuando se produce un clic en alguno de los checkboxes del treeview (esto se realizó asi en un proyecto real para evitar que cuando se marcaba un checkbox padre se dispara el postback por cada hijo que también se marcaba automáticamente). Para mi esto abre más de una posibilidad para usar el __doPostBack cuando requiere ejecutar código del servidor.
16 abr 2010
Tablas temporales y cursores
Mi amigo Pigo Sama realizó un interesante articulo sobre tablas temporales y cursores.
Es interesante como señala la satanizacion de algunas de las características disponibles en motores de base de datos cuando, como bien lo indica Pigo, es cuestión de moderación y orientación en su uso.
Es interesante como señala la satanizacion de algunas de las características disponibles en motores de base de datos cuando, como bien lo indica Pigo, es cuestión de moderación y orientación en su uso.
4 mar 2010
Usar FOREACH ó SELECT
Hay veces en las que no nos detenemos a pensar, cómo estamos haciendo alguna tarea, simplemente no nos cuestionamos, tal vez porque estamos ajustados con los tiempos de entrega o peor aún, porque siempre lo hemos realizado así y no nos interesa preguntarnos si esaes la mejor forma. Debemos mantener la sana costumbre de preguntarnos cómo funcionan las cosas y si lo que hacemos es la mejor manera de alcanzar el objetivo.
Pues luego de esta introducción la pregunta: Tengo un DataTable y necesito encontrar una o varias filas según un criterio dado ¿Qué es mejor: recorrerlo con un foreach o hacer un select que me devuelva un arreglo de DataRows?.
Antes de contestar nada mejor lo probamos y salimos de las dudas. La prueba debe constar de lo siguiente:
- Crear el DataTable y Llenarlo con 2 millones de registros.
- Ejecutar un SELECT del DataTable, midiendo el tiempo que tarda.
- Ejecutar un FOREACH con el mismo criterio. Midiendo el tiempo que tarda
Paso 1 Creando el datatable y llenándolo de datos
Paso 2 Setear la variable que vamos a usar la búsqueda y ejecutar el SELECT
Paso 3 Ejecutar el FOREACH
Esta es una prueba sencilla y hecha de forma apresurada, pero válida dentro de lo que necesitamos probar. El código está en una consola y está hecho en VS 2005 y en una maquina virtual con Windows 2003. El resultado de las pruebas fue el siguiente:
Por lo que podemos ver la prueba arroja que la carga de dos millones de registros en la DataTable duro 7 segundos, ejecutar el SELECT 5 segundos y medio y el FOREACH menos de medio segundo. Se ejecutaron varias corridas y los resultados fueron muy similares. Triunfador sin discusión: el FOREACH.
Ahora, que pasa si al DataTable le ponemos una llave. Al poner una llave debemos tener en cuenta que el engine ADO.NET, debe indexar la tabla lo que se puede llevar a cabo durante la carga de información, cada vez que se añade una fila (si creamos la llave antes de carga la información) o al crear la llave si la creamos luego de la carga de datos. Para propósitos de la prueba lo coloqué después de la carga y antes de la variable de búsqueda para determinar claramente la penalización de tiempo por la indexación.
Esta prueba arrojó el siguiente resultado
Después de varios ciclos de ejecución: el tiempo de carga se mantiene alrededor de los 7 segundos, la creación de la llave y por ende la indexación tarda entre 5.5 y 6 segundos. La ejecución del SELECT roza la instantaneidad y el FOREACH se mantiene en menos de medio segundo. Conclusión: el tiempo que tardaba la ejecución del SELECT se ha traslado a la indexación. Si hubiese más operaciones de búsqueda más adelante en el código sobre la misma datatable, puede que valiese la pena la creación de la llave pero de lo contrario prevalece la ejecución del FOREACH.
Finalmente hicimos unas pruebas utilizando un DataTableReader a partir del DataTable y recorriéndolo para obtener el mismo resultado, pero fue unas tres veces más lento que el FOREACH.
Muchas Gracias Jason y Pigo sama,
Pues luego de esta introducción la pregunta: Tengo un DataTable y necesito encontrar una o varias filas según un criterio dado ¿Qué es mejor: recorrerlo con un foreach o hacer un select que me devuelva un arreglo de DataRows?.
Antes de contestar nada mejor lo probamos y salimos de las dudas. La prueba debe constar de lo siguiente:
- Crear el DataTable y Llenarlo con 2 millones de registros.
- Ejecutar un SELECT del DataTable, midiendo el tiempo que tarda.
- Ejecutar un FOREACH con el mismo criterio. Midiendo el tiempo que tarda
Paso 1 Creando el datatable y llenándolo de datos
/* Creamos el datatable con dos columnas*/
DataTable dt = new DataTable();
DataColumn dc1 = new DataColumn("Col1", System.Type.GetType("System.Int32"));
DataColumn dc2 = new DataColumn("Col2", System.Type.GetType("System.String"));
dt.Columns.Add(dc1);
dt.Columns.Add(dc2);
/* Llenamos el datable con dos millones de registros*/
DataRow dr;
DateTime paso1 = DateTime.Now;
for (double i = 1; i < 2000001d; i++)
{
dr = dt.NewRow();
dr["Col1"] = i;
dr["Col2"] = "Datos de Prueba";
dt.Rows.Add(dr);
}
DateTime paso2 = DateTime.Now;
TimeSpan span = paso2.Subtract(paso1);
Console.WriteLine("total de Registros: " + dt.Rows.Count.ToString("N2"));
Console.WriteLine("Tiempo que dura la carga en milisegundos: " + span.TotalMilliseconds);
Paso 2 Setear la variable que vamos a usar la búsqueda y ejecutar el SELECT
/*Columna a encontrar*/
int var = 1234567;
/*Ejecutando el SELECT*/
paso1 = DateTime.Now;
DataRow[] arreglo = dt.Select("Col1 = " + var);
paso2 = DateTime.Now;
span = paso2.Subtract(paso1);
Console.WriteLine("Fin SELECT Total encontrados: " + arreglo.Length.ToString("N2"));
Console.WriteLine("Tiempo que duró el SELECT en Milisegundos: " + span.TotalMilliseconds);
Paso 3 Ejecutar el FOREACH
/* Ejecutando el FOREACH*/
ArrayList arraylist = new ArrayList();
paso1 = DateTime.Now;
foreach (DataRow dtr in dt.Rows)
{
if (Convert.ToDouble(dtr["Col1"]) == var)
{
arraylist.Add(dtr["Col1"]);
}
}
paso2 = DateTime.Now;
span = paso2.Subtract(paso1);
Console.WriteLine("Fin FOREACH Total encontrados: " + arraylist.Count.ToString("N2"));
Console.WriteLine("Tiempo que duró el FOREACH en milisegundos: " + span.TotalMilliseconds);
Esta es una prueba sencilla y hecha de forma apresurada, pero válida dentro de lo que necesitamos probar. El código está en una consola y está hecho en VS 2005 y en una maquina virtual con Windows 2003. El resultado de las pruebas fue el siguiente:
total de Registros: 2.000.000,00
Tiempo que dura la carga en milisegundos: 7000,0656
Fin SELECT Total encontrados: 1,00
Tiempo que duró el SELECT en milisegundos: 5638,1072
Fin FOREACH Total encontrados: 1,00
Tiempo que duró el FOREACH en milisegundos: 470,6768
Por lo que podemos ver la prueba arroja que la carga de dos millones de registros en la DataTable duro 7 segundos, ejecutar el SELECT 5 segundos y medio y el FOREACH menos de medio segundo. Se ejecutaron varias corridas y los resultados fueron muy similares. Triunfador sin discusión: el FOREACH.
Ahora, que pasa si al DataTable le ponemos una llave. Al poner una llave debemos tener en cuenta que el engine ADO.NET, debe indexar la tabla lo que se puede llevar a cabo durante la carga de información, cada vez que se añade una fila (si creamos la llave antes de carga la información) o al crear la llave si la creamos luego de la carga de datos. Para propósitos de la prueba lo coloqué después de la carga y antes de la variable de búsqueda para determinar claramente la penalización de tiempo por la indexación.
/*Creando LLAVE*/
paso1 = DateTime.Now;
DataColumn[] pk = new DataColumn[1];
pk[0] = dc1;
dt.PrimaryKey = pk;
paso2 = DateTime.Now;
span = paso2.Subtract(paso1);
Console.WriteLine("Creacion de llave en milisegundos: " + span.TotalMilliseconds);
Esta prueba arrojó el siguiente resultado
total de Registros: 2.000.000,00
Tiempo que dura la carga en milisegundos: 6789,7632
Creacion de llave en milisegundos: 5868,4384
Fin SELECT Total encontrados: 1,00
Tiempo que duró el SELECT en milisegundos: 10,0144
Fin FOREACH Total encontrados: 1,00
Tiempo que duró el FOREACH en milisegundos: 450,648
Después de varios ciclos de ejecución: el tiempo de carga se mantiene alrededor de los 7 segundos, la creación de la llave y por ende la indexación tarda entre 5.5 y 6 segundos. La ejecución del SELECT roza la instantaneidad y el FOREACH se mantiene en menos de medio segundo. Conclusión: el tiempo que tardaba la ejecución del SELECT se ha traslado a la indexación. Si hubiese más operaciones de búsqueda más adelante en el código sobre la misma datatable, puede que valiese la pena la creación de la llave pero de lo contrario prevalece la ejecución del FOREACH.
Finalmente hicimos unas pruebas utilizando un DataTableReader a partir del DataTable y recorriéndolo para obtener el mismo resultado, pero fue unas tres veces más lento que el FOREACH.
Muchas Gracias Jason y Pigo sama,
Suscribirse a:
Entradas (Atom)