Archivo por meses: marzo 2019

Problemas con IntelliSense en VS2019 con el editor de VB

Pues eso… que te quería seguir contando las cosas buenas de Visual Studio 2019, pero… hay que decirlo todo, y lo malo es que en la fecha en que te cuento esto, no creo que lo vayan a solucionar en la versión final que estará el próximo martes día 2 de abril. Sad smile

Te cuento lo que me pasa y voy a usar el texto con el bug que he publicado hoy en la comunidad de desarrolladores de Visual Studio (Developer Community). Te dejo el enlace por si te parece la votes a ver si así le hacen más caso (siempre hacen caso a las cosas que cuento por ahí, pero… algunas no las solucionan rápidamente… será porque es Visual Basic… y ya sabes que algunos nos consideran desarrolladores de clase B… Angry smile

Nota del 05/Abr/19

Pues resulta que esto mismo ocurre en C# pero en casos concretos (Completion gets in the way attempting to line up arguments) y por tanto han cerrado la incidencia por estar duplicada, y según cuentan ya está solucionado en VS 16.1 Preview 2.

Aquí va el texto y las capturas (más abajo está la traducción al inglés):

 

Problemas con IntelliSense en VS2019 y VB

Con Visual Studio 2019 (RC.4) da muchísimos problemas con IntelliSense y Visual Basic (con C# no ocurre lo mismo).

Comento dos de los que me suelen ocurrir habitualmente (tanto que estoy pensando dejar de usar el VS2019 al menos para los proyectos de VB) es un verdadero «desastre» hacer ciertas cosas… más o menos habituales.

Por ejemplo:
En las declaraciones de los métodos de evento me gusta poner los parámetros del método en líneas separadas (para que se vean mejor los controles que utilizan ese método) y lo que suelo hacer es poner el cursor antes del segundo parámetro (después de la coma) para pulsar la tecla ENTER, cuando lo hago y se cambia de línea se muestra la ventana de IntelliSense (ver la captura de figura 1), si a continuación pulso la tecla TAB para agrandar la indentación, el editor añade la definición de la ventana de IntelliSense (ver la captura de la figura 2) en la que se ve que añade ByRef.

Figura 1.
Figura 2.

Lo mismo ocurre cuando me pongo al principio de una línea con código y pulso ENTER para escribir en la línea anterior, IntelliSense muestra en el principio de la línea el método que estoy usando en ese control (ver la captura de la figura 3), nuevamente si pulso TAB (que en este caso no es la acción que yo querría hacer, pero para demostrar el mismo fallo) se añade erróneamente lo que haya seleccionado en la ventana emergente de IntelliSense (ver captura de la figura 4) y si no pulso la tecla TAB y quiero mover el cursor a la línea anterior (la que se ha creado al pulsar ENTER) tengo que pulsar la tecla ESC para que quite la ventana de IntelliSense.

Figura 3.
Figura 4.

Y como comento al principio esta es una acción muy, muy habitual… y es «frustrante» escribir código de esta manera…

Ese último error (pulsar INTRO al principio de una línea con código) también ocurre con los comentarios, y en el ejemplo que he hecho (un comentario encima de una asignación a la propiedad TEXT de un Label), al pulsar la tecla ENTER la ventana de IntelliSense muestra la misma propiedad que la indicada en la figura 4 tal como se puede ver en la captura de la figura 5.

Figura 5.

 

Esto con Visual Studio 2017 no ocurre.

En C# he probado los dos ejemplos que acabo de comentar y no ocurre así.

Realmente es algo que deberían solucionar, ya que si el producto final que saldrá al mercado el próximo 2 de abril tiene este tipo de BUG,, sería lamentable.

Gracias.
Guillermo

 

A ver si lo solucionan rápido… que es un rollo que ocurra eso…

 

Nos vemos.

Guillermo

 

Y como también se lo traducido al inglés (eso lo suelen hacer ellos, pero… para adelantar tiempo. Winking smile

 

Problems with IntelliSense in VS2019 and VB

With Visual Studio 2019 (RC.4) it gives many problems with IntelliSense and Visual Basic (with C# the same thing does not happen).

I mention two of those that usually happen to me habitually (so much so that I’m thinking about stopping using VS2019 at least for VB projects) it’s a real «disaster» to do certain things … more or less usual.

For example:
In the declarations of the methods of event I like to put the parameters of the method in separate lines (so that the controls that use that method are seen better) and what I usually do is put the cursor before of the second parameter (after the comma) to press the ENTER key, when I do it and the line is changed the IntelliSense window is displayed (see the capture in Figura 1), if I then press the TAB key to enlarge the indentation, the editor adds the definition of the IntelliSense window (see the capture in Figura 2) in which it is seen that it adds ByRef.

The same thing happens when I put myself at the beginning of a line with code and pulse ENTER to write on the previous line, IntelliSense shows at the beginning of the line the method I am using in that control (see the capture in Figura 3), again if I press TAB (which in this case is not the action that I would like to do, but to show the same fault) it is wrongly added what you have selected in the IntelliSense pop-up window (see the capture in Figura 4) and if not I press the TAB key and I want to move the cursor to the previous line (the one that was created when pressing ENTER) I have to press the ESC key to remove the IntelliSense window.

And as I said at the beginning this is a very, very usual action … and it is «frustrating» to write code in this way …

That last error (press ENTER at the beginning of a line with code) also occurs with the comments, and in the example that I have made (a comment above an assignment to the TEXT property of a Label), by pressing the ENTER key the window of IntelliSense shows the same property as that indicated in the capture: Figure 4 as it can be seen in the capture of Figura 5.

 

This with Visual Studio 2017 does not happen.

In C # I have tried the two examples that I just commented and it does not happen that way.

It really is something that should be solved, because if the final product that will be released on April 2 has this type of BUG, it would be unfortunate.

Thank you.
Guillermo

Novedades (algunas) del IDE de Visual Studio 2019

Pues eso… a falta de una semana para que Microsoft libere la versión final de Visual Studio 2019 (el martes 2 de abril para ser concreto) te voy a explicar un par de cosillas que creo que debes saber para que no te pase lo que a mí… Winking smile

 

Lo primero, es lo primero… evitarte quebraderos de cabeza

Así que… y como te digo en el encabezado, si quieres evitarte quebraderos de cabeza nada más empezar con esta monería de Visual Studio (porque ha mejorado mucho con respecto al Visual Studio 2017), debes quitar una de las nuevas opciones que tiene esta versión.

Al menos si usas el VS2019 en un monitor grande (o de los que tienen mucha densidad de píxeles) lo primero que deberías hacer es ir al menú Herramientas (Tools), seleccionar Opciones (Options) y en la ventana que te muestra, en Entorno>General (Environmet>General) (ver la figura 1) quitar la marca de Optimizar la representación de las pantallas con densidades de píxeles distintas (Optimize rendering for screens with different pixel densities).

Una nueva opción de VS2019 que puede darte problemas... a mí me las ha dado...
Figura 1. Una nueva opción de VS2019 que puede darte problemas… a mí me las ha dado…

¿Por qué he quitado esa opción?

Te explico.

Yo uso el portátil (laptop) como equipo de desarrollo con un monitor grande con una resolución de 3840×2160 y ahí es donde uso el Visual Studio 2019 (y el VS2017) y al menos con la versión RC.3 (y también con la RC.4) me da problemas como ni siquiera poder cambiar el tamaño de los formularios y/o controles. Aparte que al mostrar las opciones del proyecto, la ventana se mostraba muy mal o cuando el cursor del ratón estaba sobre un texto y se muestra IntelliSense no dejaba escribir salvo que ocultaras la ventana emergente (de IntelliSense)… y más cosas de las que ahora mismo no me acuerdo, pero cuando me vengan a la memoria te las contaré…

Nota:

A ver… lo mismo tú no tienes los problemas que yo he tenido, solo te lo explico por si te pasan cosas raras cuando empieces a usar Visual Studio 2019.

El que avisa…

 

El coloreado del código de VB y C# ha cambiado

Esa es otra novedad con respecto a Visual Studio 2017 que nos puede facilitar la lectura del código (si quieres).

La figura 2 es una captura de Visual Studio 2017 con un código de Visual Basic. Este coloreado seguro que ya lo conoces.

El coloreado (clásico) de Visual Studio 2017
Figura 2. El coloreado (clásico) de Visual Studio 2017

En la figura 3 tienes la nueva versión del coloreado que trae Visual Studio 2019.

El coloreado (mejorado) de Visual Studio 2019
Figura 3. El coloreado (mejorado) de Visual Studio 2019

Pregunta: ¿No te gusta el nuevo coloreado de Visual Studio 2019?

Respuesta: Sí, me gusta, pero no me lo muestra así; lo veo como en la figura 2.

Esa característica la puedes cambiar en las opciones de configuración, concretamente en las opciones del editor de texto, ya sabes: Herramientas>Opciones y en la ventana de opciones selecciona Editor de Texto (Text Editor) y después Basic o C# (esta opción solo está disponible para esos dos lenguajes). A continuación marca la opción Usar colores mejorados para C# y Basic (Use enhanced colors for C# and VB) tal como puedes ver en la figura 4.

El coloreado mejorado del código se puede cambiar para usar el de las versiones anteriores
Figura 4. El coloreado mejorado del código se puede cambiar para usar el de las versiones anteriores

Nota:

Si te fijas en la figura 4, también hay opciones para colorear las expresiones regulares y otras mejoras.

 

Nueva pantalla de inicio de Visual Studio 2019

Para finalizar esta introducción a las mejoras (o cambios) del IDE de Visual Studio 2019 vamos a lo primero que nos mostrará Visual Studio al empezar: La pantalla de inicio.

La pantalla de inicio de Visual Studio 2019
Figura 5. La pantalla de inicio de Visual Studio 2019

Tal como puedes ver en la figura 5 la pantalla de inicio de VS 2019 ha cambiado, si no quieres cargar ningún proyecto, ni crear uno nuevo, puedes pulsar en el enlace mostrado en la parte inferior derecha: Continuar sin código (Continue without code).

Los proyectos mostrados están sincronizados con los que ya tuvieras en la ventana de inicio de Visual Studio 2017, incluso siguen sincronizados en los dos entornos, respetando también los que están anclados.

Lo único que no me gusta es la forma de crear nuevos proyectos, de eso te hablaré en otra ocasión. Además de que hecho en falta las noticias, que seguramente estarán en otra parte, pero por ahora no he dado con ellas, aparte de ir a el blog de los desarrolladores de Visual Studio.

 

Espero que te haya sido de utilidad. Esa es la idea (que no IDE) Winking smile

 

Nos vemos.
Guillermo

P.S.

Aquí te dejo unos enlaces, dos de ellos sobre lo primero que te he contado y que la gente de Visual Studio lo llama: Representación con reconocimiento del monitor (Per-monitor aware (PMA) rendering).

Si prefieres ver los artículos en inglés, al menos los publicados en docs.microsoft.com, puedes cambiar /es-es/ por /en-us/ (o viceversa) en la barra de direcciones.

Normalmente las traducciones al español son generadas automáticamente, pero mucho mejores que si las traduces con algunas herramientas de traducción, incluso la que incorpora Edge que se supone que es la misma que usa Microsoft en su sitio.

VarChar y NVarChar en SQL Server y MySQL el código para VB y C#

Pues eso… lo prometido es deuda y aquí tienes el código que te prometí del ejemplo correspondiente al post anterior (VarChar y NVarChar en SQL Server) para VB y C#.

Este código te permite comprobar que usando VARCHAR también puedes agregar caracteres especiales del idioma español: vocales acentuadas, eñes, etc.

En este ejemplo también uso dos bases de datos (en realidad 3), una de SQL Server y otra de MySQL en un servidor que está en la nube (en un hosting de Internet, concretamente en uno de Domitienda.com que es donde yo tengo mis sitios alojados). La tercera base es una de SLQ Server en mi servidor local (el de SQLEXPRESS).

El diseño del formulario y el código de VB y C#

Este es el formulario en modo de diseño (figura 1):

Figura 1. El formulario en modo de diseño.
Figura 1. El formulario en modo de diseño.

Nota:

En el código tienes la cadena de conexión para las bases de datos que están en «la web» y es posible que dejen de estar disponibles dentro de algún tiempo (no sé si una semana, un mes, un año o un día), así que… si quieres probarlo, usa cuanto antes el código del ZIP que te pondré al final o crea un proyecto a partir de lo que aquí te muestro.

El proyecto está creado con Visual Studio 2019 Preview 4.3 pero debería cargar también en Visual Studio 2017 y utiliza el .NET Framework 4.7.2.

El código para Visual Basic .NET

'------------------------------------------------------------------------------
' Prueba de los tipos de SQL VarChar y NVarChar                     (19/Mar/19)
' Usando base de SQL Server y MySQL
'
'
' (c) Guillermo (elGuille) Som, 2019
'------------------------------------------------------------------------------
Option Strict On
Option Infer On

Imports System.Data
Imports System.Data.SqlClient
' Versión de mysql.data.dll: Connector/Net 6.0.3.0
Imports MySql.Data.MySqlClient

Imports System.Linq


Public Class Form1

    Private inicializando As Boolean = True

    ''' <summary>
    ''' Para las primeras pruebas uso una base local
    ''' </summary>
    Private UsarBaseLocal As Boolean = True

    Private ServerName As String = ".\SQLEXPRESS"
    Private DatabaseName As String = "PruebaVarChar"
    Private UsuarioDB As String = "elGuille_info"
    Private PasswordDB As String = "VarChar_19"

    Private Tabla As String = "VarCharElGuille"
    ' Campos: Fecha, ConVarChar varchar(50), ConNVarChar nvarchar(50)
    ' en MySQL no hay NVARCHAR y uso TEXT(50)

    Private MaxFilas As Integer = 5

    ''' <summary>
    ''' La cadena de conexión a la base de datos
    ''' </summary>
    Private Function CadenaConexionSQL() As String
        ConectarSQL()

        Dim csb As New SqlConnectionStringBuilder

        csb.DataSource = ServerName
        csb.InitialCatalog = DatabaseName
        csb.UserID = UsuarioDB & "SQL"
        csb.Password = PasswordDB
        csb.IntegratedSecurity = False

        Return csb.ConnectionString
    End Function

    ''' <summary>
    ''' La cadena de conexión a la base de datos
    ''' </summary>
    Private Function CadenaConexionMySQL() As String
        If UsarBaseLocal Then Return "No hay base local de MySQL"

        ConectarMySQL()

        Dim csb As New MySqlConnectionStringBuilder

        csb.Server = ServerName
        csb.Database = DatabaseName
        csb.UserID = UsuarioDB & "My"
        csb.Password = PasswordDB

        Return csb.ConnectionString
    End Function


    ''' <summary>
    ''' Conectar a la base de datos de SQL Server
    ''' </summary>
    Private Sub ConectarSQL()
        If UsarBaseLocal Then
            ServerName = ".\SQLEXPRESS"
        Else
            ServerName = "sql3.servidoreswindows.net"
        End If
    End Sub

    ''' <summary>
    ''' Conectar a la base de datos de MySQL.
    ''' Siempre en remoto.
    ''' </summary>
    Private Sub ConectarMySQL()
        ServerName = "mysql1.servidoreswindows.net"
    End Sub


    ''' <summary>
    ''' Añadir el dato a la base de SQL Server
    ''' </summary>
    Private Function AñadirSQL() As String
        Dim sCon As String = CadenaConexionSQL()
        Dim sel = $"INSERT INTO {Tabla} (Fecha, ConVarChar, ConNVarChar) " &
                  $"VALUES('{DateTime.Now}', '{txtDato.Text}', '{txtDato.Text}')"

        Using con As New SqlConnection(sCon)
            Dim cmd As New SqlCommand(sel, con)

            Try
                con.Open()
                cmd.ExecuteNonQuery()
                con.Close()

                Return ""
            Catch ex As Exception
                Return $"ERROR: {ex.Message}"
            End Try
        End Using
    End Function

    ''' <summary>
    ''' Añadir el dato a la base de datos de MySQL
    ''' </summary>
    Private Function AñadirMySQL() As String
        If UsarBaseLocal Then Return "No hay base local de MySQL"

        Dim sCon = CadenaConexionMySQL()
        ' En MySQL he definido Fecha como varchar(20)
        Dim sel = $"INSERT INTO {Tabla} (Fecha, ConVarChar, ConNVarChar) " &
                  $"VALUES('{DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")}', '{txtDato.Text}', '{txtDato.Text}')"

        Using con As New MySqlConnection(sCon)
            Dim cmd As New MySqlCommand(sel, con)

            Try
                con.Open()
                cmd.ExecuteNonQuery()
                con.Close()

                Return ""
            Catch ex As Exception
                Return $"ERROR: {ex.Message}"
            End Try
        End Using
    End Function

    ''' <summary>
    ''' Mostrar los datos de la base de SQLServer
    ''' </summary>
    Private Function MostrarDatosSQL(ByRef dt As DataTable) As String
        Dim orden = If(chkOrden.Checked, "DESC", "ASC")
        Dim sel = $"SELECT TOP ({MaxFilas}) * FROM {Tabla} ORDER BY Fecha {orden}"

        Dim sCon = CadenaConexionSQL()
        Dim da As SqlDataAdapter
        dt = New DataTable

        Try
            ' Crear un nuevo objeto del tipo DataAdapter
            da = New SqlDataAdapter(sel, sCon)

            ' Llenar la tabla con los datos indicados
            da.Fill(dt)

            Return $"Recuperadas {dt.Rows.Count} filas."
        Catch ex As Exception
            Return $"ERROR: {ex.Message}"
        End Try

    End Function

    ''' <summary>
    ''' Mostrar los datos de MySQL
    ''' </summary>
    Private Function MostrarDatosMySQL(ByRef dt As DataTable) As String
        If UsarBaseLocal Then Return "No hay base local de MySQL"

        Dim orden = If(chkOrden.Checked, "DESC", "ASC")
        ' MySQL no tiene TOP, usar en su lugar LIMIT
        Dim sel = $"SELECT * FROM {Tabla} ORDER BY Fecha {orden} LIMIT {MaxFilas}"

        Dim sCon = CadenaConexionMySQL()
        Dim da As MySqlDataAdapter
        dt = New DataTable

        Try
            ' Crear un nuevo objeto del tipo DataAdapter
            da = New MySqlDataAdapter(sel, sCon)

            ' Llenar la tabla con los datos indicados
            da.Fill(dt)

            Return $"Recuperadas {dt.Rows.Count} filas."
        Catch ex As Exception
            Return $"ERROR: {ex.Message}"
        End Try

    End Function

    Private Sub btnAñadir_Click(sender As Object,
                                e As EventArgs) Handles btnAñadir.Click
        Dim msg = ""

        msg = AñadirSQL() & vbCrLf
        msg &= AñadirMySQL()

        LabelError.Text = msg

        btnRefrescar.PerformClick()
    End Sub

    Private Sub btnRefrescar_Click(sender As Object,
                                   e As EventArgs) Handles btnRefrescar.Click
        Dim dt As DataTable = Nothing
        Dim msg = ""
        lvDatos.Items.Clear()

        Dim i = 5
        Integer.TryParse(txtFilas.Text, i)
        MaxFilas = i

        msg = MostrarDatosSQL(dt) & vbCrLf
        asignarDatos("SQL", dt)

        Dim lvi = lvDatos.Items.Add("---")
        lvi.SubItems.Add("---")
        lvi.SubItems.Add("---")
        lvi.SubItems.Add("---")

        dt = Nothing
        msg &= MostrarDatosMySQL(dt)
        asignarDatos("MySQL", dt)

        LabelError.Text = msg
    End Sub

    Private Sub asignarDatos(base As String, dt As DataTable)
        If dt Is Nothing Then Return

        For Each r As DataRow In dt.Rows
            Dim lvi = lvDatos.Items.Add(base)
            lvi.SubItems.Add(r("Fecha").ToString)
            lvi.SubItems.Add(r("ConVarChar").ToString)
            lvi.SubItems.Add(r("ConNVarChar").ToString)
        Next

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        inicializando = False
    End Sub

    Private Sub ChkUsarBaseLocal_CheckedChanged(sender As Object, e As EventArgs) Handles chkUsarBaseLocal.CheckedChanged
        If inicializando Then Return

        UsarBaseLocal = chkUsarBaseLocal.Checked
    End Sub

End Class

El código para C#

//-----------------------------------------------------------------------------
// Prueba de los tipos de SQL VarChar y NVarChar                    (21/Mar/19)
// Usando base de SQL Server y MySQL
//
//
// (c) Guillermo (elGuille) Som, 2019
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Data.SqlClient;
// Versión de mysql.data.dll: Connector/Net 6.0.3.0
using MySql.Data.MySqlClient;

namespace VarChar_y_NVarChar_cs
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool inicializando = true;

        /// <summary>
        /// Para las primeras pruebas uso una base local
        /// </summary>
        private bool UsarBaseLocal = true;

        private string ServerName = @".\SQLEXPRESS";
        private string DatabaseName = "PruebaVarChar";
        private string UsuarioDB = "elGuille_info";
        private string PasswordDB = "VarChar_19";

        private string Tabla = "VarCharElGuille";
        // Campos: Fecha, ConVarChar varchar(50), ConNVarChar nvarchar(50)
        // en MySQL no hay NVARCHAR y uso TEXT(50)

        private int MaxFilas = 5;

        /// <summary>
        /// La cadena de conexión a la base de datos
        /// </summary>
        private string CadenaConexionSQL()
        {
            ConectarSQL();

            var csb = new SqlConnectionStringBuilder();

            csb.DataSource = ServerName;
            csb.InitialCatalog = DatabaseName;
            csb.UserID = UsuarioDB + "SQL";
            csb.Password = PasswordDB;
            csb.IntegratedSecurity = false;

            return csb.ConnectionString;
        }

        /// <summary>
        /// La cadena de conexión a la base de datos
        /// </summary>
        private string CadenaConexionMySQL()
        {
            if (UsarBaseLocal)
                return "No hay base local de MySQL";

            ConectarMySQL();

            var csb = new MySqlConnectionStringBuilder();

            csb.Server = ServerName;
            csb.Database = DatabaseName;
            csb.UserID = UsuarioDB + "My";
            csb.Password = PasswordDB;

            return csb.ConnectionString;
        }


        /// <summary>
        /// Conectar a la base de datos de SQL Server
        /// </summary>
        private void ConectarSQL()
        {
            if (UsarBaseLocal)
                ServerName = @".\SQLEXPRESS";
            else
                ServerName = "sql3.servidoreswindows.net";
        }

        /// <summary>
        /// Conectar a la base de datos de MySQL.
        /// Siempre en remoto.
        /// </summary>
        private void ConectarMySQL()
        {
            ServerName = "mysql1.servidoreswindows.net";
        }


        /// <summary>
        /// Añadir el dato a la base de SQL Server
        /// </summary>
        private string AñadirSQL()
        {
            string sCon = CadenaConexionSQL();
            var sel = $"INSERT INTO {Tabla} (Fecha, ConVarChar, ConNVarChar) " + 
                      $"VALUES('{DateTime.Now}', '{txtDato.Text}', '{txtDato.Text}')";

            using (var con = new SqlConnection(sCon))
            {
                var cmd = new SqlCommand(sel, con);

                try
                {
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();

                    return "";
                }
                catch (Exception ex)
                {
                    return $"ERROR: {ex.Message}";
                }
            }
        }

        /// <summary>
        /// Añadir el dato a la base de datos de MySQL
        /// </summary>
        private string AñadirMySQL()
        {
            if (UsarBaseLocal)
                return "No hay base local de MySQL";

            var sCon = CadenaConexionMySQL();
            // En MySQL he definido Fecha como varchar(20)
            var sel = $"INSERT INTO {Tabla} (Fecha, ConVarChar, ConNVarChar) " + 
                      $"VALUES('{DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")}', '{txtDato.Text}', '{txtDato.Text}')";

            using (var con = new MySqlConnection(sCon))
            {
                var cmd = new MySqlCommand(sel, con);

                try
                {
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();

                    return "";
                }
                catch (Exception ex)
                {
                    return $"ERROR: {ex.Message}";
                }
            }
        }

        /// <summary>
        /// Mostrar los datos de la base de SQLServer
        /// </summary>
        private string MostrarDatosSQL(ref DataTable dt)
        {
            var orden = chkOrden.Checked ? "DESC" : "ASC";
            var sel = $"SELECT TOP ({MaxFilas}) * FROM {Tabla} ORDER BY Fecha {orden}";

            var sCon = CadenaConexionSQL();
            SqlDataAdapter da;
            dt = new DataTable();

            try
            {
                // Crear un nuevo objeto del tipo DataAdapter
                da = new SqlDataAdapter(sel, sCon);

                // Llenar la tabla con los datos indicados
                da.Fill(dt);

                return $"Recuperadas {dt.Rows.Count} filas.";
            }
            catch (Exception ex)
            {
                return $"ERROR: {ex.Message}";
            }
        }

        /// <summary>
        /// Mostrar los datos de MySQL
        /// </summary>
        private string MostrarDatosMySQL(ref DataTable dt)
        {
            if (UsarBaseLocal)
                return "No hay base local de MySQL";

            var orden = chkOrden.Checked ? "DESC" : "ASC";
            // MySQL no tiene TOP, usar en su lugar LIMIT
            var sel = $"SELECT * FROM {Tabla} ORDER BY Fecha {orden} LIMIT {MaxFilas}";

            var sCon = CadenaConexionMySQL();
            MySqlDataAdapter da;
            dt = new DataTable();

            try
            {
                // Crear un nuevo objeto del tipo DataAdapter
                da = new MySqlDataAdapter(sel, sCon);

                // Llenar la tabla con los datos indicados
                da.Fill(dt);

                return $"Recuperadas {dt.Rows.Count} filas.";
            }
            catch (Exception ex)
            {
                return $"ERROR: {ex.Message}";
            }
        }

        private void BtnAñadir_Click(object sender, EventArgs e)
        {
            var msg = "";

            msg = AñadirSQL() + "\n";
            msg += AñadirMySQL();

            LabelError.Text = msg;

            btnRefrescar.PerformClick();
        }

        private void BtnRefrescar_Click(object sender, EventArgs e)
        {
            DataTable dt = null;
            var msg = "";
            lvDatos.Items.Clear();

            var i = 5;
            int.TryParse(txtFilas.Text, out i);
            MaxFilas = i;

            msg = MostrarDatosSQL(ref dt) + "\n";
            asignarDatos("SQL", dt);

            var lvi = lvDatos.Items.Add("---");
            lvi.SubItems.Add("---");
            lvi.SubItems.Add("---");
            lvi.SubItems.Add("---");

            dt = null;
            msg += MostrarDatosMySQL(ref dt);
            asignarDatos("MySQL", dt);

            LabelError.Text = msg;
        }

        private void asignarDatos(string @base, DataTable dt)
        {
            if (dt == null) return;

            foreach (DataRow r in dt.Rows)
            {
                var lvi = lvDatos.Items.Add(@base);
                lvi.SubItems.Add(r["Fecha"].ToString());
                lvi.SubItems.Add(r["ConVarChar"].ToString());
                lvi.SubItems.Add(r["ConNVarChar"].ToString());
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            inicializando = false;
        }

        private void ChkUsarBaseLocal_CheckedChanged(object sender, EventArgs e)
        {
            if (inicializando) return;

            UsarBaseLocal = chkUsarBaseLocal.Checked;
        }
    }
}

Y esto es todo… espero que te sea de utilidad.

Nos vemos.
Guillermo

El código completo del ejemplo
(solución para Visual Studio usando .NET 4.7.2)

El ZIP con el código completo (una solución de Visual Studio 2019 Preview con los proyectos de Visual Basic y C# además de la DLL de MySQL con la referencia a la copia dentro del directorio de la solución.

El zip: VarChar_y_NVarChar_20190321.zip (147 KB)

MD5 Checksum: 888346C11622183F6A39FE5FBA4339D3

Nota:

Aquí tienes el enlace para la descarga del ZIP que me descargué con el conector de MySQL para .NET versión 6.0.3 (mysql-connector-net-6.0.3-noinstall.zip) el tamaño es 1.64MB y el MD5 Checksum es: 57BB7F42645665D5A616A3484041F0C0.

VarChar y NVarChar en SQL Server

Actualizado el 21/Mar/2019 con los pasos para resolver el fallo que tenía de acceso a las bases de datos remotas y también con el enlace al código para VB y C#.

Pues eso… el otro día estaba creando una base de datos de MySQL y me di cuenta que MySQL no tiene el tipo NVARCHAR o al menos a mí no me daba la opción de crear un campo con ese tipo, al menos desde el panel de control del hosting que utilizo (Domitienda.com), así que… utilicé VARCHAR, el problema que me temía que iba a tener era no poder usar las vocales acentuadas (con tilde), la eñe, etc. Pero resultó que sí… que lo aceptaba sin problemas.

Así que, me puse a buscar en Internet a ver cuál era la diferencia entre VARCHAR y NVARCHAR, ya que yo siempre usaba NVARCHAR en mis bases de SQL Server (que es el tipo de base que uso, salvo excepciones muy, muy contadas) porque era el tipo que me permitía usar los caracteres especiales del idioma español (o al menos así lo entendí yo, que puede ser que lo entendiese mal… ).

Pero resulta que si utilizo VARCHAR puedo indicar esos caracteres especiales sin mayor problema.

Por supuesto la información que encontré hablando de esa diferencia entre esos dos tipos de datos era… bueno… no aclaratoria del todo… pero en realidad me daba igual lo que me quisieran decir, ya que yo he comprobado por mí mismo que se puede guardar algo así: Raúl Rodríguez López es de Valdepeñas en un campo del tipo VARCHAR.

Un ejemplo para acceder a SQL Server y MySQL

Aquí tienes una captura de un ejemplo que he hecho para mostrar que sí funciona eso de guardar los caracteres especiales, al menos los usados en español.

El código lo publicaré otro día, ya que es tarde y además no me funciona el código para acceder a las bases de datos remotas (en el hosting de Domitienda), seguramente habré configurado algo mal, ya que a otras que tengo en el mismo hosting si que puedo acceder…

Nota del 21 de Marzo:

Según parece resulta que en el «plesk» del hosting no permite usar el mismo nombre de usuario para varias bases de datos o bien la longitud de la contraseña debe ser menor de la que usé… en cualquier caso lo he solucionado haciendo lo siguiente:

He creado dos usuarios diferentes, el de la base de datos de SQL Server se llama elGuille_infoSQL y el de MySQL se llama elGuille_infoMy.

He usado una clave más corta.

Y ahora todo funciona bien… o casi… ya que añadí un campo DATETIME a la base de MySQL y da error al convertir el contenido de la base de datos a un tipo DateTime de .NET, así que… lo he creado como VARCHAR(20).

Otra cosa con la que me he encontrado con la consulta de MySQL es que no acepta TOP para indicar el número de filas a devolver, en su lugar he usado LIMIT y ya va bien.

En la captura de la Figura 2 puedes ver la aplicación totalmente operativa y accediendo a las bases de datos remotas.

Si te fijas en los valores mostrados al final con todo a cero, eso era lo que había añadido usando el tipo de datos DATETIME en MySQL, después al añadirlo como VARCHAR ya se muestra bien.

El código de VB y C# lo puedes ver en la entrada publicada el 21 de marzo: VarChar y NVarChar en SQL Server y MySQL el código para VB y C#.

Figura 2. La aplicación operativa con acceso remoto después de los cambios hechos en el hosting.
Figura 2. La aplicación operativa con acceso remoto después de los cambios hechos en el hosting.

Figura 1. Formulario de prueba
Figura 1. El formulario de prueba

Los datos mostrados en la figura 1 son de una base de datos de SQL Server usada localmente, el mensaje de error que se muestra es el devuelto por el servidor de MySQL.

Lo importante es que puedes comprobar que tanto el campo VARCHAR como NVARCHAR muestran las vocales con tilde y la eñe.

Seguramente si uso caracteres de otros idiomas como el CHINO o RUSO no se guardarían bien en el VARCHAR… no lo sé porque no lo he probado… 😉

Pues esto es todo por hoy… en los enlaces puedes ver más información sobre esos tipos de datos (en la documentación de SQL Server) y lo que cuentan en algunos sitios sobre la diferencia entre ellos.

Este enlace es sobre VARCHAR en la documentación de MySQL.

A ver si el jueves próximo (día 21, luna llena, por más señas) te pongo el código de ejemplo de la aplicación que guarda esos caracteres en los dos tipos de datos y como de costumbre tanto para Visual Basic como para C#.

Nos vemos.
Guillermo

Nota:
Según el panel de control la versión de MySQL es:

mysql1.servidoreswindows.net
Versión del servidor: 5.1.73-log

Un regalito a una suscripción a Visual Studio Enterprise (por 12 meses)

Pues eso… que te acabo de contar que la licencia de Visual Studio 2017 Professional que parecía que me habían dado hace unos meses ya había expirado (y parecía que era definitiva y no de prueba) y acabo de abrir el correo y me encuentro que me han dado una suscripción a Visual Studio Enterprise (válida por un año) tal como puedes ver en la captura de la figura 1.

Un regalito para un ex-MVP (ahora rMVP)
Figura 1. Un regalito para un ex-MVP (ahora rMVP)

Esta suscripción (para 12 meses) contiene el Visual Studio y muchas más cosas (Windows, Office, etc.), como las antiguas suscripciones a MSDN que nos daban a los MVP reconocidos como developers… pero esta vez la dan por 12 meses a algunos ex-MVP ahora llamados MVP Reconnect (rMVP) y puede que la renueven… a ver qué pasa dentro de un año.

¡Muchas gracias!

Nos vemos.
Guillermo

Donde dije digo, digo Diego (y buscar las referencias a un método)

Pues eso… como te comenté hace unos meses (Tiene una licencia para Visual Studio Professional 2017) resulta que solo era de evaluación, pero se ve que de unos tres meses… en fin… eso de que no digan las cosas claras es un poco frustrante, por decir algo suave, ya que en ningún lugar decían nada de que fuese una licencia de prueba, en fin… uno que siempre intenta ver la parte buena… Winking smile

Nota:
Poco después de publicar esta entrada he abierto el correo y me encontrado con un bonito regalo: Un regalito a una suscripción a Visual Studio Enterprise (por 12 meses).
Gracias

Pero resulta que solo era una licencia temporal… o al menos así lo dice la captura de la ventana de aviso que me ha salido (ver la figura 1).

La licencia de prueba ha expirado
Figura 1. La licencia de prueba ha expirado

En esta ocasión si dice que «era» una licencia de prueba (Trial extension), en fin…

Pero no me importa, con la versión Community me apaño, ya que en realidad la versión Professional la instalé porque tenía una cosilla que me venía muy bien: saber dónde se estaban usando los métodos de mis clases, (con enlaces a cada uno de los sitios en los que se accedía al método) cosa que desde hace unos meses ya no aparece, al menos como aparecía antes: encima de la definición del método.

 

Buscar todas las referencias a un método

Si te sitúas en la definición de un método y pulsas en el menú contextual, te saldrá algo como lo mostrado en la figura 2 y seleccionando Buscar todas las referencias te mostrará una lista desde dónde se accede a ese método (ver la figura 3).

Menú contextual de la definición de un método
Figura 2. Menú contextual de la definición de un método
Las referencias al método
Figura 3. Las referencias al método

Nota:
Comentarte que no solo se pueden ver las referencias a un método, también a las clases y otros tipos definidos.

Y esto es todo… seguiré con la versión Community de Visual Studio 2017 y (mientras tenga acceso) a las versiones Preview de Visual Studio 2019 y cuando salga la definitiva (recuerda que está prevista para el 2 de abril) si no consigo una versión mayor, seguiré con la de la comunidad (que esa sí que es gratuita de por vida… o al menos por ahora lo es).

Nos vemos.
Guillermo