lunes, 23 de agosto de 2010

Introducción al tipo de datos geography en Sql Server

Geography es de tipo espacial, y está implementado como un tipo de datos CLR en Sql Server, es decir es una clase administrada . Este tipo representa daata en un sistema de coordenadas de la tierra, la cual almacena información elipsoidal como latitud y longitud.

Ahora veremos un pequeño ejemplo de como hacer una consulta pero antes necesitamos crear nuestra tabla:

Código
CREATE TABLE [dbo].[Customer](
[ID] [decimal](18, 0) IDENTITY(1,1) NOT NULL,
[Name] [varchar](250) NOT NULL,
[Location] [geography] NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Simplemente creamos una tabla de clientes, con un ID, Nombre y su posición espacial utilizando el tipo geography. Ejecutamos el Script para crear la tabla y listo.

Ya con nuestra tabla creada ingresaremos la data. Hay que tener en cuenta que la posición es parecido a X,Y, (Longitud y latitud). Otro punto es que la data para ser convertida hay que utilizar ciertos métodos del tipo geography, la lista de métodos pueden verla en http://msdn.microsoft.com/en-us/library/bb933988.aspx los cuales soportan las especificaciones de Open Geospatial Consortium (OGC).

En este caso usaremos STGeomFromText, el cual según msdn se define como: "STGeomFromText (geography Data Type): Returns a geography instance from an Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation augmented with any Z (elevation) and M (measure) values carried by the instance."

La sintaxis es la siguiente:
Código:
STGeomFromText ( 'geography_tagged_text' , SRID )

El primer parámetro es el texto que queremos parsear como coordenadas, puede ser algo como 'POINT(-81.13 -6.17)'

El segundo parámetro es el identificador de referencia espacial. En nuestro caso usaremos el del planeta tierra que es el World Geodetic System 1984 (WGS 84) en donde el valor es: 4326 segun la tabla de sqlserver sys.spatial_reference_systems.

Con todo esto explicado el insert quedaría algo así:
Código
INSERT INTO Customer VALUES('Juan', geography::STGeomFromText('POINT(-81.13 -6.17)',4326))




Hacemos un Query:
Código
SELECT * FROM Customer
Código:
1 Juan 0xE6100000010CAE47E17A14AE18C0B81E85EB514854C0




Pero es muy dificil de comprender, por lo que hacemos un cast a Point:
Código
SELECT ID,Name,Location,CONVERT(Varchar(max),Location) AS Point FROM Customer
Código:
1 0xE6100000010CAE47E17A14AE18C0B81E85EB514854C0 POINT (-81.13 -6.17)



Intentemos algo más interesante: Hay un método llamado STDistance, el cual te regresa la distancia entre dos puntos, entonces hacemos la siguiente consulta:

Código
INSERT INTO Customer VALUES('Juan', geography::STGeomFromText('POINT(-60.13 -6.17)',4326))
GO
SELECT ID,Name,CONVERT(Varchar(max),Location) AS Point,
Location.STDistance(geography::STGeomFromText('POINT(-50.13 -6.17)',4326))
FROM Customer
GO

¿Qué hace? Pues, primero añadimos otro registro para darle un poco más valor a esto. Luego ejecutamos el Select, el cual calcula por cada registro la distancia sobre un punto en común: geography::STGeomFromText('POINT(-50.13 -6.17)',4326)

Cuando vemos el resultado es más fácil de entender:

Código:
ID Name Location Distance
1 Juan POINT (-81.13 -6.17) 3430549.19165979
3 Pedro POINT (-60.13 -6.17) 1106773.11874875

De esta forma podemos hacer que la consulta nos traiga los 10 Clientes más cercanos a X punto, qué es mucho más preciso que hacerlo por ciudad o algo parecido.

Un saludo, espero seguir con el tema en cuanto pueda.

Marshal - Interactuando entre managed y unmanaged memory.

Antes de comenzar con el tema tenemos que tener en cuenta que toda aplicación en .Net se ejecuta bajo una porción de memoria administrada por el CLR y no interactúa directamente con la memoria nativa.

Pero ahora, ¿Qué es Marshal?. Marshal es una clase que está en el namespace System.Runtime.InteropServices, que casi nadie habla de él y que no muchos han visto, y lo que hace es mediar entre ambos entornos. Imaginen un bar de lujo (Managed Memory), la calle (Unmanaged Memory) y el portero (Marshal), no es más que eso, si quieres entrar o salir del bar, vas a tener que pedirle permiso a Marshal. En pocas palabras marshal nos permite copiar data de un lado a otro.

Les voy a mostrar un cuadro que vi hace tiempo en msdn, y que ilustra muy bien las categorías de los miembros de la clase Marshal:

En este artículo utilizaremos principalmente los miembros de la categoría Data transformation, qué son los que nos permiten pasar data del entorno administrado al nativo y viceversa. Como vemos en la tabla, los métodos son bastante descriptivos, por ejemplo StringToHGlobalAnsi lo que hace es copiar el contenido de un string administrado a la memoria nativa, y te retorna la dirección en donde copió la data.

En esta página de msdn Marshal Members podrán ver bien qué hace cada miembro y si requiere de algún paso adicional, como es el caso de StringToHGlobalAnsi, el cual necesita llamar a la función FreeHGlobal (también de Marshal)

Veamos un ejemplo práctico del uso de Marshal:

Un amigo, [Zero], tiene una clase en C, es una especie de utilitario. Para el ejemplo usaremos la siguiente función del código de [Zero]:

//La funcion lo que hace es terminar un proceso en ejecucion.
int cTerminateProcess(char* lpProcessName)
{
HANDLE hProcess=NULL;
HANDLE hSnapshot=NULL;
PROCESSENTRY32 *pInfo=NULL;

hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(!hSnapshot) return -1;

pInfo=(PROCESSENTRY32*)GlobalAlloc(GPTR,sizeof(PROCESSENTRY32));
pInfo->dwSize=sizeof(PROCESSENTRY32);

//Obtenemos el PID del proceso
Process32First(hSnapshot,pInfo);
do
{
if(!lstrcmpA(pInfo->szExeFile,lpProcessName))
{
if(OpenProcess(PROCESS_TERMINATE,FALSE,pInfo->th32ProcessID))
{
hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,pInfo->th32ProcessID);
}
}
}while(Process32Next(hSnapshot,pInfo));

GlobalFree(pInfo);

if(!hProcess) return -1;

if(!TerminateProcess(hProcess,0))return -1;

Sleep(100);

return 1;
}

Supongamos que yo quiero usarlo desde .Net, ¿Cómo sería eso posible? No es muy dificil, ni requiere mucho tiempo. La idea es crear una librería en .Net la cual podamos referencia sin ningún problema, esto se llama wrapper, y lo haremos desde C++ CLI, el cual nos permite exactamente lo que queremos, interactuar entre entornos Administrados y Nativos mucho más fácil que desde C#, aunque sigue siendo posible, pero tendríamos que usar el keyword unsafe. En C++ tenemos mucho más fácil el acceso a la memoria nativa del sistema, y el mismo acceso al framework.

Ahora sigamos los siguientes pasos para crear nuestro Wrapper:

1.- Creamos una Solución en Blanco en Visual Studio
Le ponen un nombre y click en aceptar. Eso es todo.!

2.- Ahora agregamos Un Proyecto C++ (Static Library)
Este proyecto es donde va el código en C, es decir, las funciones a las cuales les queremos hacer el wrapper (en español es algo como envoltorio, ya veremos por qué). Para crear el proyecto le dan botón derecho en la solución, en el explorador de soluciones. Luego Agregar Nuevo Proyecto. En la ventana seleccionen Visual C++ y en el listado escojan Win32 Project, le dan un nombre y Click en Aceptar.

Aquí es donde va la función cTerminateProcess del código de [Zero].

3.- Creamos un Proyecto C++ CLI (Dynamic Library)
Este va a ser nuestro Wrapper, por lo que crearemos un proyecto en C++ CLI de tipo Dynamic Library, es decir una DLL. De la misma forma que con el proyecto anterior, agregamos un nuevo proyecto seleccionamos igual Visual C++ pero esta vez el tipo de Proyecto será Class Library. Nombramos el proyecto y aceptamos.

Ahora tenemos que hacer dos cosas, la primera es agregar el directorio en donde está el .h del proyecto de C, esto se hace yendo a las propiedades del proyecto > Propiedades de Configuración > C/C++ > General, y dónde dice Additional Include Directories agregar el directorio correspondiente. El segundo paso es agregar a la lista de dependencias la dirección en donde está el .lib que es el resultado del static library en C. Pueden hacerlo yendo a Propiedades de Configuración > Linker > Input, agregandolo en donde dice Dependencias Adicionales.

Ya tenemos todo listo para comenzar a hacer el wrapper.

Creamos una clase y le ponemos el nombre que quieras ponerle cuando la vayan a utilizar, por lo que debe ser un nombre que haga referencia a la función del código. En nuestro caso le pondremos DemoClass. Se crearán dos archivos uno .h y otro .cpp, Abrimos el .h para definir la clase y el método que queremos.

El código del .h quedaría así:
// DemoClass.h

#pragma once

using namespace System;

namespace Demo{

public ref class DemoClass
{
public:
int TerminateProcess(String^ ProcessName);
};
}

Si recordamos la función en C se llama cTerminateProcess, entonces en nuestro wrapper se llamará simplemente TerminateProcess, los parámetros es algo que hay que tener en cuenta, la funcion original pide char*, en .Net la idea es NO usar punteros por lo que usaremos String, y vale la pena recalcar el uso del simbolo ^ que es simplemente para identificar las referencias a código administrado y código nativo.

Ya tenemos el .h listo, vamos a codificar el cpp:

Código
// This is the main DLL file.

#include "stdafx.h"
#include
#include "DemoClass.h"

using namespace System;
using namespace System::Runtime::InteropServices;

namespace Demo{
int DemoClass::TerminateProcess(String^ ProcessName)
{
//Validamos :)
if(!ProcessName)
throw gcnew ArgumentNullException;

//Utilizamos StringToHGlobalAnsi el cual pide String como parametro
//como retorna un puntero, y sabemos que es un string, le hacemos un
//cast a char*
char* lpProcessName = (char*)(void*)Marshal::StringToHGlobalAnsi(ProcessName);

//ejecutamos cTerminateProcess y le pasamos lpProcessName
int result = AmC::cTerminateProcess(lpProcessName);

//liberamos la memoria usada por lpProcessName , y retornamos
Marshal
::FreeHGlobal((System::IntPtr)(void*)lpProcessName);
return result;
}
}

Como pueden ver no es nada complicado, aunque hay que hacerlo muy bien para no dejar punteros sin liberar ni funciones sin validar.


3.- Por último agregamos un Proyecto C# en Windows
Usaremos el proyecto para testear la libería. Al Form1 le agregamos un botón y un textbox.

Doble Click al botón para subscribirnos al evento Click, y colocamos esto:

Código
DemoClass m_amNet = new DemoClass();
m_amNet.
TerminateProcess(m_terminateProcessTextBox.Text);

Simplemente creamos una instancia de la clase DemoClass y llamamos al método TerminateProcess que a su vez llama al cTerminateProcess en la liberia en C.

Presionamos F5 para compilar y ejecutar nuestra solución, ejecutamos la calculadora, colocamos ese nombre calc.exe (el nombre del proceso de la calculadora) en el textbox, por último hacemos click en el botón y si todo sale bien debería cerrarse el proceso.



Espero les sirva de ayuda!

Un saludo!

domingo, 22 de agosto de 2010

El Blog De Juan ahora en Twitter!!



Sigue al blog en Twitter (@blogdejuan), y entérate de Tips, Enlaces, Noticias y muchas cosas más!!

Además es una forma más de poder escribirme y mandar cualquier cosa interesante que quieras compartir con nuestros lectores!

Gracias por leer y te esperamos en twitter!

martes, 17 de agosto de 2010

I JORNADA DE TECNOLOGÍA E INFORMÁTICA. CRUZANDO LÍMITES TECNOLÓGICOS.


Un evento de tecnología en donde participarán ponentes especialistas en las áreas correspondientes! Aprende y actualízate!

Hora
Octubrer 2 · 8:00am - 5:30pm

LugarAuditorio UJAP. San Diego, Edo. Carabobo, Venezuela

Enlace al evento en Facebook:
http://www.facebook.com/event.php?eid=148824025144375#!/event.php?eid=148824025144375

Espero puedan asistir!

lunes, 16 de agosto de 2010

Servicios

Aumentar la productividad gracias a la automatización de procedimientos mediante tecnologías de punta y bajando costos de los mismos es el objetivo de toda empresa. Puede contar con los siguientes servicios para conseguirlo:


  • Desarrollo:

    • Aplicaciones Web, Diseño gráfico digital, Web Services

    • Aplicaciones Windows y Plataformas Móviles

    • Diseño análisis de base de datos

    • Port de aplicaciones .Net a Mono Compilant



  • Consultoría y Asesorías en casi cualquier tecnología disponible

  • Reingeniera de procesos

  • Contacto con expertos de seguridad informática


Email de Contacto: andreujuanc[at]gmail[dot].com

Contacto


Para contactarme pueden escribir en el Chat, o también pueden escribirme un comentario en cualquier post del blog. O si lo prefieren, pueden escribir un email a: contact @ andreujuan . com (sin los espacios).

Saludos!

miércoles, 11 de agosto de 2010

II Foro Nacional de Tecnologías de la Información y la Comunicación

4 debates entre especialistas y expertos, todo el día.
Más una conferencia especial de obsequio.
Aforo limitado. Confirme su asistencia con tiempo.
El valor de las entradas será publicado a partir del mes de agosto.
(Certificado incluido)

Representantes de las mayores industrias de Information Technologies.
Un evento organizado por Lourtec (www.lourtec.com) y Softrain (www.softrain.com.ve)

Con el auspicio de Fundacid UC y la Biblioteca Central de la Universidad de Carabobo.




Lugar:
Centro Cultural Eladio Alemán Sucre
El Carabobeño. C.C Omnicentro. Av Universidad. Municipio Naguanagua
Valencia, Venezuela

Día y Hora:
November 20 · 7:30am - 7:00pm