TeraBIThia

31/10/07

Díalogos para trabajar con cadenas de conexión

Archivado en: Uncategorized — crisfervil @ 2:00 pm

Estoy trabajando en una aplicación que requiere que el usuario introduzca una cadena de conexión. ¿Qué opciones tengo?

1 – Poner una caja de texto y dar por hecho que el usuario conoce todas las claves que puede utilizar en la cadena, y se desenvuelve tranquilamente en el infierno de las cadenas de conexión.

2 – Poner la caja de texto anterior, y al lado un enlace a http://www.connectionstrings.com/

image

3 – Usar el diálogo que viene incluido en la api de OLEDB.

image

4- Usar el diálogo que usa el visual studio 2005 en la pestaña de servidores.

image

4 – Crear un archivo con la extensión udl y ejecutarlo con System.Diagnostics.Process.Start(nombreFichero)

image

Vamos a ver como se implementan opción 3 y 4, que son las interesantes.

Opción 3:

Este diálog es el que ofrece la API de OLEDB. La pega que tiene es que no es código administrado y no está pensado para ser usado con ADO.net.

Los providers que se muestran no son los que admite el modelo de datos de .net, y de echo, la clave provider generada por este diálogo, no es admitida por los providers de SQL y Oracle.

Vamos, que hay que usarlo, pero con cuidado.

Pasos para usarlo:

1º – Agregar al proyecto referencias a los objetos COM Microsoft ActiveX Data Objects 2.x Library y OLE DB Service Component 1.0 Type Library.

2º – Para mostrar el diálogo para generar una nueva cadena de conexión, usar este código:

// Crear referencia e instancia del diálogo
MSDASC.DataLinks mydlg = new MSDASC.DataLinks();
// Mostrar el diálogo y referenciar la conexión ADO devuelta
ADODB._Connection ADOcon = (ADODB._Connection) mydlg.PromptNew();
// Si se ha generado correctamente una coneción ADO...
if (ADOcon != null)
{
    // Mostramos su connectionString en 
    // la caja de texto
    txtConnectionString.Text = ADOcon.ConnectionString;
}

3º – Para mostrar el diálogo en modo edición, usar este otro:

// Crear referencia e instancia del diálogo
MSDASC.DataLinks mydlg = new MSDASC.DataLinks();
// Crear un objeto ADO Connection
ADODB.ConnectionClass conn = new ADODB.ConnectionClass();
// Plantarle la cadena de conexión
conn.ConnectionString = txtConnectionString.Text;
// Crear una instancia de tipo Object de la conexión
// para poder pasarla por referencia al diálogo
object oConn = (object)conn;
// Mostrar el diálogo
bool result = mydlg.PromptEdit(ref oConn);
// Si OK...
if (result)
{
    // Mostramos la ConnectionString del objeto ADO 
    // en la caja de texto
    txtConnectionString.Text = conn.ConnectionString;
}

Dejo por aquí este snippet que uso para eliminar la clave Provider de una ConnectionString. Puede venir bien.

using System.Data.Common;
private string RemoveProviderKey(string connectionString)
{
    // DBConnectionStringBuilder es una clase de System.Data.Common que
    // viene estupendamente para tratar cadenas de conexión
    DbConnectionStringBuilder csb = new DbConnectionStringBuilder();
    csb.ConnectionString = connectionString;
    // Eliminamos la clave "Provider"
    csb.Remove("Provider");
    // Devolvemos lo que queda
    return csb.ConnectionString;
}

Opción 4:

Este diálogo se encuentra en el ensamblado Microsoft.Data.ConnectionUI.Dialog.dll ubicado en la carpeta [Archivos de programa]\Microsoft Visual Studio 8\Common7\IDE\.

El inconveniente de usar este diálogo, es que este archivo es propiedad de Microsoft y no es redistribuible, con lo cual sólo podríamos usarlo en aplicaciones en las que sepamos que se encuentra instalado este componente (Este inconveniente siempre puede ser resuelto con el Reflector)

La ventaja, es que este componente es 100% código administrado es un ensamblado de .net y está pensado pas ser usado con ADO.net. De hecho, lo primero que seleccionamos antes de generar la cadena de conexión, es el proveedor que queremos utilizar.

Pues eso, al lío.

1º – Añadir la referencia  a Microsoft.Data.ConnectionUI.Dialog.dll en la ruta antes mencionada.

2º – Hacer un using de Microsoft.Data.ConnectionUI

3º – Usar el siguiente código:

// Instanciamos el diálogo...
// Hacemos using, porque es necesario hacer un dispose al final
using (DataConnectionDialog dlg = new DataConnectionDialog())
{
    // Cargar en el diálogo los providers disponibles en el sistema
    DataSource.AddStandardDataSources(dlg);
    // Mostrar el diálogo
    if (DataConnectionDialog.Show(dlg) == DialogResult.OK)
    {
        // Aquí asignaríamos dlg.ConnectionString a nuestra caja de texto
        MessageBox.Show(dlg.ConnectionString);
    }
}

Si preferimos mostrar el diálogo de edición usamos el mismo código, con algunas modificaciones:

// Instanciamos el diálogo...
// Hacemos using, porque es necesario hacer un dispose al final
using (DataConnectionDialog dlg = new DataConnectionDialog())
{
    // Cargar en el diálogo los providers disponibles en el sistema
    DataSource.AddStandardDataSources(dlg);
    // Indicar el DataSource
    dlg.SelectedDataSource = DataSource.SqlDataSource;
    // Indicar cuál sera el provider a usar 
    // En este caso usaremos SQL Server
    dlg.SelectedDataProvider = DataProvider.SqlDataProvider;
    // la cadena que vayamos a editar
    // Lo suyo sería asignar el valor contenido en nuestra
    // caja de texto
    dlg.ConnectionString = "Server=myServerAddress;" +
                            "Database=myDataBase;Uid=myUsername;Pwd=myPassword;";
    // Mostrar el diálogo
    if (DataConnectionDialog.Show(dlg) == DialogResult.OK)
    {
        // Aquí asignaríamos dlg.ConnectionString a nuestra caja de texto
        MessageBox.Show(dlg.ConnectionString);
    }
}

 

 Referencias:

http://www.mztools.com/articles/2007/mz2007011.aspx

http://support.microsoft.com/kb/286189/EN-US/

Crossposted from crisfervil.com

11/10/07

TestDriven.net, Nunit y los archivos de configuración.

Archivado en: Uncategorized — crisfervil @ 2:06 pm

Para especificar archivo de configuración a usar en los test de Nunit:

1 – Menú Project/Edit…

2 – En el diálogo, en el campo “Configuration File Name” indicar el archivo a usar.

Si por el contrario, usamos la herramienta TestDriven.net, para ejecutar las pruebas directamente desde Visual Studio, el archivo de configuraciones debe encontrarse en el mismo directorio en el que se encuentra el ensamblado, y debe llamarse igual, pero con la extensión “config”.

Entonces, tedríamos dos opciones:

Bien, establecer, dentro del explorador de soluciones,  en las propiedades del archivo de configuración la propiedad “Copy to Output Directory” a “Copy always” (Sólo funciona con VS 2005)

o bien agregar un post-build command en las propiedades del proyecto (muy recomendable si el config a usar no se llama igual que el ensamblado o si trabajamos con VS 2003).

El comando a agregar seria:

copy “$(ProjectDir)TEST.config” “$(TargetPath).config”

Si alguno sabe como indicarle al TestDriven.net que no compile cada vez que inicia una prueba, que lo ponga en un comentario, o me lo mande al mail, por favor.

Fuente: http://weblogs.asp.net/nunitaddin/archive/2006/06/…

Crossposted from crisfervil.com

02/10/07

MarshalByRefObject y Remoting

Archivado en: Uncategorized — crisfervil @ 9:38 pm

La clase MarshalByRefObject permite a sus herederas exponer propiedades y métodos fuera de los límites de la aplicación.

Y cuáles son los límites de la aplicación?

El dominio de la aplicación es un trozo de memoria, o más bien de sistema operativo en el que se ejecuta una aplicación. Los objetos de la misma aplicación exponen sus propiedades y métodos directamente por encontrarse dentro del mismo dominio, pero si necesitaramos acceder a las variables de otra aplicación, esto no sería posible, por encontrarse fuera del dominio.

Es justamente en este contexto multidominio, donde aparece la clase MarshalByRefObject . Esta clase permite exponer y acceder a clases fuera del dominio de nuestra aplicación. Y “fuera” puede ser en la misma máquina o en otra distinta.

Lo que hace falta para exponer clases con Remoting.

- Un servicio o aplicación ejecutando que hagan de servidor.

- Una biblioteca de clases, o ejecutable, con las clases a exponer.

- Una aplicación cliente que consuma los servicios.

Como es natural, todo puede estar distribuido, en máquinas distintas, o en el mismo equipo.

Práctica:

En una solución de visual studio:

image 
Estructura de la solución.

Crear un proyecto ClassLibrary llamado PepitoSLLibrary que contendrá la biblioteca de clases expuesta.

Crear una clase pública Clientes, que herede de MarshalByRefObject .

public class Clientes: MarshalByRefObject
{
    private string _nombre;
    public string Nombre
    {
        get { return _nombre; }
        set { _nombre = value; }
    }
    public string Saludar()
    {
     string path =       System.Reflection.Assembly.GetCallingAssembly().Location;
     return String.Format("Hola {0}. Estoy en {1}",_nombre, path);
    }
}

Crear un proyecto Console Application llamado PepitoSLServices que será el programa en ejecución en el servidor que expondrá los servicios a través de remoting.

Agregar referencia al proyecto PepitoSLLibrary.

Los servicios de Remoting se pueden configurar en línea, especificando las propiedades en el código, o usando un archivo de configuración. Nosotros lo haremos de la segunda manera ya que es lo más flexible y lo mas elegante.

Añadiremos pues, un archivo de configuración services.config al proyecto PepitoSLServices. Escribiremos lo que sigue:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="tcp" port="8000" />
      </channels>
      <service>
        <wellknown mode="Singleton"            type="PepitoSLLibrary.Clientes, PepitoSLLibrary"
           objectUri="Clientes" />
      </service>
    </application>
  </system.runtime.remoting>
</configuration>

En las propiedades el archivo de configuración, establecer la propiedad Copy to Output Directory a “Always” para que copie el archivo en la carpeta del exe.

Lo siguiente, levantar los servicios.

Escribir el siguiente código en el Program.cs de PepitoSLServices

class Program
{
  static void Main(string[] args)
  {
    RemotingConfiguration.Configure("services.config",true);
    Console.WriteLine("Servicios levantados.Presione enter para finalizar");
    Console.ReadLine();
  }
}

Crear un proyecto Cosole Application llamado PepitoSLFrontEnd que será el cliente que consumirá los servicios expuestos por el servidor.

Finalmente, en el FrontEnd tendremos que consumir los servicios.

Añadir referencia al proyecto PepitoSLLibrary.

Al igual que en el servidor, el cliente de Remoting se puede configurar por código, pero nosotros lo haremos por archivo de configuraciones.

Añadir al proyecto un archivo de configuración “services.config” con la propiedad Copy to Output Directory a “Always”.

Escribir el código de configuración del cliente:

<?xml version="1.0" encoding="utf-8" ?>
  <configuration>
    <system.runtime.remoting>
      <application name = "PepitoSL">
        <client>
          <wellknown
          type="PepitoSLLibrary.Clientes, PepitoSLLibrary"
          url="tcp://localhost:8000/Clientes"/>
        </client>
        <channels>
          <channel ref="tcp" port="0"/>
        </channels>
      </application>
    </system.runtime.remoting>
  </configuration>

Copiar el siguiente código al Program.cs:

class Program
{
    static void Main(string[] args)
    {
      RemotingConfiguration.Configure("services.config",true);
      Clientes clientesService = new Clientes();
      clientesService.Nombre = "Cristhian";
      Console.WriteLine(clientesService.Saludar());
      Console.WriteLine("Presione enter para finalizar");
      Console.ReadLine();
    }
}
}

Configurar la solución para que al ejecutar, inicie las dos consolas; PepitoSLServices y PepitoSLFrontEnd.

image

Y finalmente, ejecutar, para ver lo que pasa.

Este es el resultado:

La consola del servidor:

image

La consola del cliente:

image

He pueso que el servicio devuelva la ruta del CallingAssembly para demostrar que no hay trampa ni cartón. Si comentáramos la línea de configuración de RemotingServices en el cliente, estaríamos instanciando la clase Clientes en el cliente; y el calling assembly sería otro.

image

Fuentes:
- MSDN Library
- techmentors.net 

Código de ejemplo

Crossposted from crisfervil.com

Blog de WordPress.com.