Creare un'applicazione dati semplice tramite ADO.NET

Nota

I set di dati e le classi correlate sono tecnologie .NET Framework legacy dei primi anni '2000 che consentono alle applicazioni di lavorare con i dati in memoria mentre le applicazioni vengono disconnesse dal database. Sono particolarmente utili per le applicazioni che consentono agli utenti di modificare i dati e rendere persistenti le modifiche apportate al database. Anche se i set di dati hanno dimostrato di essere una tecnologia molto efficace, è consigliabile che le nuove applicazioni .NET usino Entity Framework Core. Entity Framework offre un modo più naturale per usare i dati tabulari come modelli a oggetti e ha un'interfaccia di programmazione più semplice.

Quando si crea un'applicazione che modifica i dati in un database, è possibile eseguire attività di base, ad esempio la definizione delle stringhe di connessione, l'inserimento di dati e l'esecuzione di stored procedure. Seguendo questo argomento, è possibile scoprire come interagire con un database dall'interno di una semplice applicazione Windows Form "moduli su dati" usando Visual C# o Visual Basic e ADO.NET. Tutte le tecnologie dati .NET, inclusi i set di dati, LINQ to SQL e Entity Framework, eseguono infine passaggi molto simili a quelli illustrati in questo articolo.

Questo articolo illustra un modo semplice per ottenere rapidamente i dati da un database. Se l'applicazione deve modificare i dati in modi non intermedi e aggiornare il database, è consigliabile usare Entity Framework e usare il data binding per sincronizzare automaticamente i controlli dell'interfaccia utente alle modifiche nei dati sottostanti.

Importante

Per semplificare il codice, non include la gestione delle eccezioni dell'ambiente di produzione.

Nota

È possibile accedere al codice completo per questa esercitazione nel repository GitHub della documentazione di Visual Studio in C# e Visual Basic.

Prerequisiti

Per creare l'applicazione, è necessario:

  • Visual Studio con i carichi di lavoro di sviluppo per desktop .NET e Archiviazione dati ed elaborazione installati. Per installarli, aprire Programma di installazione di Visual Studio e scegliere Modifica (o Altro>modifica) accanto alla versione di Visual Studio da modificare.

  • LocalDB di SQL Server Express. Se SQL Server Express Local DB non è disponibile, è possibile installarlo dalla pagina di download di SQL Server.

In questo argomento si presuppone che si abbia familiarità con le funzionalità di base dell'IDE di Visual Studio e che sia possibile creare un'applicazione Windows Form, aggiungere moduli al progetto, inserire pulsanti e altri controlli nei moduli, impostare le proprietà dei controlli e scrivere semplici eventi. Se non si ha familiarità con queste attività, è consigliabile completare l'esercitazione Creare un'app Windows Form in Visual Studio con Visual Basic o l'esercitazione Creare un'app Windows Form in Visual Studio con C# prima di iniziare questa procedura dettagliata.

Impostare il database di esempio

Creare il database di esempio seguendo questa procedura:

  1. In Visual Studio aprire la finestra Esplora server.

  2. Fare clic con il pulsante destro del mouse su Connessione dati e scegliere Crea nuovo database di SQL Server.

  3. Nella casella di testo Nome server immettere (localdb)\mssqllocaldb.

  4. Nella casella di testo Nuovo nome database immettere Sales e quindi scegliere OK.

    Il database Sales vuoto viene creato e aggiunto al nodo Data Connessione ions in Esplora server.

  5. Fare clic con il pulsante destro del mouse sulla connessione dati Sales e selezionare Nuova query.

    Verrà visualizzata una finestra dell'editor di query.

  6. Copiare lo script Transact-SQL Sales negli Appunti.

  7. Incollare lo script T-SQL nell'editor di query e quindi scegliere il pulsante Esegui .

    Dopo un breve periodo di tempo, la query termina l'esecuzione e gli oggetti di database vengono creati. Il database contiene due tabelle: Customer e Orders. Queste tabelle non contengono inizialmente dati, ma è possibile aggiungere dati quando si esegue l'applicazione creata. Il database contiene anche quattro semplici stored procedure.

Creare i form e aggiungere i controlli

  1. Creare un progetto C# o Visual Basic usando il modello app Windows Form (.NET Framework) e denominarlo SimpleDataApp.

    Visual Studio crea il progetto e diversi file, tra cui un form Windows vuoto denominato Form1.

  2. Aggiungere due form Windows al progetto in modo da disporre di tre form e assegnare i nomi seguenti:

    • Navigazione

    • NewCustomer

    • FillOrCancel

  3. Per ogni form, aggiungere caselle di testo, pulsanti e altri controlli come illustrato nelle figure seguenti. Per ciascun controllo, impostare le proprietà descritte nelle tabelle.

    Nota

    La casella di gruppo e i controlli Label migliorano la leggibilità, ma non vengono usati nel codice.

    Form Navigazione

    Finestra di dialogo Navigazione

Controlli per il form Navigazione Proprietà
Pulsante Name = btnGoToAdd
Pulsante Name = btnGoToFillOrCancel
Pulsante Name = btnExit

Form NewCustomer

Aggiungere un nuovo cliente e inserire un ordine

Controlli per il form NewCustomer Proprietà
TextBox Name = txtCustomerName
TextBox Name = txtCustomerID

Readonly = True
Pulsante Name = btnCreateAccount
NumericUpdown DecimalPlaces = 0

Maximum = 5000

Name = numOrderAmount
DateTimePicker Format = Short

Nome = dtpOrderDate
Pulsante Name = btnPlaceOrder
Pulsante Name = btnAddAnotherAccount
Pulsante Name = btnAddFinish

Form FillOrCancel

Completare o annullare gli ordini

Controlli del form FillOrCancel Proprietà
TextBox Name = txtOrderID
Pulsante Name = btnFindByOrderID
DateTimePicker Format = Short

Name = dtpFillDate
DataGridView Name = dgvCustomerOrders

Readonly = True

RowHeadersVisible = False
Pulsante Name = btnCancelOrder
Pulsante Name = btnFillOrder
Pulsante Name = btnFinishUpdates

Archiviare la stringa di connessione

Quando l'applicazione tenta di aprire una connessione al database, l'applicazione deve disporre dell'accesso alla stringa di connessione. Per evitare di immettere manualmente la stringa in ogni modulo, archiviare la stringa nel file App.config nel progetto e creare un metodo che restituisce la stringa quando il metodo viene chiamato da qualsiasi modulo nell'applicazione.

È possibile trovare il stringa di connessione facendo clic con il pulsante destro del mouse sulla connessione dati Sales in Esplora server e scegliendo Proprietà. Individuare la proprietà Connessione ionString, quindi usare CTRL A, CTRL++C per selezionare e copiare la stringa negli Appunti.

  1. Se si usa C#, in Esplora soluzioni espandere il nodo Proprietà nel progetto e quindi aprire il file Impostazioni.settings. Se si usa Visual Basic, in Esplora soluzioni fare clic su Mostra tutti i file, espandere il nodo Progetto personale e quindi aprire il file Impostazioni.settings.

  2. Nella colonna Nome immettere connString.

  3. Nell'elenco Tipo selezionare (Connessione ion String).

  4. Nell'elenco Ambito selezionare Applicazione.

  5. Nella colonna Valore immettere il stringa di connessione (senza virgolette esterne) e quindi salvare le modifiche.

    Screenshot della stringa di Connessione ion in Impostazioni.settings

Nota

In un'applicazione reale è consigliabile archiviare i stringa di connessione in modo sicuro, come descritto in stringhe di Connessione e file di configurazione.

Scrivere il codice per i form

Questa sezione contiene brevi panoramiche sulle operazioni di ogni modulo. Fornisce inoltre il codice che definisce la logica sottostante quando si fa clic su un pulsante nel modulo.

Quando si esegue l'applicazione, verrà visualizzato il form Navigazione. Il pulsante Aggiungi un account consente di aprire il form NewCustomer. Il pulsante Completare o annullare gli ordini consente di aprire il form FillOrCancel. Il pulsante Esci consente di chiudere l'applicazione.

Impostare il form Navigazione come form di avvio

Se si usa C#, in Esplora soluzioni aprire Program.cs e modificare la riga Application.Run nel seguente modo: Application.Run(new Navigation());

Se si usa Visual Basic, in Esplora soluzioni aprire la finestra Proprietà, selezionare la scheda Applicazione e quindi selezionare SimpleDataApp.Navigation nell'elenco Modulo di avvio.

Creare gestori eventi generati automaticamente

Fare doppio clic sui tre pulsanti nel modulo di spostamento per creare metodi del gestore eventi vuoti. Facendo doppio clic sui pulsanti viene aggiunto anche il codice generato automaticamente nel file di codice della finestra di progettazione che consente a un pulsante di fare clic per generare un evento.

Nota

Se si ignora l'azione di doppio clic nella finestra di progettazione e si copia semplicemente il codice e lo si incolla nei file di codice, non dimenticare di impostare il gestore eventi sul metodo corretto. È possibile eseguire questa operazione nella finestra Proprietà . Passare alla scheda Eventi (usare il pulsante della barra degli strumenti del fulmine) e cercare il gestore Click .

Aggiungere codice per la logica del modulo di spostamento

Nella tabella codici del modulo di spostamento completare i corpi del metodo per i tre gestori eventi click pulsante, come illustrato nel codice seguente.In the code for the Navigation form, complete the method bodies for the three button-click event handlers as shown in the following code.

/// <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

Il codice per questa esercitazione è disponibile in C# e Visual Basic. Per cambiare il linguaggio di codice in questa pagina tra C# e Visual Basic, usare lo switcher del linguaggio di codice nella parte superiore di ogni esempio di codice.

Form NewCustomer

Quando si immette un nome cliente e quindi si seleziona il pulsante Crea account , il modulo NewCustomer crea un account cliente e SQL Server restituisce un valore IDENTITY come nuovo ID cliente. È quindi possibile effettuare un ordine per il nuovo account specificando un importo e una data dell'ordine e selezionando il pulsante Ordina .

Creare gestori eventi generati automaticamente

Creare un gestore eventi Click vuoto per ogni pulsante nel modulo NewCustomer facendo doppio clic su ognuno dei quattro pulsanti. Facendo doppio clic sui pulsanti viene aggiunto anche il codice generato automaticamente nel file di codice della finestra di progettazione che consente a un pulsante di fare clic per generare un evento.

Aggiungere codice per la logica del modulo NewCustomer

Per completare la logica del modulo NewCustomer, seguire questa procedura.

  1. Inserire lo spazio dei nomi nell'ambito System.Data.SqlClient in modo che non sia necessario qualificare completamente i nomi dei relativi membri.

    using System.Data.SqlClient;
    
  2. Aggiungere alcune variabili e metodi helper alla classe, come illustrato nel codice seguente.

    // 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. Completare i corpi del metodo per i quattro gestori eventi button-click, come illustrato nel codice seguente.

    /// <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();
    }
    

Form FillOrCancel

Il modulo FillOrCancel esegue una query per restituire un ordine quando si immette un ID ordine e quindi si fa clic sul pulsante Trova ordine . La riga restituita viene visualizzata in una griglia di dati di sola lettura. È possibile contrassegnare l'ordine come annullato (X) se si seleziona il pulsante Annulla ordine oppure è possibile contrassegnare l'ordine come riempito (F) se si seleziona il pulsante Ordine di riempimento . Se si seleziona di nuovo il pulsante Trova ordine , viene visualizzata la riga aggiornata.

Creare gestori eventi generati automaticamente

Creare gestori eventi Click vuoti per i quattro pulsanti nel modulo FillOrCancel facendo doppio clic sui pulsanti. Facendo doppio clic sui pulsanti viene aggiunto anche il codice generato automaticamente nel file di codice della finestra di progettazione che consente a un pulsante di fare clic per generare un evento.

Aggiungere codice per la logica del modulo FillOrCancel

Per completare la logica del modulo FillOrCancel, seguire questa procedura.

  1. Inserire i due spazi dei nomi seguenti nell'ambito in modo che non sia necessario qualificare completamente i nomi dei relativi membri.

    using System.Data.SqlClient;
    using System.Text.RegularExpressions;
    
  2. Aggiungere una variabile e un metodo helper alla classe come illustrato nel codice seguente.

    // 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. Completare i corpi del metodo per i quattro gestori eventi button-click, come illustrato nel codice seguente.

    /// <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();
    }
    

Testare l'applicazione

Eseguire l'applicazione e provare a creare alcuni clienti e ordini per verificare che tutto funzioni come previsto. Per verificare che il database venga aggiornato con le modifiche, aprire il nodo Tabelle in Esplora server, fare clic con il pulsante destro del mouse sui nodi Clienti e Ordini e scegliere Mostra dati tabella.