Leer en inglés

Compartir a través de


Creación de una aplicación de datos sencilla mediante ADO.NET

Nota

Los conjuntos de datos y las clases relacionadas son tecnologías heredadas de .NET Framework de principios de los años 2000 que permiten a las aplicaciones trabajar con datos en memoria mientras las aplicaciones están desconectadas de la base de datos. Las tecnologías son especialmente útiles para las aplicaciones que permiten a los usuarios modificar datos y conservar los cambios de nuevo en la base de datos. Aunque los conjuntos de datos han demostrado ser una tecnología muy exitosa, se recomienda que las nuevas aplicaciones .NET usen Entity Framework Core. Entity Framework proporciona una manera más natural de trabajar con datos tabulares como modelos de objetos y tiene una interfaz de programación más sencilla.

Cuando se crea una aplicación que manipula datos en una base de datos, se realizan tareas básicas como definir cadenas de conexión, insertar datos y ejecutar procedimientos almacenados. Al seguir este tema, puede descubrir cómo interactuar con una base de datos desde una sencilla aplicación de Formularios Windows Forms "formularios sobre datos" mediante Visual C# o Visual Basic y ADO.NET. Todas las tecnologías de datos de .NET, incluidos los conjuntos de datos, LINQ to SQL y Entity Framework, realizan en última instancia pasos muy similares a los que se muestran en este artículo.

En este artículo se muestra una manera sencilla de obtener rápidamente datos de una base de datos. Si la aplicación necesita modificar datos de maneras notriviales y actualizar la base de datos, debe considerar la posibilidad de usar Entity Framework y usar el enlace de datos para sincronizar automáticamente los controles de la interfaz de usuario a los cambios en los datos subyacentes.

Importante

Para mantener el código sencillo, no se incluye el control de excepciones listo para producción.

Nota

Se puede acceder al código completo de este tutorial en el repositorio de GitHub de Visual Studio en C# y en Visual Basic.

Prerrequisitos

Para crear la aplicación, necesita:

  • Visual Studio con las cargas de trabajo de procesamiento y almacenamiento de datos y desarrollo de escritorio de .NET instaladas. Para instalarlos, abra el Instalador de Visual Studio y elija Modificar (o Más>Modificar) junto a la versión de Visual Studio que desea modificar.

  • SQL Server Express LocalDB. Si no tiene SQL Server Express LocalDB, puede instalarlo desde la página de descarga de SQL Server.

En este tema se da por supuesto que está familiarizado con la funcionalidad básica del IDE de Visual Studio y puede crear una aplicación de Windows Forms, agregar formularios al proyecto, colocar botones y otros controles en los formularios, establecer propiedades de los controles y codificar eventos sencillos. Si no está familiarizado con estas tareas, se recomienda completar la Crear una aplicación de Windows Forms en Visual Studio con Visual Basic tutorial o el tutorial Crear una aplicación de Windows Forms en Visual Studio con C# tutorial antes de iniciar este tutorial.

Configuración de la base de datos de ejemplo

Cree la base de datos de ejemplo siguiendo estos pasos:

  1. En Visual Studio, abra la ventana Explorador de servidores.

  2. Haga clic con el botón derecho en conexiones de datos y elija Crear nueva base de datos de SQL Server.

  3. En el cuadro de texto nombre del servidor , escriba (localdb)\mssqllocaldb.

  4. En el cuadro de texto Nombre de la base de datos nueva, escriba Sales y, después, elija Aceptar.

    Se crea la base de datos vacía Sales y se agrega al nodo Conexiones de datos en el Explorador de servidores.

  5. Haga clic con el botón derecho en la conexión de datos Sales y seleccione Nueva consulta.

    Se abre una ventana del editor de consultas.

  6. Copie el script de Transact-SQL de Sales en el Portapapeles.

  7. Pegue el script T-SQL en el editor de consultas y, a continuación, elija el botón Ejecutar.

    Después de un breve tiempo, la consulta termina de ejecutarse y se crean los objetos de base de datos. La base de datos contiene dos tablas: Customer y Orders. Estas tablas no contienen datos inicialmente, pero puede agregar datos al ejecutar la aplicación que cree. La base de datos también contiene cuatro procedimientos almacenados simples.

Crear los formularios y agregar controles

  1. Cree un proyecto de C# o Visual Basic con la plantilla de la Aplicación de Windows Forms (.NET Framework) y, a continuación, asígneles el nombre SimpleDataApp.

    Visual Studio crea el proyecto y varios archivos, incluido un formulario windows vacío denominado Form1.

  2. Agregue dos formularios Windows Forms al proyecto para que tenga tres formularios y, a continuación, asígneles los siguientes nombres:

    • Navegación

    • NuevoCliente

    • Llenar o Cancelar

  3. Para cada formulario, agregue los cuadros de texto, los botones y otros controles que aparecen en las ilustraciones siguientes. Para cada control, establezca las propiedades que describen las tablas.

    Nota

    El cuadro de grupo y los controles de etiqueta agregan claridad, pero no se usan en el código.

    Formulario Navigation

    cuadro de diálogo Navegación

Controles para el formulario de navegación Propiedades
Botón Nombre = btnGoToAdd
Botón Nombre = btnGoToFillOrCancel
Botón Nombre = btnExit

Formulario NewCustomer

Agregar un nuevo cliente y realizar un pedido

Controles para el formulario NewCustomer Propiedades
Caja de texto Nombre = txtCustomerName
TextBox Nombre = txtCustomerID

De solo lectura = True
Botón Nombre = btnCreateAccount
NumericUpDown Posiciones decimales = 0

Máximo = 5000

Nombre = numOrderAmount
DateTimePicker Formato = Corto

Nombre = dtpOrderDate
Botón Nombre = btnPlaceOrder
Botón Nombre = btnAddAnotherAccount
Botón Nombre = btnAddFinish

Formulario de Completar o Cancelar

rellenar o cancelar pedidos

Controles para el formulario FillOrCancel Propiedades
Caja de texto Nombre = txtOrderID
Botón Nombre = btnFindByOrderID
DateTimePicker Formato = Corto

Nombre = dtpFillDate
DataGridView Nombre = dgvCustomerOrders

De solo lectura = True

Encabezados de filas visibles = False
Botón Nombre = btnCancelOrder
Botón Nombre = btnFillOrder
Botón Nombre = btnFinishUpdates

Almacenar la cadena de conexión

Cuando la aplicación intenta abrir una conexión a la base de datos, la aplicación debe tener acceso a la cadena de conexión. Para evitar escribir manualmente la cadena en cada formulario, almacene la cadena en el archivo App.config del proyecto y cree un método que devuelva la cadena cuando se llame al método desde cualquier formulario de la aplicación.

Para encontrar la cadena de conexión, haga clic con el botón derecho en la conexión de datos Sales en el Explorador de servidores y elija Propiedades. Busque la propiedad ConnectionString y, a continuación, use Ctrl+A, Ctrl+C para seleccionar y copiar la cadena en el portapapeles.

  1. Si está usando C#, en Explorador de soluciones, expanda el nodo Propiedades dentro del proyecto y, a continuación, abra el archivo Settings.settings. Si usa Visual Basic, en Explorador de soluciones, haga clic en Mostrar todos los archivos, expanda el nodo Mi proyecto y, a continuación, abra el archivo Settings.settings.

  2. En la columna Nombre, escriba connString.

  3. En la lista Tipo, seleccione (Cadena de conexión).

  4. En la lista Ámbito, elija Aplicación.

  5. En la columna Valor, escriba la cadena de conexión (sin comillas externas) y después guarde los cambios.

    Captura de pantalla de la cadena de conexión en Settings.settings

Precaución

En una aplicación real, debe almacenar la cadena de conexión de forma segura, como se describe en Cadenas de conexión y archivos de configuración. Para obtener la mejor seguridad, use un método de autenticación que no dependa de almacenar una contraseña en la cadena de conexión, como la autenticación de Windows para una base de datos de SQL Server local. Consulte Guardar y editar cadenas de conexión.

Escribir el código para los formularios

Esta sección contiene breves información general sobre lo que hace cada formulario. También proporciona el código que define la lógica subyacente cuando se hace clic en un botón del formulario.

El formulario de navegación se abre al ejecutar la aplicación. El botón Agregar una cuenta abre el formulario NewCustomer. El botón Rellenar o cancelar órdenes abre el formulario FillOrCancel. El botón Salir cierra la aplicación.

Convertir el formulario de navegación en el formulario de inicio

Si usa C#, en el Explorador de soluciones, abra Program.cs y, a continuación, cambie la línea Application.Run a esta: Application.Run(new Navigation());

Si usa Visual Basic, en el Explorador de soluciones, abra la ventana Propiedades, elija la pestaña Aplicación y, después, elija SimpleDataApp.Navigation en la lista Formulario de inicio.

Creación de controladores de eventos generados automáticamente

Haga doble clic en los tres botones del formulario Navigation para crear métodos de controlador de eventos vacíos. Al hacer doble clic en los botones también se agrega código generado automáticamente en el archivo de código del Diseñador que permite que un clic de botón genere un evento.

Nota

Si omite la acción de doble clic en el diseñador y solo copia el código y lo pega en los archivos de código, no olvide establecer el controlador de eventos en el método correcto. Puede hacerlo en la ventana Propiedades. Cambie a la pestaña Eventos (use el botón de la barra de herramientas con un icono de rayo) y busque el controlador Click.

Adición de código para la lógica del formulario de navegación

En la página de códigos del formulario Navegación, complete los cuerpos de método para los tres controladores de eventos generados con clic de botón, como se muestra en el código siguiente.

C#
/// <summary>
/// Opens the NewCustomer form as a dialog box,
/// which returns focus to the calling form when it is closed. 
/// </summary>
private void btnGoToAdd_Click(object sender, EventArgs e)
{
    Form frm = new NewCustomer();
    frm.Show();
}

/// <summary>
/// Opens the FillorCancel form as a dialog box. 
/// </summary>
private void btnGoToFillOrCancel_Click(object sender, EventArgs e)
{
    Form frm = new FillOrCancel();
    frm.ShowDialog();
}

/// <summary>
/// Closes the application (not just the Navigation form).
/// </summary>
private void btnExit_Click(object sender, EventArgs e)
{
    this.Close();
}

Nota

El código de este tutorial está disponible en C# y Visual Basic. Para cambiar el lenguaje de código de esta página entre C# y Visual Basic, use el modificador de lenguaje de código en la parte superior de cada ejemplo de código.

Formulario NewCustomer

Cuando escriba un nombre de cliente y, a continuación, seleccione el botón Crear cuenta, el formulario NewCustomer crea una cuenta de cliente y SQL Server devuelve un valor IDENTITY como el nuevo identificador de cliente. Después, puede realizar un pedido para la nueva cuenta especificando una cantidad y una fecha de pedido y seleccionando el botón realizar pedido.

Creación de controladores de eventos generados automáticamente

Cree un controlador de eventos Click vacío para cada botón del formulario NewCustomer haciendo doble clic en cada uno de los cuatro botones. Al hacer doble clic en los botones también se agrega código generado automáticamente en el archivo de código del Diseñador que permite que un clic de botón genere un evento.

Adición de código para la lógica de formulario NewCustomer

Para completar la lógica de formulario NewCustomer, siga estos pasos.

  1. Incluya el espacio de nombres System.Data.SqlClient en el ámbito para que no tenga que usar los nombres completos de sus miembros.

    C#
    using System.Data.SqlClient;
    
  2. Agregue algunas variables y métodos auxiliares a la clase como se muestra en el código siguiente.

    C#
    // Storage for IDENTITY values returned from database.
    private int parsedCustomerID;
    private int orderID;
    
    /// <summary>
    /// Verifies that the customer name text box is not empty.
    /// </summary>
    private bool IsCustomerNameValid()
    {
        if (txtCustomerName.Text == "")
        {
            MessageBox.Show("Please enter a name.");
            return false;
        }
        else
        {
            return true;
        }
    }
    
    /// <summary>
    /// Verifies that a customer ID and order amount have been provided.
    /// </summary>
    private bool IsOrderDataValid()
    {
        // Verify that CustomerID is present.
        if (txtCustomerID.Text == "")
        {
            MessageBox.Show("Please create customer account before placing order.");
            return false;
        }
        // Verify that Amount isn't 0.
        else if ((numOrderAmount.Value < 1))
        {
            MessageBox.Show("Please specify an order amount.");
            return false;
        }
        else
        {
            // Order can be submitted.
            return true;
        }
    }
    
    /// <summary>
    /// Clears the form data.
    /// </summary>
    private void ClearForm()
    {
        txtCustomerName.Clear();
        txtCustomerID.Clear();
        dtpOrderDate.Value = DateTime.Now;
        numOrderAmount.Value = 0;
        this.parsedCustomerID = 0;
    }
    
  3. Complete los cuerpos de método para los cuatro controladores de eventos generados con clic de botón, como se muestra en el código siguiente.

    C#
    /// <summary>
    /// Creates a new customer by calling the Sales.uspNewCustomer stored procedure.
    /// </summary>
    private void btnCreateAccount_Click(object sender, EventArgs e)
    {
        if (IsCustomerNameValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create a SqlCommand, and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspNewCustomer", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add input parameter for the stored procedure and specify what to use as its value.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerName", SqlDbType.NVarChar, 40));
                    sqlCommand.Parameters["@CustomerName"].Value = txtCustomerName.Text;
    
                    // Add the output parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.Int));
                    sqlCommand.Parameters["@CustomerID"].Direction = ParameterDirection.Output;
    
                    try
                    {
                        connection.Open();
    
                        // Run the stored procedure.
                        sqlCommand.ExecuteNonQuery();
    
                        // Customer ID is an IDENTITY value from the database.
                        this.parsedCustomerID = (int)sqlCommand.Parameters["@CustomerID"].Value;
    
                        // Put the Customer ID value into the read-only text box.
                        this.txtCustomerID.Text = Convert.ToString(parsedCustomerID);
                    }
                    catch
                    {
                        MessageBox.Show("Customer ID was not returned. Account could not be created.");
                    }
                    finally
                    {
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Calls the Sales.uspPlaceNewOrder stored procedure to place an order.
    /// </summary>
    private void btnPlaceOrder_Click(object sender, EventArgs e)
    {
        // Ensure the required input is present.
        if (IsOrderDataValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create SqlCommand and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspPlaceNewOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the @CustomerID input parameter, which was obtained from uspNewCustomer.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.Int));
                    sqlCommand.Parameters["@CustomerID"].Value = this.parsedCustomerID;
    
                    // Add the @OrderDate input parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@OrderDate", SqlDbType.DateTime, 8));
                    sqlCommand.Parameters["@OrderDate"].Value = dtpOrderDate.Value;
    
                    // Add the @Amount order amount input parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@Amount", SqlDbType.Int));
                    sqlCommand.Parameters["@Amount"].Value = numOrderAmount.Value;
    
                    // Add the @Status order status input parameter.
                    // For a new order, the status is always O (open).
                    sqlCommand.Parameters.Add(new SqlParameter("@Status", SqlDbType.Char, 1));
                    sqlCommand.Parameters["@Status"].Value = "O";
    
                    // Add the return value for the stored procedure, which is  the order ID.
                    sqlCommand.Parameters.Add(new SqlParameter("@RC", SqlDbType.Int));
                    sqlCommand.Parameters["@RC"].Direction = ParameterDirection.ReturnValue;
    
                    try
                    {
                        //Open connection.
                        connection.Open();
    
                        // Run the stored procedure.
                        sqlCommand.ExecuteNonQuery();
    
                        // Display the order number.
                        this.orderID = (int)sqlCommand.Parameters["@RC"].Value;
                        MessageBox.Show("Order number " + this.orderID + " has been submitted.");
                    }
                    catch
                    {
                        MessageBox.Show("Order could not be placed.");
                    }
                    finally
                    {
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Clears the form data so another new account can be created.
    /// </summary>
    private void btnAddAnotherAccount_Click(object sender, EventArgs e)
    {
        this.ClearForm();
    }
    
    /// <summary>
    /// Closes the form/dialog box.
    /// </summary>
    private void btnAddFinish_Click(object sender, EventArgs e)
    {
        this.Close();
    }
    

Formulario de Rellenar o Cancelar

El formulario FillOrCancel ejecuta una consulta para devolver un pedido al escribir un identificador de pedido y, a continuación, selecciona el botón Buscar pedido. La fila devuelta aparece en una cuadrícula de datos de solo lectura. Puede marcar el pedido como cancelado (X) si selecciona el botón Cancelar pedido, o puede marcar el pedido como completado (F) si selecciona el botón Rellenar pedido. Si selecciona de nuevo el botón Buscar pedido, aparecerá la fila actualizada.

Creación de controladores de eventos generados automáticamente

Cree controladores de eventos Click vacíos para los cuatro botones del formulario FillOrCancel haciendo doble clic en los botones. Al hacer doble clic en los botones también se agrega código generado automáticamente en el archivo de código del Diseñador que permite que un clic de botón genere un evento.

Adición de código para la lógica de formulario FillOrCancel

Para completar la lógica del formulario FillOrCancel, siga estos pasos.

  1. Incluya los dos espacios de nombres siguientes en el ámbito para que no tenga que usar los nombres completos de sus miembros.

    C#
    using System.Data.SqlClient;
    using System.Text.RegularExpressions;
    
  2. Agregue una variable y un método auxiliar a la clase como se muestra en el código siguiente.

    C#
    // Storage for the order ID value.
    private int parsedOrderID;
    
    /// <summary>
    /// Verifies that an order ID is present and contains valid characters.
    /// </summary>
    private bool IsOrderIDValid()
    {
        // Check for input in the Order ID text box.
        if (txtOrderID.Text == "")
        {
            MessageBox.Show("Please specify the Order ID.");
            return false;
        }
    
        // Check for characters other than integers.
        else if (Regex.IsMatch(txtOrderID.Text, @"^\D*$"))
        {
            // Show message and clear input.
            MessageBox.Show("Customer ID must contain only numbers.");
            txtOrderID.Clear();
            return false;
        }
        else
        {
            // Convert the text in the text box to an integer to send to the database.
            parsedOrderID = Int32.Parse(txtOrderID.Text);
            return true;
        }
    }
    
  3. Complete los cuerpos de método para los cuatro controladores de eventos generados con clic de botón, como se muestra en el código siguiente.

    C#
    /// <summary>
    /// Executes a t-SQL SELECT statement to obtain order data for a specified
    /// order ID, then displays it in the DataGridView on the form.
    /// </summary>
    private void btnFindByOrderID_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Define a t-SQL query string that has a parameter for orderID.
                const string sql = "SELECT * FROM Sales.Orders WHERE orderID = @orderID";
    
                // Create a SqlCommand object.
                using (SqlCommand sqlCommand = new SqlCommand(sql, connection))
                {
                    // Define the @orderID parameter and set its value.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    try
                    {
                        connection.Open();
    
                        // Run the query by calling ExecuteReader().
                        using (SqlDataReader dataReader = sqlCommand.ExecuteReader())
                        {
                            // Create a data table to hold the retrieved data.
                            DataTable dataTable = new DataTable();
    
                            // Load the data from SqlDataReader into the data table.
                            dataTable.Load(dataReader);
    
                            // Display the data from the data table in the data grid view.
                            this.dgvCustomerOrders.DataSource = dataTable;
    
                            // Close the SqlDataReader.
                            dataReader.Close();
                        }
                    }
                    catch
                    {
                        MessageBox.Show("The requested order could not be loaded into the form.");
                    }
                    finally
                    {
                        // Close the connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Cancels an order by calling the Sales.uspCancelOrder
    /// stored procedure on the database.
    /// </summary>
    private void btnCancelOrder_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create the SqlCommand object and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspCancelOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the order ID input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    try
                    {
                        // Open the connection.
                        connection.Open();
    
                        // Run the command to execute the stored procedure.
                        sqlCommand.ExecuteNonQuery();
                    }
                    catch
                    {
                        MessageBox.Show("The cancel operation was not completed.");
                    }
                    finally
                    {
                        // Close connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Fills an order by calling the Sales.uspFillOrder stored
    /// procedure on the database.
    /// </summary>
    private void btnFillOrder_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create command and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspFillOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the order ID input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    // Add the filled date input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@FilledDate", SqlDbType.DateTime, 8));
                    sqlCommand.Parameters["@FilledDate"].Value = dtpFillDate.Value;
    
                    try
                    {
                        connection.Open();
    
                        // Execute the stored procedure.
                        sqlCommand.ExecuteNonQuery();
                    }
                    catch
                    {
                        MessageBox.Show("The fill operation was not completed.");
                    }
                    finally
                    {
                        // Close the connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Closes the form.
    /// </summary>
    private void btnFinishUpdates_Click(object sender, EventArgs e)
    {
        this.Close();
    }
    

Prueba de la aplicación

Ejecute la aplicación e intente crear algunos clientes y pedidos para comprobar que todo funciona según lo previsto. Para comprobar que la base de datos se actualiza con los cambios, abra el nodo Tablas en el Explorador de servidores, haga clic con el botón derecho en los nodos Customers y Orders y elija Mostrar datos de tabla.