lunes, 27 de mayo de 2019

Caracteres Extraños Oracle ñ

En algunos casos al trabajar con bases de datos Oracle nos encontramos con que algunos caracteres especiales tales como Ñ, Á ü, no son mostrados correctamente.

Lo más probable es que el error se esté generando debido a que el cliente y el servidor de la base de datos tiene configurado diferente Juego de caracteres.

Para corregir este problema es necesario igualar el juego de caracteres de la base de datos y del cliente que esta realizando la consulta , inserción y actualización (Es recomendable revisar y unificar la  juego de caracteres de cada uno de los clientes que se conecte a la BD. de lo contrario podría existir discrepancia entre lo que diferentes clientes pueden ver)

1.- Ejecuta la siguiente consulta en la base de datos Oracle  con la que estas experimentando el problema: 

SELECT *
FROM V$NLS_PARAMETERS
WHERE PARAMETER in ('NLS_LANGUAGE','NLS_TERRITORY','NLS_CHARACTERSET'); 


    El resultado de la consulta deberá ser similar al siguiente: 
   


2.- Genera una cadena con los tres  valores devueltos. La cadena deberá tener la siguiente estructura: [NS_LANGUAGE_[NLS_TERRITORY].[NLS_CHARACTERSET]


3.- Agrega una nueva entrada en las variables del entorno del sistema (Inicio>>Este Equipo>>(botón secundario)>>Propiedades>>Configuración Avanzada del sistema.>>Variables del Entorno)


Ejemplo: MEXICAN SPANISH_MEXICO.WE8ISO8859P1



4.- Reinicia el sistema





viernes, 1 de febrero de 2019

Cursores Implicitos Oracle

Los cursores no son mi herramienta favorita pero por alguna razón que no tengo muy clara la realidad es que en el mundo de Oracle es una de las formas más comunes de hacer las cosas .. Cursor para esto, cursor para aquello, todo se puede resolver con cursores y la verdad es que he de reconocer que tienen un gran poder sin embargo prefiero prescindir de ellos en la medida de lo posible.

Pero para aquellos casos en los que no hay más opciones o la manera rápida de hacerlo es mediante un cursos aqui les dejo la forma que considero más sencilla de trabajar con cursores son los cursores implicitos. Aqui dejo un ejemplo de como se pueden usar 



BEGIN
    FOR  REGISTRO IN  (SELECT CAMPO1, CAMPO2
                                   FROM   Tabla1                 T1
                                              Inner join Tabla2  T2 On T1.A = T2.B
                                         )
     LOOP
          DBMS_OUTPUT.put_line(registro.campo1);     
    END LOOP;        

END; 


En esta entrada comparto un script para poder enviar correos desde Power Shel es importante señalar que antes de poder realizar el envío desde cuentas de gmail u outlook es necesario habilitar el envío de Aquí puedes encontrar un manual de como hacerlo.

$EmailFrom = "pruebas@gmail.com"
$EmailPass = "1234"
$EmailTo = "pruebas@gmail.com"
$Subject = "Prueba de correo PowerShel"
$Body = "Cuertpo del correo"
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom, $EmailPass)
$SMTPCliente.EnableSsl = $true;
$SMTPClient.send($SMTPMessage)



Es posible que el antivirus bloquee el envío de correos en esta caso podrías recibir un error similar al siguiente:





Si este es el caso revisa

Para enviar el mismo correo varias veces puedes sustituir la ultima linea por estas tres lineas:

for($i=0; $i -lt 3; $i++)
{
   $SMTPClient.send($SMTPMessage)
}

jueves, 2 de agosto de 2018

Monitor de licencias ASPEL

Hoy me enfrente con que el servidor de licencias de ASPEL no funcionaba y no me permita entrar en ninguno de los equipo (trabajo en red) y después de muchos intentes finalmente lo conseguí hacer funcionar.


1.- Desinstala y instala el servicio windows de licencias de usuario
  Abre una consola de comandos (CMD)
  Ejecuta la siguiente instrucción : C:\windowsSysWOW64\servlicasp /uninstall
  Reinicia la maquina.

Abre una consola de comandos (CMD)   Ejecuta la siguiente instrucción : C:\windowsSysWOW64\servlicasp /install
  Reinicia la maquina y asegurate de que el servicio se este ejecutando (Inicio->Servicios).


2.-Registra la DLL midas.dll
   regsvr32.exe c:\windows\system32\midas.dll


3.-Verifica que todas las referencias a a la DLL Midas.dll estén correctas en el reg edit
   Entrar al Regedit , seleccionar MI PC luego menú Edición / Buscar / midas.dll
  Verificar que todas las etiquetas que encuentres tengan la misma ruta y sea correcta es posible que hagan referencia a una ruta que ya no existe.


En otro momento ampliaré esta información.

sábado, 10 de junio de 2017

Copia masiva de datos usando OracleBulkCopy y Array Binding

En algunas ocasiones en nuestros desarrollos nos encontramos con la necesidad de copiar o insertar una gran cantidad de registros a nuestra base de datos desde algún origen externo como lo puede ser un archivo u otra base de datos; En esta entrada les comparto dos formas en las que pueden realizar esta copia de información de manera eficiente


El poderoso método de copia masiva BulkCopy

No tiene rival cuando de copiar una gran cantidad de datos se trata, yo lo recomiendo cuando se trata de más de 10,000 registros e incluso menos si es que requieres que tu copia de datos sea rápida. Debes garantizar que los registros que copias no infrinjan alguna de las reglas de la tabla y solo se puede hacer la copia no se puede usar con sentencias sql.

public static void CopiaMasivao(List<Libro> listaLibros)
{
        OracleBulkCopy copiaMasiva = new OracleBulkCopy("tu cadena de conexion");
        
        copiaMasiva.BulkCopyTimeout = 600;
        copiaMasiva.DestinationTableName = "LIBRO";
        copiaMasiva.ColumnMappings.Add("ID", "ID");
        copiaMasiva.ColumnMappings.Add("TITULO", "TITULO");
        copiaMasiva.ColumnMappings.Add("ISBN", "ISBN");
        //El uso de mappings sólo se requiere cuando el origen y el destino tienen número u orden de
        //columnas/propiedades diferentes. 
     
        copiaMasiva.WriteToServer(listaLibros.ToDataTable());

       cmdInsert.Connection.Close()
}

//Método  que que permite convertir una IEnumerable (en este caso nuestra lista generica) en un DataTable 

  public static class IEnumerableExtensions
    {
      public static DataTable ToDataTable<T>(this IEnumerable<T> data)
            {
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
                var table = new DataTable();
                foreach (PropertyDescriptor prop in properties)
                    table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
                foreach (T item in data)
                {
                    DataRow row = table.NewRow();
                    foreach (PropertyDescriptor prop in properties)
                        row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                    table.Rows.Add(row);
                }
                return table;
            }
        
    }

---------------------------------------------------------------------------------------------------------------------


El  poco documentado método de Array Binding (hasta donde se sólo disponible para Oracle)

Este método es muy efectivo lo recomiendo cuando se trata de menos de 10,000 registros o bien cuando no no se puede hacer uso de BulkCopy. La diferencia respecto al método de registro por registros que este método manda la información por bloques a la BD en lugar de enviar uno por uno, el tamaño del bloque es determinado por la propiedad BatchSieze. Es un excelente método de realizar no solo copia de datos sino de ejecutar instrucciones SQL con parámetros asociados.

public static void CopiaArray(List<Libro> listaLibros)
{
            string strSql = @"INSERT INTO LIBRO (ID,  TITULO,  ISBN) 
                                        VALUES  (:ID, :TITULO, :ISBN)";

            OracleCommand cmdInsert= new OracleCommand(strSql);
            cmdInsert.Connection = new OracleConnection("tu cadena de conexion");

            cmdInsert.Parameters.Add(":ID",OracleDbType.Int64);
            cmdInsert.Parameters.Add(":TITULO",OracleDbType.Varchar2,255);
            cmdInsert.Parameters.Add(":ISBN",OracleDbType.Int64);

            cmdInsert.Connection.Open();
            cmdInsert.Parameters["ID"].Value =  listaLibros.Select(x => x.ID).ToArray();
            cmdInsert.Parameters["TITULO"].Value = listaLibros.Select(x => x.Titulo).ToArray();
            cmdInsert.Parameters["ISBN"].Value =listaLibros.Select(x => x.ISBN).ToArray();;
            cmd.ArrayBindCount = listaLibros.Count;
          
            cmdInsert.ExecuteNonQuery();
            cmdInsert.Connection.Close()
}



El viejo y conocido método de registro por registro  

Ineficiente a la hora de copiar o insertar un numero importante de registros,  ya que por cada execute del comando se realiza un viaje a la BD con el respectivo costo que esto implica. Solo es recomendable cuando la inserción puede generar un error  y se requiere que continúe  con las demás inserciones 

public static void CopiaRegistroPorRegistro(List<Libro> listaLibros)
{
            string strSql = @"INSERT INTO LIBRO (ID,  TITULO,  ISBN) 
                                        VALUES  (:ID, :TITULO, :ISBN)";

            OracleCommand cmdInsert= new OracleCommand(strSql);
            cmdInsert.Connection = new OracleConnection("tu cadena de conexion");
            cmdInsert.Parameters.Add(":ID",OracleDbType.Int64);
            cmdInsert.Parameters.Add(":TITULO",OracleDbType.Varchar2,255);
            cmdInsert.Parameters.Add(":ISBN",OracleDbType.Int64);

            cmdInsert.Connection.Open();
            foreach (Libro libro  in listaLibros)
            {
                cmdInsert.Parameters["ID"].Value = libro.ID;
                cmdInsert.Parameters["TITULO"].Value = libro.Titulo;
                cmdInsert.Parameters["ISBN"].Value = libro.ISBN;

                cmdInsert.ExecuteNonQuery();
            }
            cmdInsert.Connection.Close()
}







jueves, 29 de septiembre de 2016

Estructura de Tablas Aspel SAE 6.0

Como ya hemos comentado en otra ocasión la mayoría de las aplicaciones de Aspel utilizan la base de datos FireBird. 

Para el caso de SAE la base de datos tiene una estructura mucho más decente, comparada con la estructura que tiene Aspel CAJA, aun así los nombres de las tablas no son tan claros y además no siempre resulta fácil lidiar con sus más de 150 Tablas. 

ASi que aqui ire agregando los nombres de las tablas más cpmunes usadas dentro de Aspel SAE:


De entrada las tablas contiene tiene una terminación que se coincide con el número de empresa así que por default las tablas tendrán la terminación 01. 

PRODUCTOS E INVENTARIOS
INVE01
Contiene el catálogo e información como: clave, nombre, método de costeo existencias entre otro. En caso de usar el multialmacén estas existencias representan las existencias globales de la empresa, es decir suman las existencias de cada almacén, para conocer las existencia de cada almacén cuando se hace uso del multialmacen se debe consultar la tabla (en cuanto recuerde el nombre lo actualiza pero es algo así como multi-).
INVE_CLIB01
Contiene los campos libres que se usa para el catálogo de productos estos campos suelen usarse para almacenar información adicional de productos como puede ser si ficha técnica u otros detalles. 



PAGOS Y CUENTSA POR COBRAR
CUEN_M02
Contiene información respecto al pago que nos han realizado nuestros clientes.

sábado, 26 de diciembre de 2015

Conexión de FireBird desde .NET (unable to complete network request to host)


Firebird es un gestor de base de datos que ha ganado popularidad y que en lo personal me gusta bastante, pues es muy ligero así que decidí hacer algunas pruebas con .NET y al principio resulto bastante complicado encontrar la información para conexión remota pero después de varias horas logré realizar la conexión 

Aquí les dejo una lista de pasos que deben realizar para poder conectarse desde .NET. Los primeros pasos son para configurar el servidor Firebird, y permitir atender peticiones provenientes de la red. 


En esta entrada mencionare los pasos que se requieren para realizar una conexión a una base de datos remota con el servidor de base de datos Firebird. 

1.-Instalar el Servidor Firebird (Super Clasic o Super Server) 

2.-Verificar que FireBbird se ejecute como un servicio

3.-Modificar el archivo de configuración, debemos descomentar las siguientes lineas:

  RemoteServiceName=gds_db
  RemoteServicePort=3050

4.-Crear un alias de la base de datos ( esto se hace en el archivo aliases.config) 

     MiAliasDeBaseDeDatos = C:\directorio\base.bdf
    
5.-Agregar(si aún no existe) una regla en el firewall de Windows para permitir la conexión al puerto 3050 (TCP)

6.- Reiniciar el servicio de Firebird Server (no confundir con Firebird Guardian) 


Con esto deberemos estar listos para conectarnos, de manera remota,  a nuestro servidor de base de 


Ahora para poder conectarnos desde .NET (en mi caso en particular uso C#) debemos realizar los siguientes pasos 

    1- Obtener el proveedor de datos nativo de FireBird 
         
        La manera más sencilla de instalarlo es desde la Consola del Administrador de Paquetes de Visual Estudio.

         Herramientas>>Administrador de Paquetes de Biblioteca>>Consola del Administrador de Paquetes. 

        En la consola que se mostrará (parte inferior) escribimos 

        Install-Package FirebirdSql.Data.FirebirdClient
      
       Esperamos a que termine la instalación que no suele tardar más de dos minutos y ahora ya podemos incluir el espacio de nombres en los archivos que sean necesarios 

       using FirebirdSql.Data.FirebirdClient;


    2.- Crear la cadena de conexión,

        private void testConnection()
       {
            string strCnn = "data source=192.168.0.2; initial catalog=MiAliasDeBaseDeDatos;user id=SYSDBA;password=masterkey;port number=3050"

           FbConnection cnn = new FbConnection();
           cnn.ConnectionString = strCnn;
    
            try
            {
                cnn.Open();
                cnn.Close();
                MessageBox.Show("Conexión Exitosa","Información");
            }
            catch (Exception er)
            {
                MessageBox.Show("Error al tratar de abrir la base dedatos. " + er.Message.ToString(), "Error");
            }

}