none
Cadena de conexión múltiple app.confg C# y SqlSever RRS feed

  • Pregunta

  • Que tal a todos,

    Estoy por terminar una aplicación de escritorio con windows Forms C# y como gestor de base de datos estoy usando SqlServer.

    Para la conexión a la base de datos estoy usando la app.config y cargo las instancias de Sql en un combo box de la siguiente forma:

    private void FormConexion_Load(object sender, EventArgs e)
            {
                cmbServer.Items.Add(".");
                cmbServer.Items.Add("(local)");
                cmbServer.Items.Add(@".\SQLEXPRESS");
                cmbServer.Items.Add(string.Format(@"{0}\SQLEXPRESS", Environment.MachineName));
                cmbServer.Items.Add("3");
            }

    El botón conectar:

            private void btnConection_Click(object sender, EventArgs e)
            {
                string connectionString = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};", cmbServer.Text, txtDb.Text, txtUser.Text, txtPassword.Text);
                try
                {
                    SqlHelper helper = new SqlHelper(connectionString);
                    if (helper.IsConnection)
                        MessageBox.Show("Connection has been succeeded.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }


    Y el botón para salvar la conexion:

    private void btnSave_Click(object sender, EventArgs e)
            {
                //Set connection string
                string connectionString = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};", cmbServer.Text, txtDb.Text, txtUser.Text, txtPassword.Text);
                try
                {
                    SqlHelper helper = new SqlHelper(connectionString);
                    if (helper.IsConnection)
                    {
                        AppSetting setting = new AppSetting();
                        setting.SaveConnectionString("cn", connectionString);
                        MessageBox.Show("Your connection string has been successfully saved.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        Application.Restart();
                    }
                }
    
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }


    Mi app.config:

        <connectionStrings>
            <add name="cn" connectionString="Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=123@qaz?;" providerName="System.Data.SqlClient"/>
        </connectionStrings>

    Porque lo estoy haciendo de esta forma, bueno la aplicación la estarán usando diferentes entidades cada entidad tiene su propio servidor pero la base de datos tiene la misma arquitectura en cada entidad.

    El combo box se encarga de mostrar la instancia Sql que encuentra en el equipo, pero la forma en que lo muestra es:

    192.xxx.xx.xx\Entidad_1

    Lo que quiero hacer es mostrar en el combo box las 23 entidades pero no que aparezca el nombre de la instancia como tal si, no que muestre solo:

    • Entidad I
    • Entidad II
    • Entidad III
    • Entidad IV
    • Entidad IV
    • localhost
    • .

    Ya que cada usuario tiene sus credenciales de inicio de sesión, además me sirve a mi como administrador conectarme a una instancia de producción y otra de prueba en local sin estar cambiando la cadena de conexión, pero realmente no se si se puede hacer esto y como puedo hacerlo?

    Por ejemplo esto seria lo que cargaría en el ComboBox:

    private void FormConexion_Load(object sender, EventArgs e)
            {
                cmbServer.Items.Add("ENTIDAD I");
                cmbServer.Items.Add("ENTIDAD II");
                cmbServer.Items.Add("ENTIDAD III");
                cmbServer.Items.Add("ENTIDAD IV");
                cmbServer.Items.Add("ENTIDAD V");
                cmbServer.Items.Add("ENTIDAD VI");
                cmbServer.Items.Add(".");
                cmbServer.Items.Add("(local)");
                cmbServer.Items.Add(@".\SQLEXPRESS");
                cmbServer.Items.Add(string.Format(@"{0}\SQLEXPRESS", Environment.MachineName));
                cmbServer.Items.Add("3");
            }

    Pero como le paso la instancia real a cada Item seleccionado por el usuario?

    Espero me puedan ayudar con este problema.

    DS


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    lunes, 23 de noviembre de 2020 4:17

Respuestas

  • Una pregunra la clases internal donde la tengo que agregar?

    Da igual, no tiene nada que ver en este asunto. La puse internal por poner un ejemplo, pero si la quieres hacer private o public es indiferente a los efectos del tema de usarla para los items del combo.

    Una clase internal se puede ubicar en el mismo sitio que cualquier otra clase, es decir puede ir en su propio archivo dentro del mismo ensamblado, igual que si fuese pública (pero no puede ir en un ensamblado diferente mientras que la public sí que puede). También se puede anidar dentro de la clase que la usa (en tu caso sería el Form), pero en este caso normalmente suele ser preferible marcarla como private en lugar de internal. Pero nada de todo esto afecta al hecho de que uses una clase para encapsular los items del combo; a estos efectos da igual que la clase sea private, internal o public, con tal de que la ubiques en un sitio donde sea visible al código que la usa.

    Ah, por cierto, en C# si declaras una clase y no le pones nada, por defecto es internal. Así que si estás declarando tus clases poniendo simplemente "class loQueSea", en realidad todas ellas son iguales que si les hubieras puesto "internal class loQueSea".

    • Marcado como respuesta Dany Solis lunes, 23 de noviembre de 2020 20:22
    lunes, 23 de noviembre de 2020 19:36
    Moderador
  • En un combo box de Windows forms, los items no tienen por qué ser strings. En realidad son de tipo object, y el combo muestra en pantalla el resultado de llamar a .ToString sobre cada object.

    Eso te permite definir una clase que tenga, por ejemplo, dos propiedades tales como Descripción e Instancia:

    Internal class ItemParaCombo
    {
        public string Descripcion { get; set; }
        public string Instancia { get; set; }
        public override string ToString() { return Descripcion; }
    }

    Entonces, cargas el combo con items de este tipo:

    cmbServer.Items.Add(new ItemParaCombo {Descripcion="ENTIDAD 1", Instancia=".\\SqlExpress" } );

    Y luego, cuando necesites recuperar la instancia seleccionada, la tomas del SelectedItem mediante un "cast":

    string instanciaSeleccionada = ((ItemParaCombo)(cmbServer.SelectedItem)).Instancia;

    Por cierto, una recomendación: No uses string.Format para ensamblar tu cadena de conexión a partir de sus partes. En su lugar, utiliza la clase SqlConnectionStringBuilder. Le pasas los datos en sus propiedades, y ella te devuelve el ConnectionString. Tiene la ventaja de que garantiza que la cadena es correcta, y que "escapa" debidamente cualquier carácter especial que haya dentro de los datos que le pasas, y que daría errores o incluso sería un riesgo de seguridad si lo concatenases en la cadena.

    lunes, 23 de noviembre de 2020 8:15
    Moderador

Todas las respuestas

  • En un combo box de Windows forms, los items no tienen por qué ser strings. En realidad son de tipo object, y el combo muestra en pantalla el resultado de llamar a .ToString sobre cada object.

    Eso te permite definir una clase que tenga, por ejemplo, dos propiedades tales como Descripción e Instancia:

    Internal class ItemParaCombo
    {
        public string Descripcion { get; set; }
        public string Instancia { get; set; }
        public override string ToString() { return Descripcion; }
    }

    Entonces, cargas el combo con items de este tipo:

    cmbServer.Items.Add(new ItemParaCombo {Descripcion="ENTIDAD 1", Instancia=".\\SqlExpress" } );

    Y luego, cuando necesites recuperar la instancia seleccionada, la tomas del SelectedItem mediante un "cast":

    string instanciaSeleccionada = ((ItemParaCombo)(cmbServer.SelectedItem)).Instancia;

    Por cierto, una recomendación: No uses string.Format para ensamblar tu cadena de conexión a partir de sus partes. En su lugar, utiliza la clase SqlConnectionStringBuilder. Le pasas los datos en sus propiedades, y ella te devuelve el ConnectionString. Tiene la ventaja de que garantiza que la cadena es correcta, y que "escapa" debidamente cualquier carácter especial que haya dentro de los datos que le pasas, y que daría errores o incluso sería un riesgo de seguridad si lo concatenases en la cadena.

    lunes, 23 de noviembre de 2020 8:15
    Moderador
  • En un combo box de Windows forms, los items no tienen por qué ser strings. En realidad son de tipo object, y el combo muestra en pantalla el resultado de llamar a .ToString sobre cada object.

    Eso te permite definir una clase que tenga, por ejemplo, dos propiedades tales como Descripción e Instancia:

    Internal class ItemParaCombo
    {
        public string Descripcion { get; set; }
        public string Instancia { get; set; }
        public override string ToString() { return Descripcion; }
    }

    Entonces, cargas el combo con items de este tipo:

    cmbServer.Items.Add(new ItemParaCombo {Descripcion="ENTIDAD 1", Instancia=".\\SqlExpress" } );


    Una pregunra la clases internal donde la tengo que agregar?

    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    lunes, 23 de noviembre de 2020 19:12
  • Una pregunra la clases internal donde la tengo que agregar?

    Da igual, no tiene nada que ver en este asunto. La puse internal por poner un ejemplo, pero si la quieres hacer private o public es indiferente a los efectos del tema de usarla para los items del combo.

    Una clase internal se puede ubicar en el mismo sitio que cualquier otra clase, es decir puede ir en su propio archivo dentro del mismo ensamblado, igual que si fuese pública (pero no puede ir en un ensamblado diferente mientras que la public sí que puede). También se puede anidar dentro de la clase que la usa (en tu caso sería el Form), pero en este caso normalmente suele ser preferible marcarla como private en lugar de internal. Pero nada de todo esto afecta al hecho de que uses una clase para encapsular los items del combo; a estos efectos da igual que la clase sea private, internal o public, con tal de que la ubiques en un sitio donde sea visible al código que la usa.

    Ah, por cierto, en C# si declaras una clase y no le pones nada, por defecto es internal. Así que si estás declarando tus clases poniendo simplemente "class loQueSea", en realidad todas ellas son iguales que si les hubieras puesto "internal class loQueSea".

    • Marcado como respuesta Dany Solis lunes, 23 de noviembre de 2020 20:22
    lunes, 23 de noviembre de 2020 19:36
    Moderador
  • Gracias por la explicación y la ayuda con esto tengo para seguir con lo que pretendo.

    Saludos

    DS


    Aprendiz de todos maestro de nadie. Saludos desde Cd. Juarez Chihuahua Mexico. DS.

    lunes, 23 de noviembre de 2020 20:23
  • Hola

    Alguna actualización sobre tu consulta?

    Saludos

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

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.

    Si tiene algún cumplido o reclamo sobre el soporte de MSDN sientase en la libertad de contactar  MSDNFSF@microsoft.com. 

    viernes, 27 de noviembre de 2020 17:14
    Moderador