jueves, 29 de octubre de 2009

Windows 7 Network Driver for Vmware 6.5

El día de hoy instalé Windows 7 en una máquina virtual con Vmware 6.5, el problema fue que no reconocía el driver de la tarjeta de red de la máquina virtual. Sin embargo existe solución en caso de que el Vmware no tenga los drivers y esta es indicarle al Vmware que utilice cierto driver específico, para ello hay que ir al archivo .vmx de la máquina virtual (hay que apagar la virtual primero), abrirlo con el block de notas y añadir la siguiente línea:

ethernet0.virtualDev = "e1000"

Con ello reconocerá la tarjeta como 'Intel(R) PRO/1000 MT Network Connection' y ¡listo! ya podemos tener la red dentro de la vm.

Como comentario debo decir que la virtual ejecuta bastante bien, y eso que solamente le permití que tomara 512 MB de RAM. Tiene buena pinta el Windows 7, por lo menos es más ligero que sus predecesores. Seguiré probándolo.

(Update 23/Nov./2009) Es posible instalar Windows 7 indicando Windows Vista como sistema operativo base en VmWare, de esa manera no será necesario especificar drivers de red ni mover configuraciones manualmente.

viernes, 9 de octubre de 2009

Oracle UPSERT

En ocasiones resulta que necesitamos insertar un dato en la tabla si es que no existe ó actualizar (hacer un update) si es que sí existe. La primera solución que se viene a la mente tal vez sea la de:

select count(*) into CNT from where

if CNT = 0 then
insert into ...
else
update ....
end if;

Sin embargo existe otra manera más elegante de hacerlo que nos evita realizar el select-count inicial y se refiere a utilizar el valor de la pseudo-variable SQL%NOTFOUND que es un indicador que nos dice si la última instrucción de Update tuvo o no éxito (si encontró o no registros a modificar).

Utilizando esa propuesta, nuestro código quedaría de esta forma:

UPDATE set = where

if SQL%NOTFOUND then
insert into ...
end if;

Creo que de la forma anterior (sql%notfound) obtenemos un código más limpio y que en caso de tener un update exitoso nos ahorramos también tiempo de ejecución al no tener que hacer un conteo inicial.

Existe también otra posible solución que es la de utilizar la sentencia MERGE pero hablaremos de ella en otro post en un par de días.

martes, 25 de agosto de 2009

ASP.NET SetFocus y UpdatePanel

Recientemente me encontré con el hecho de que al utilizar el método .Focus() de un textbox todo funcionaba de maravilla mientras éste fuera invocado durante un full-refresh de la página, sin embargo al invocarlo durante una llamada asíncrona de un UpdatePanel la cosa cambiaba y el focus aparentemente se ejecutaba pero al mostrarse la página simplemente ningún control tenía el foco.

Indagando en foros y blogs me encontré con diversas soluciones a través de JavaScript pero ninguna me funcionó, al final me topé con una simpleza como la siguiente:

ScriptManager.SetFocus( TextBox1 )

Y esa fue la solución, ya que el script manager se encarga de poner el foco al regreso de la llamada asíncrona al UpdatePanel.

miércoles, 17 de junio de 2009

El control ModalPopUp en ASP.NET

En ocasiones se complica un poco recordar qué propiedad controla cada parte de un control ModalPopUp en ASP.NET + AJAX, es por ello que a continuación explico brevemente las propiedades más importantes y presento un diagrama de las mismas.

  • TargetControlID: indica cuál Label o control provocará que aparezca el ModalPopUp, éste puede ser un control dummy,
  • PopUpControlID: indica cuál es el panel que contiene nuestro cuadro de diálogo que deseamos se presente en forma modal.
  • OkControlID: indica cuál es el control que fungirá como botón de "Ok" ó "Aceptar" y hará que desaparezca el cuadro modal. Puede ser un control dummy.
  • CancelControlID: indica cuál es el control que fungirá como botón de "Cancelar" y hará que desaparezca el cuadro modal. Puede ser un control dummy.
  • BackgroundCssClass: indica el nombre de la clase CSS que debe ser aplicada como fondo mientras el panel modal está activo.

(click en la imagen para verla ampliada).



Nota: por "dummy" me refiero a un control que no tiene funcionalidad y cuyo único propósito es estar allí para que el componente no marque error. Un dummy en este caso podría ser un Label con la propiedad de Text en blanco.

sábado, 30 de mayo de 2009

Leer un Oracle REF CURSOR en ASP.NET

En ocasiones me ha resultado más conveniente que la aplicación web obtenga los datos consultando un procedimiento almacenado que devuelve un Ref Cursor en Oracle. Lo anterior debido a que en caso de ser necesario realizar algún cambio en la consulta, por ejemplo cambiar algunas condiciones en el select ó realizar alguna corrección.

De esta manera nos evitamos tener que modificar el código fuente y tener que dejarlo nuevamente en el servidor web. Además, podemos tomar el código del procedimiento almacenado y ejecutarlo en nuestras herramientas de desarrollo, SqlDeveloper en mi caso, para verificar resultados sin tener que pasar por todas las páginas involucradas en la aplicación web.

Recientemente me enfrenté al problema de que en ASP.NET surgían errores al tratar de obtener los valores desde un Ref Cursor.

Para el ejemplo, tenemos declarado el siguiente procedimiento Oracle:

PROCEDURE GET_TEST(cData OUT CursorType, XTRA OUT VARCHAR2)
IS
BEGIN
xtra := 'AE';

OPEN
cDATA FOR
SELECT
*
FROM DUAL;
END;



A continuación el código en ASP.NET (recortado, claro)

Dim DbCn as OracleConnection

' Codigo de asignación de propiedades para la conexion

' Codigo de apertura de conexion
DbCn.Open
Dim Cmd As OracleCommand = DbCn.CreateCommand
Cmd.CommandText
= "GET_TEST" ' Nombre del procedimiento almacenado
Cmd.CommandType = Data.CommandType.StoredProcedure

' Adición de los parámetros, en este caso uno de tipo RefCursor y el otro de tipo Varchar2
Cmd.Parameters.Add("pRET", OracleDbType.RefCursor).Direction = Data.ParameterDirection.Output
Cmd.Parameters.Add(
"PX", OracleDbType.Varchar2).Direction = Data.ParameterDirection.Output
Cmd.Parameters(
"PX").Size = 20

Cmd.ExecuteNonQuery()

' Obtención de los valores devueltos
Dim XX As String = Cmd.Parameters("PX").Value.ToString
Dim RC As Oracle.DataAccess.Types.OracleRefCursor = Cmd.Parameters("pRET").Value
Dim Da As New OracleDataAdapter
Dim dt As New System.Data.DataTable
Da.Fill(dt, RC)

' Eliminamos los objetos
RC.Dispose()
Da.Dispose()
DbCn.Close()

Me.GridView1.DataSource = dt
Me.GridView1.DataBind()


Quedan por hacer algunos comentarios:
  • Para algunos tipos de parámetro es necesario indicar la longitud del dato, tal es el caso de los Varchar2, en este caso, si al parámetro no se le indica un Size (20 en el ejemplo) entonces ocurrirá un error que indicará que la variable no es lo suficientemente grande como para almacenar el valor retornado.
  • Al objeto OracleCommand es necesario indicarle que el tipo de comando es "StoredProcedure" y entonces en el CommandText pondremos el nombre del procedimiento SIN parámetros ya que los parámetros los añadiremos después.
  • Los parámetros deberán ser añadidos en el orden en que aparecen en la declaración del stored procedure.
  • Luego de ejecutar el objeto comando con ExecuteNonQuery, obtendremos el valor del parámetro correspondiente a un OracleRefCursor y lo asignaremos a una variable de ese tipo, todo esto para después llenar un DataTable (ó DataSet) a través de un OracleDataAdapter ya que éste puede llenar la DataTable a través del objeto OracleRefCursor.
  • Luego de lo anterior ya podremos utilizar nuestro DataTable puesto que ya contendrá la información cargada.
  • Es posible leer de procedimientos que retornen más de un OracleRefCursor.
Espero que el presente post les haya sido de utilidad. Cualquier comentario, sugerencia o duda allí tienen el espacio de comentarios para expresarse =)