20 de enero de 2015

C# - Oracle: Conexión

Se trabaja este ejemplo sobre Oracle 11g Standart Edition, lo primero sera abrir el SQL Plus para crearnos un usuario sobre la base de datos, el nombre de la base de datos que usare en este ejemplo es Lingonet.


Ahora se muestra la secuencia para crear un usuario, asignarle los tablespace y otorgarle permisos sobre la base de datos, aquí puedes tu asignarle los roles que te hayas creado,para este ejemplo el usuario sera blogger y el password blogger, esto lo puedes hacer tambien desde Enterprise Manager, lo encuentras en tu instalación de Oracle en la dirección https://localhost:1158/em

con el usuario creado ahora abrimos el Oracle SQL Developer y creamos una nueva conexion a la base de datos Lingonet

Esta es la pantalla que creara la conexión

La vista de la conexión ya creada

Ahora sobre la conexión, se debe buscar el icono de Tables, dar click derecho y seleccionar New Table...

Creamos la tabla con los siguientes campos y la denominamos BLOGTABLE

a la tabla recién creada le asignamos los siguientes registros

Suficiente con Oracle, nos vamos al Visual Studio y creamos un nuevo proyecto, en este ejemplo utilizare un proyecto de Windows Forms, lo primero sera agregar una referencia a nuestro proyecto

Nos vamos a la instalación de Oracle, que por defecto esta en C:\app y buscamos la dll: Oracle.DataAccess.dll en la siguiente ubicación:
C:\app\Pc-User\product\11.2.0\dbhome_1\ODP.NET\bin\2.x
una vez ubicada la libreria, damos click en Add para que se agregue como referencia al proyecto

Ahora toca buscar el tnsnames.ora, este archivo configura los alias de las cadenas de conexión a distintas bases de datos, tipicamente se encuentra en la siguiente ruta
C:\app\Pc-User\product\11.2.0\dbhome_1\NETWORK\ADMIN

y copiamos la cadena de conexión con identificador LINGONET como se muestra

Conexión Estática

Le llamo estática porque todos los usuarios se conectaran con la misma identificación, por ejemplo: 
  • Carlos el de contabilidad se conectara con user=bloggger y password=blogger,
  • Maria de RRHH se conectara con user=blogger y password=blogger,
  • Mendoza de Bodega se conectara con user=blogger y password=blogger,
  • Monica de publicidad de conectara con user=blogger y password=blogger,
cualquier fulanito que requiera acceso a la base de datos se conectara con user=blogger y password=blogger, ya captan la idea? Bueno, toca crear el connectionstring en el app.config de la aplicación y pegar el contenido copiado desde tsnnames.ora


a nuestro formulario que se agrego por defecto al crear el nuevo proyecto de Windows Forms App, le agregamos un botón y sobre el evento click del botón escribimos este código, listo !!!

Librerias
using Oracle.DataAccess.Client;
using System.Configuration;

Evento Click
private void button1_Click(object sender, EventArgs e){

    string oradb = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;
            OracleConnection conn = new OracleConnection();
            conn.ConnectionString = oradb;
            try{
                conn.Open();
                MessageBox.Show(conn.State.ToString());
            }
            catch (Exception ex){ MessageBox.Show(ex.Message);  }
        }

Conexión Dinámica

Le llamo dinámica porque ahora el usuario que quiera realizar operaciones sobre la base de datos deberá especificar sus credenciales, cabe mencionar que cada usuario(persona, departamento, sucursal, etc) puede tener su propio esquema para trabajar, por tanto deben especificar su user y password a fin de acceder a "su colección de objetos de la base de datos"

para tal fin lo primero sera modificar la connectionstring que tenemos en el app.config así pues pasara de esto 

<connectionStrings>
<add name="conexion" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))
(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = lingonet)));User Id=blogger;Password=blogger;"/>
</connectionStrings>

a esto(se elimina la especificación del usuario y del password y en vez de ello se agregaran las credenciales a la cadena de conexión):

<connectionStrings>
<add name="conexion" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))
(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = lingonet)));User Id={0};Password={0};"/>

</connectionStrings>

con el cambio anterior cada vez que un usuario quiera conectarse a la base de datos deberá proveer al sistema con sus credenciales de lo contrario simplemente no accederá, ahora viene la parte del código, la parte de compartir la información de usuario entre los formulario de nuestra aplicación -  ojo, vamos a compartir la información entre formularios no a pasar información de un formulario a otro- podemos hacerlo de dos maneras:

1. Pasar las credenciales de formulario a formulario(Funcional pero no recomendada)

Lo que vamos a hacer es pasar la cadena de conexion como un parametro de un formulario a otro, para ello primero vamos a agregar un nuevo formulario que hara las veces de Login para que el usuario ingrese sus credenciales a fin de obtener acceso a la base de datos Lingonet


y ademas modificaremos nuestro formulario que utilizamos en el ejemplo de conexión estática, le agregaremos un DataGridView para mostrar los datos de nuestra tabla BLOGTABLE


El código para el formulario Login es el siguiente:

private void btn_Click(object sender, EventArgs e){

            string username = txtUsername.Text.Trim();
            string password = txtPassword.Text.Trim();
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) {
                MessageBox.Show("El usuario y el password son datos requeridos");
            }
            else{ Validar(username, password); }
            }

private void Validar(string username, string password) {

string CadenaConexion = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;
CadenaConexion = string.Format(CadenaConexion, username, password);
          
            try{          
                Form1 formulario = new Form1();
                formulario.cnn = CadenaConexion;
                formulario.ShowDialog();
                this.Hide();
            }
            catch (Exception ex){ MessageBox.Show(ex.Message); }
         
          }

y el código de Form1 es el siguiente:

public partial class Form1 : Form{
        public string cnn;
        public Form1(){
             InitializeComponent(); }

private void button1_Click(object sender, EventArgs e){

            try{
               
                DataTable dt = new DataTable();
                OracleCommand cmd = new OracleCommand();
                cmd.Connection = Conectar();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "select * from BLOGTABLE";
                OracleDataAdapter da = new OracleDataAdapter();
                da.SelectCommand = cmd;
                da.Fill(dt);
                dataGridView1.DataSource=dt;
             }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }

private OracleConnection Conectar() {
            OracleConnection conn = new OracleConnection();
            conn.ConnectionString = cnn;
            tryconn.Open(); }
            catch (Exception ex){
               MessageBox.Show(ex.Message);
            }
            return conn;

        }

2. Utilizar el Patrón Singleton

Al haber un patrón de por medio sabes que si quieres aaceder a algo global estara alli, y no en variables desperdigadas por cualquier lado, agregamos una nueva clase al proyecto con nombre Registro.cs asi

namespace WindowsFormsApplication1{
    public class Registro{
        private static readonly Registro Autorizacion = new Registro();
        public string Username { get; set; }
        public string Password { get; set; }
        private  Registro(){}
        public static Registro Instance{
            get{
                return Autorizacion;
            }
        }
    }

}

el cambio anterior implica modificar nuestro formulario de Login asi:

private void btn_Click(object sender, EventArgs e){

            string username = txtUsername.Text.Trim();
            string password = txtPassword.Text.Trim();
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) {
                MessageBox.Show("El usuario y el password son datos requeridos");
            }
            else{ Validar(username, password); }
            }

        private void Validar(string username, string password) {
            Registro.Instance.Username = username;
            Registro.Instance.Password = password;
          
            try{
                Form1 formulario = new Form1();
                formulario.ShowDialog();
                this.Hide();
            }
            catch (Exception ex){ MessageBox.Show(ex.Message); }
         
          }

y por ultimo muestro como queda el codigo para el formulario que muestra los datos:

private void button1_Click(object sender, EventArgs e){

            try{
                DataTable dt = new DataTable();
                OracleCommand cmd = new OracleCommand();
                cmd.Connection = Conectar();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "select * from BLOGTABLE";
                OracleDataAdapter da = new OracleDataAdapter();
                da.SelectCommand = cmd;
                da.Fill(dt);
                dataGridView1.DataSource=dt;
             }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }

        private OracleConnection Conectar() {
            string username = Registro.Instance.Username;
            string password = Registro.Instance.Password;
            string CadenaConexion = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;
            CadenaConexion = string.Format(CadenaConexion, username, password);
            OracleConnection conn = new OracleConnection();
            conn.ConnectionString = CadenaConexion;
            try{
                conn.Open();
            }
            catch (Exception ex){
               MessageBox.Show(ex.Message);
            }
            return conn;
        }