Introducción al trabajo con una base de datos en sitios de ASP.NET Web Pages (Razor)

por Tom FitzMacken

En este artículo se describe cómo usar las herramientas de Microsoft WebMatrix para crear una base de datos en un sitio web de ASP.NET Web Pages (Razor) y cómo crear páginas que le permiten mostrar, agregar, editar y eliminar datos.

Aprenderá lo siguiente:

  • Creación de una base de datos
  • Conexión a una base de datos
  • Visualización de los datos en una página web
  • Inserción, actualización y eliminación de registros de base de datos

Estas son las características que se presentan en el artículo:

  • Trabajo con una base de datos de Microsoft SQL Server Compact Edition
  • Trabajo con consultas SQL
  • La clase Database.

Versiones de software usadas en el tutorial

  • ASP.NET Web Pages (Razor) 2
  • WebMatrix 2

Este tutorial también funciona con WebMatrix 3. Puede usar ASP.NET Web Pages 3 y Visual Studio 2013 (o Visual Studio Express 2013 para Web); sin embargo, la interfaz de usuario será diferente.

Introducción a las bases de datos

Imagine una libreta de direcciones típica. Para cada entrada de la libreta de direcciones (es decir, para cada persona) tiene varios datos, como el nombre, los apellidos, la dirección, la dirección de correo electrónico y el número de teléfono.

Una manera típica de imagen de datos como esta es como una tabla con filas y columnas. En términos de base de datos, cada fila se conoce a menudo como un registro. Cada columna (a veces denominada campos) contiene un valor para cada tipo de datos: nombre, apellido, etc.

ID Nombre Apellidos Dirección Correo electrónico Teléfono
1 Jim Abrus 210 100th St SE Orcas WA 98031 jim@contoso.com 555 0100
2 Terry Adams 1234 Main St. Seattle WA 99011 terry@cohowinery.com 555 0101

En la mayoría de las tablas de bases de datos, la tabla debe tener una columna que contenga un valor único, como un número de cliente, un número de cuenta, etc. Esto se conoce como clave principal de la tabla y se utiliza para identificar cada fila de la tabla. En el ejemplo, la columna ID es la clave principal de la libreta de direcciones.

Con esta comprensión básica de las bases de datos, ya se tiene todo preparado para aprender a crear una base de datos sencilla y realizar operaciones como agregar, modificar y eliminar datos.

Sugerencia

Bases de datos relacionales

Puede almacenar datos de muchas maneras, incluidos archivos de texto y hojas de cálculo. Sin embargo, para la mayoría de los usos empresariales, los datos se almacenan en una base de datos relacional.

En este artículo no se profundiza mucho en las bases de datos. Sin embargo, es posible que le resulte útil saber un poco sobre ellas. En una base de datos relacional, la información se divide lógicamente en tablas independientes. Por ejemplo, una base de datos para una escuela podría contener tablas independientes para los alumnos y para las ofertas de clase. El software de base de datos (como SQL Server) admite comandos eficaces que permiten establecer dinámicamente relaciones entre las tablas. Por ejemplo, puede usar la base de datos relacional para establecer una relación lógica entre alumnos y clases con el fin de crear una programación. El almacenamiento de datos en tablas independientes reduce la complejidad de la estructura de la tabla y reduce la necesidad de mantener los datos redundantes en las tablas.

Crear una base de datos

En este procedimiento se muestra cómo crear una base de datos denominada SmallBakery mediante la herramienta de diseño de base de datos de SQL Server Compact que se incluye en WebMatrix. Aunque puede crear una base de datos mediante código, es más habitual crear la base de datos y las tablas de base de datos mediante una herramienta de diseño como WebMatrix.

  1. Inicie WebMatrix y, en la página Inicio rápido, haga clic en Sitio desde plantilla.

  2. Seleccione Sitio vacío y, en el cuadro Nombre del sitio, escriba "SmallBakery" y, a continuación, haga clic en Aceptar. El sitio se crea y se muestra en WebMatrix.

  3. En el panel izquierdo, haga clic en el área de trabajo Base de datos.

  4. En la cinta de opciones, haga clic en Nueva base de datos. Se crea una base de datos vacía con el mismo nombre que el sitio.

  5. En el panel izquierdo, expanda el nodo SmallBakery.sdf y, a continuación, haga clic en Tablas.

  6. En la cinta de opciones, haga clic en Nueva tabla. WebMatrix abre el diseñador de tablas en una nueva pestaña.

    [Screenshot shows Web Matrix opening the table designer.]

  7. Haga clic en la columna Name y escriba "Id".

  8. En la columna Tipo de datos, seleccione int.

  9. Establezca las opciones ¿Es la clave principal? e ¿Identificar? en .

    Como sugiere el nombre, Is Primary Key indica a la base de datos que será la clave principal de la tabla. Identificar indica a la base de datos que cree automáticamente un número de identificador para cada registro nuevo y asígnele el siguiente número secuencial (a partir de 1).

  10. Haga clic en la fila siguiente. El editor inicia una nueva definición de columna.

  11. En el valor Nombre, escriba "Name".

  12. En Tipo de datos, elija "nvarchar" y establezca la longitud en 50. La parte var de nvarchar indica a la base de datos que los datos de esta columna serán una cadena cuyo tamaño puede variar de un registro a otro. (El prefijo n representa nacional, lo que indica que el campo puede contener datos de caracteres para cualquier alfabeto o sistema de escritura, es decir, el campo contiene datos Unicode).

  13. Establezca la opción Permitir valores null en No. Esto aplicará que la columna Name no quede en blanco.

  14. Con este mismo proceso, cree una columna denominada Description. Establezca Tipo de datos en "nvarchar" y 50 para la longitud, y Permitir valores null en false.

  15. Cree una columna denominada Price. Establezca Tipo de datos en "money" y Permitir valores null en false.

  16. En el cuadro de la parte superior, asigne un nombre a la tabla "Product".

    Cuando haya terminado, la definición tendrá este aspecto:

    [Screenshot shows what the definition will look like when finished.]

  17. Presione CTRL+S para guardar la tabla.

Adición de datos a la base de datos

Ahora puede agregar algunos datos de ejemplo a la base de datos con los que trabajará más adelante en el artículo.

  1. En el panel izquierdo, expanda el nodo SmallBakery.sdf y, a continuación, haga clic en Tablas.

  2. Haga clic con el botón derecho en la tabla Product y, a continuación, haga clic en Datos.

  3. En el panel de edición, escriba los siguientes registros:

    Nombre Descripción Precio
    Pan Recién horneado todos los días 2,99
    Tarta de fresa Hecha con fresas orgánicas de nuestro jardín 9,99
    Tarta de manzana La mejor después de la de nuestra madre 12.99
    Tarta de nueces Si le gustan las nueces, esta es para usted. 10,99
    Tarta de limón Hecha con los mejores limones del mundo 11.99
    Magdalenas A sus hijos y al niño que hay en usted le encantarán. 7,99

    Recuerde que no tiene que escribir nada en la columna Id. Al crear la columna Id, se establece su propiedad Identificar en true, lo que hace que se rellene automáticamente.

    Cuando haya terminado de escribir los datos, el diseñador de tablas tendrá este aspecto:

    [Screenshot shows what the table designer will look like when the data is finished being entered.]

  4. Cierre la pestaña que contiene el diseñador de la base de datos.

Visualización de datos desde una base de datos

Cuando tenga una base de datos con datos en ella, puede mostrar los datos en una página web de ASP.NET. Para seleccionar las filas de tabla que se van a mostrar, use una instrucción SQL, que es un comando que se pasa a la base de datos.

  1. En el panel izquierdo, haga clic en el área de trabajo Archivos.

  2. En la raíz del sitio web, cree una nueva página CSHTML denominada ListProducts.cshtml.

  3. Reemplace el marcado existente por lo siguiente:

    @{
        var db = Database.Open("SmallBakery");
        var selectQueryString = "SELECT * FROM Product ORDER BY Name";
     }
    <!DOCTYPE html>
    <html>
     <head>
       <title>Small Bakery Products</title>
       <style>
           table, th, td {
             border: solid 1px #bbbbbb;
             border-collapse: collapse;
             padding: 2px;
           }
        </style>
     </head>
     <body>
       <h1>Small Bakery Products</h1>
       <table>
           <thead>
               <tr>
                   <th>Id</th>
                   <th>Product</th>
                   <th>Description</th>
           <th>Price</th>
               </tr>
           </thead>
           <tbody>
               @foreach(var row in db.Query(selectQueryString)){
                <tr>
                   <td>@row.Id</td>
                       <td>@row.Name</td>
                       <td>@row.Description</td>
                       <td>@row.Price</td>
                </tr>
               }
           </tbody>
       </table>
     </body>
    </html>
    

    En el primer bloque de código, abra el archivo SmallBakery.sdf (base de datos) que creó anteriormente. El método Database.Open supone que el archivo .sdf está en la carpeta App_Data del sitio web. (Tenga en cuenta que no es necesario especificar la extensión .sdf; de hecho, si lo hace, el método Open no funcionará).

    Nota:

    La carpeta App_Data es una carpeta especial en ASP.NET que se usa para almacenar archivos de datos. Para más información, consulte Conexión a una base de datos más adelante en este artículo.

    A continuación, realice una solicitud para consultar la base de datos mediante la siguiente instrucción SQL Select:

    SELECT * FROM Product ORDER BY Name
    

    En la instrucción, Product identifica la tabla que se va a consultar. El carácter * especifica que la consulta debe devolver todas las columnas de la tabla. (También puede enumerar columnas individualmente, separadas por comas, si quiere ver solo algunas de las columnas). La cláusula Order By indica cómo se deben ordenar los datos; en este caso, por la columna Name. Esto significa que los datos se ordenan alfabéticamente en función del valor de la columna Name para cada fila.

    En el cuerpo de la página, el marcado crea una tabla HTML que se usará para mostrar los datos. Dentro del elemento <tbody>, se usa un bucle foreach para obtener individualmente cada fila de datos devuelta por la consulta. Para cada fila de datos, se crea una fila de tabla HTML (elemento <tr>). A continuación, se crean celdas de tabla HTML (elementos <td>) para cada columna. Cada vez que pase por el bucle, la siguiente fila disponible de la base de datos se encuentra en la variable row (se configura en la instrucción foreach). Para obtener una columna individual de la fila, puede usar row.Name o row.Description, o cualquiera que sea el nombre de la columna que desee.

  4. Ejecute la página en un explorador. (Asegúrese de que la página está seleccionada en el área de trabajo Archivos antes de ejecutarla) La página muestra una lista similar a la siguiente:

    [Screenshot shows the list the page will display in the browser.]

Sugerencia

Lenguaje de consulta más estructurado (SQL)

SQL es un lenguaje que se utiliza en la mayoría de las bases de datos relacionales para administrar los datos de una base de datos. Incluye comandos que permiten recuperar datos y actualizarlos, y que permiten crear, modificar y administrar datos en tablas de bases de datos. SQL es diferente de un lenguaje de programación (como el que usa en WebMatrix) porque, con SQL, la idea es que indique a la base de datos lo que desea y es el trabajo de la base de datos averiguar cómo obtener los datos o realizar la tarea. Estos son unos ejemplos de algunos comandos SQL y lo que hacen:

SELECT Id, Name, Price FROM Product WHERE Price > 10.00 ORDER BY Name

Esto captura las columnas Id, Name y Price de los registros de la tabla Product si el valor de Price es superior a 10 y devuelve los resultados en orden alfabético en función de los valores de la columna Name. Este comando devolverá un conjunto de resultados que contiene los registros que cumplen los criterios o un conjunto vacío si no coinciden registros.

INSERT INTO Product (Name, Description, Price) VALUES ("Croissant", "A flaky delight", 1.99)

Este comando inserta un nuevo registro en la tabla Product, estableciendo la columna Name en "Croissant", la columna Description en "A flaky delight" y el precio en 1,99.

DELETE FROM Product WHERE ExpirationDate < "01/01/2008"

Este comando elimina los registros de la tabla Product cuya columna de fecha de caducidad sea anterior al 1 de enero de 2008. (El comando asume que la tabla Product tiene dicha columna, por supuesto). La fecha se introduce aquí en formato DD/MM/AAAA, pero debe introducirse en el formato que se utilice en su localidad.

Los comandos Insert Into y Delete no devuelven conjuntos de resultados. En su lugar, devuelven un número que indica cuántos registros se han visto afectados por la orden.

Para algunas de estas operaciones (como insertar y eliminar registros), el proceso que solicita la operación debe tener los permisos adecuados en la base de datos. Gracias a esto, las bases de datos de producción suele ser necesario indicar un nombre de usuario y una contraseña al conectarse a la base de datos.

Hay docenas de comandos SQL, pero todos siguen un patrón como este. Puede utilizar comandos SQL para crear tablas de bases de datos, contar el número de registros de una tabla, calcular precios y realizar muchas más operaciones.

Inserción de datos en una base de datos

En esta sección se muestra cómo crear una página que permita a los usuarios agregar un nuevo producto a la tabla de la base de datos Product. Después de insertar un nuevo registro de producto, la página muestra la tabla actualizada con la página ListProducts.cshtml que creó en la sección anterior.

La página incluye validación para asegurarse de que los datos que escribe el usuario son válidos para la base de datos. Por ejemplo, el código de la página garantiza que se ha escrito un valor para todas las columnas necesarias.

  1. En el sitio web, cree un nuevo archivo CSHTML denominado InsertProducts.cshtml.

  2. Reemplace el marcado existente por lo siguiente:

    @{
        Validation.RequireField("Name", "Product name is required.");
        Validation.RequireField("Description", "Product description is required.");
        Validation.RequireField("Price", "Product price is required.");
    
        var db = Database.Open("SmallBakery");
        var Name = Request.Form["Name"];
        var Description = Request.Form["Description"];
        var Price = Request.Form["Price"];
    
        if (IsPost && Validation.IsValid()) {
            // Define the insert query. The values to assign to the
            // columns in the Product table are defined as parameters
            // with the VALUES keyword.
            if(ModelState.IsValid) {
                var insertQuery = "INSERT INTO Product (Name, Description, Price) " +
                    "VALUES (@0, @1, @2)";
                db.Execute(insertQuery, Name, Description, Price);
                // Display the page that lists products.
                Response.Redirect("~/ListProducts");
            }
        }
    }
    
    <!DOCTYPE html>
    <html>
    <head>
     <title>Add Products</title>
     <style type="text/css">
        label {float:left; width: 8em; text-align: right;
               margin-right: 0.5em;}
        fieldset {padding: 1em; border: 1px solid; width: 50em;}
        legend {padding: 2px 4px; border: 1px solid; font-weight:bold;}
        .validation-summary-errors {font-weight:bold; color:red;
               font-size: 11pt;}
     </style>
    </head>
    <body>
     <h1>Add New Product</h1>
    
     @Html.ValidationSummary("Errors with your submission:")
    
     <form method="post" action="">
       <fieldset>
         <legend>Add Product</legend>
         <div>
           <label>Name:</label>
           <input name="Name" type="text" size="50" value="@Name" />
         </div>
         <div>
           <label>Description:</label>
           <input name="Description" type="text" size="50"
               value="@Description" />
         </div>
         <div>
           <label>Price:</label>
           <input name="Price" type="text" size="50" value="@Price" />
         </div>
         <div>
           <label>&nbsp;</label>
           <input type="submit" value="Insert" class="submit" />
         </div>
       </fieldset>
     </form>
    </body>
    </html>
    

    El cuerpo de la página contiene un formulario HTML con tres cuadros de texto que permiten a los usuarios escribir un nombre, una descripción y un precio. Cuando los usuarios hacen clic en el botón Insertar, el código de la parte superior de la página abre una conexión a la base de datos SmallBakery.sdf. A continuación, obtiene los valores que el usuario ha enviado mediante el objeto Request y asigna esos valores a variables locales.

    Para validar que el usuario escribió un valor para cada columna necesaria, registre cada elemento <input> que desee validar:

    Validation.RequireField("Name", "Product name is required.");
    Validation.RequireField("Description", "Product description is required.");
    Validation.RequireField("Price", "Product price is required.");
    

    El asistente Validation comprueba que hay un valor en cada uno de los campos que ha registrado. Puede probar si todos los campos han superado la validación comprobando Validation.IsValid(), lo que suele hacerse antes de procesar la información que obtiene del usuario:

    if (IsPost && Validation.IsValid()) {
        // Process information here
    }
    

    (El operador && significa AND; esta prueba es Si se trata de un envío de formulario Y todos los campos han superado la validación).

    Si todas las columnas están validadas (ninguna estaba vacía), continúe y cree una instrucción SQL para insertar los datos y, a continuación, ejecutarla como se muestra a continuación:

    var insertQuery =
        "INSERT INTO Product (Name, Description, Price) VALUES (@0, @1, @2)";
    

    Para que los valores se inserte, incluya marcadores de posición de parámetros (@0, @1, @2).

    Nota:

    Como precaución de seguridad, pase siempre valores a una instrucción SQL mediante parámetros, como se muestra en el ejemplo anterior. Esto le ofrece la oportunidad de validar los datos del usuario, además de que ayuda a protegerse frente a intentos de enviar comandos malintencionados a la base de datos (a veces denominados ataques por inyección de código SQL).

    Para ejecutar la consulta, use esta instrucción y pase a ella las variables que contienen los valores que se van a sustituir por los marcadores de posición:

    db.Execute(insertQuery, Name, Description, Price);
    

    Una vez ejecutada la instrucción Insert Into, se envía al usuario a la página que muestra los productos mediante esta línea:

    Response.Redirect("~/ListProducts");
    

    Si la validación no se realizó correctamente, omita la inserción. En su lugar, tiene un asistente en la página que puede mostrar los mensajes de error acumulados (si los hay):

    @Html.ValidationSummary("Errors with your submission:")
    

    Observe que el bloque de estilo del marcado incluye una definición de clase CSS denominada .validation-summary-errors. Este es el nombre de la clase CSS que se usa de manera predeterminada para el elemento <div> que contiene los errores de validación. En este caso, la clase CSS especifica que los errores de resumen de validación se muestran en rojo y en negrita, pero puede definir la clase .validation-summary-errors para mostrar cualquier formato que desee.

Prueba de la página Insert

  1. Vea ahora la página en un explorador. La página muestra un formulario similar al que se muestra en la ilustración siguiente.

    [Screenshot shows a form that will display on the page in a browser.]

  2. Escriba los valores de todas las columnas, pero asegúrese de dejar en blanco la columna Price.

  3. Haga clic en Insertar. La página muestra un mensaje de error, como se indica en la ilustración siguiente. (No se crea ningún registro).

    [Screenshot shows an error message.]

  4. Rellene el formulario por completo y, a continuación, haga clic en Insert. Esta vez, se muestra la página ListProducts.cshtml y muestra el nuevo registro.

Actualización de datos de una base de datos

Después de escribir los datos en una tabla, es posible que tenga que actualizarlos. Este procedimiento muestra cómo crear dos páginas similares a las que creó anteriormente para la inserción de datos. La primera página muestra los productos y permite a los usuarios seleccionar uno para cambiar. La segunda página permite a los usuarios realizar las modificaciones y guardarlas.

Nota:

Importante En un sitio web de producción, normalmente restringe quién puede realizar cambios en los datos. Para obtener información sobre cómo configurar la pertenencia y sobre las formas de autorizar a los usuarios a realizar tareas en el sitio, consulte Agregar seguridad y pertenencia a un sitio de ASP.NET Web Pages.

  1. En el sitio web, cree un nuevo archivo CSHTML denominado EditProducts.cshtml.

  2. Reemplace el marcado existente del archivo por el siguiente;

    @{
        var db = Database.Open("SmallBakery");
        var selectQueryString = "SELECT * FROM Product ORDER BY Name";
    
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title>Edit Products</title>
        <style type="text/css">
            table, th, td {
              border: solid 1px #bbbbbb;
              border-collapse: collapse;
              padding: 2px;
            }
        </style>
    </head>
    <body>
        <h1>Edit Small Bakery Products</h1>
        <table>
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Name</th>
              <th>Description</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            @foreach (var row in db.Query(selectQueryString)) {
              <tr>
                <td><a href="@Href("~/UpdateProducts", row.Id)">Edit</a></td>
                <td>@row.Name</td>
                <td>@row.Description</td>
                <td>@row.Price</td>
              </tr>
            }
          </tbody>
        </table>
    </body>
    </html>
    

    La única diferencia entre esta página y la página ListProducts.cshtml anterior es que la tabla HTML de esta página incluye una columna adicional que muestra un vínculo Edit. Al hacer clic en este vínculo, se le lleva a la página UpdateProducts.cshtml (que creará a continuación) donde puede editar el registro seleccionado.

    Examine el código que crea el vínculo Edit:

    <a href="@Href("~/UpdateProducts", row.Id)">Edit</a></td>
    

    Esto crea un elemento <a> HTML cuyo atributo href se establece dinámicamente. El atributo href especifica la página que se va a mostrar cuando el usuario hace clic en el vínculo. También pasa el valor Id de la fila actual al vínculo. Cuando se ejecuta la página, el origen de la página puede contener vínculos como estos:

    <a href="UpdateProducts/1">Edit</a></td>
    <a href="UpdateProducts/2">Edit</a></td>
    <a href="UpdateProducts/3">Edit</a></td>
    

    Observe que el atributo href se establece en UpdateProducts/n, donde n es un número de producto. Cuando un usuario hace clic en uno de estos vínculos, la dirección URL resultante tendrá un aspecto similar al siguiente:

    http://localhost:18816/UpdateProducts/6

    En otras palabras, el número de producto que se va a editar se pasará en la dirección URL.

  3. Vea ahora la página en un explorador. La página muestra los datos en un formato similar al siguiente:

    [Screenshot shows the data displayed on the page in the browser.]

    A continuación, creará la página que permite a los usuarios actualizar realmente los datos. La página de actualización incluye la validación para validar los datos que escribe el usuario. Por ejemplo, el código de la página garantiza que se ha escrito un valor para todas las columnas necesarias.

  4. En el sitio web, cree un nuevo archivo CSHTML denominado UpdateProducts.cshtml.

  5. Reemplace el marcado existente del archivo por el siguiente.

    @{
        Validation.RequireField("Name", "Product name is required.");
        Validation.RequireField("Description", "Product description is required.");
        Validation.RequireField("Price", "Product price is required.");
    
        var Name = "";
        var Description = "";
        var Price = Decimal.Zero;
    
        var ProductId  = UrlData[0];
        if (ProductId.IsEmpty()) {
             Response.Redirect("~/EditProducts");
        }
    
        var db = Database.Open("SmallBakery");
    
        if (IsPost && Validation.IsValid()) {
            var updateQueryString =
                "UPDATE Product SET Name=@0, Description=@1, Price=@2 WHERE Id=@3" ;
            Name = Request["Name"];
            Description = Request["Description"];
            Price = Request["Price"].AsDecimal();
            db.Execute(updateQueryString, Name, Description, Price, ProductId);
            Response.Redirect(@Href("~/EditProducts"));
        }
        else {
            var selectQueryString = "SELECT * FROM Product WHERE Id=@0";
    
            var row = db.QuerySingle(selectQueryString, ProductId);
            Name = row.Name;
            Description = row.Description;
            Price = row.Price;
        }
    
    }
    
    <!DOCTYPE html>
    <html>
    <head>
      <title>Add Products</title>
      <style type="text/css">
         label { float: left; width: 8em; text-align: right;
                 margin-right: 0.5em;}
         fieldset { padding: 1em; border: 1px solid; width: 35em;}
         legend { padding: 2px 4px;  border: 1px solid; font-weight: bold;}
         .validation-summary-errors {font-weight:bold; color:red; font-size:11pt;}
      </style>
    </head>
    <body>
      <h1>Update Product</h1>
       @Html.ValidationSummary("Errors with your submission:")
       <form method="post" action="">
         <fieldset>
           <legend>Update Product</legend>
           <div>
             <label>Name:</label>
             <input name="Name" type="text" size="50" value="@Name" />
           </div>
           <div>
             <label>Description:</label>
             <input name="Description" type="text" size="50"
                value="@Description" />
           </div>
           <div>
              <label>Price:</label>
              <input name="Price" type="text" size="50" value="@Price" />
           </div>
           <div>
              <label>&nbsp;</label>
              <input type="submit" value="Update" class="submit" />
           </div>
        </fieldset>
      </form>
    </body>
    </html>
    

    El cuerpo de la página contiene un formulario HTML donde se muestra un producto y donde los usuarios pueden editarlo. Para que se muestre el producto, use esta instrucción SQL:

    SELECT * FROM Product WHERE Id=@0
    

    Esto seleccionará el producto cuyo identificador coincide con el valor que se pasa en el parámetro @0. (Como Id es la clave principal y, por lo tanto, debe ser único, solo se puede seleccionar un registro de producto de esta manera). Para obtener el valor de identificador que se va a pasar a esta instrucción Select, puede leer el valor que se pasa a la página como parte de la dirección URL mediante la sintaxis siguiente:

    var ProductId  = UrlData[0];
    

    Para capturar realmente el registro del producto, use el método QuerySingle, que devolverá solo un registro:

    var row = db.QuerySingle(selectQueryString, ProductId);
    

    La fila única se devuelve a la variable row. Puede obtener datos de cada columna y asignarlos a variables locales como esta:

    var Name = row.Name;
    var Description = row.Description;
    var Price = row.Price;
    

    En el marcado del formulario, estos valores se muestran automáticamente en cuadros de texto individuales mediante código insertado como el siguiente:

    <input name="Name" type="text" size="50" value="@Name" />
    

    Esa parte del código muestra el registro del producto que se va a actualizar. Una vez que se haya mostrado el registro, el usuario puede editar columnas individuales.

    Cuando el usuario envía el formulario haciendo clic en el botón Actualizar, se ejecuta el código del bloque if(IsPost). Esto obtiene los valores del usuario del objeto Request, almacena los valores en variables y valida que cada columna se ha rellenado. Si se supera la validación, el código crea la siguiente instrucción de actualización de SQL:

    UPDATE Product SET Name=@0, Description=@1, Price=@2, WHERE ID=@3
    

    En una instrucción Update SQL, especifique cada columna en la que se va a actualizar y el valor en el que se va a establecer. En este código, los valores se especifican mediante los marcadores de posición del parámetro @0, @1, @2, etc. (Como se indicó anteriormente, por seguridad, siempre debe pasar valores a una instrucción SQL mediante parámetros).

    Al llamar al método db.Execute, se pasan las variables que contienen los valores en el orden que corresponde a los parámetros de la instrucción SQL:

    db.Execute(updateQueryString, Name, Description, Price, ProductId);
    

    Una vez ejecutada la instrucción Update, llame al método siguiente para redirigir al usuario de nuevo a la página de edición:

    Response.Redirect(@Href("~/EditProducts"));
    

    El efecto es que el usuario ve una lista actualizada de los datos de la base de datos y puede editar otro producto.

  6. Guarde la página.

  7. Ejecute la página EditProducts.cshtml (no la página de actualización) y, a continuación, haga clic en Editar para seleccionar un producto que quiere editar. Aparece la página UpdateProducts.cshtml, que muestra el registro seleccionado.

    [Screenshot shows the Update Products page, along with the selected record.]

  8. Realice un cambio y haga clic en Actualizar. La lista de productos se muestra de nuevo con los datos actualizados.

Eliminación de los datos de una tabla

En esta sección se muestra cómo permitir que los usuarios eliminen un producto de la tabla de base de datos Product. El ejemplo consta de dos páginas. En la primera página, el usuario selecciona el registro que quiere eliminar. El registro que se va a eliminar se muestra en una segunda página que les permite confirmar que quiere eliminar el registro.

Nota:

Importante En un sitio web de producción, normalmente restringe quién puede realizar cambios en los datos. Para obtener información sobre cómo configurar la pertenencia y sobre las formas de autorizar al usuario a realizar tareas en el sitio, consulte Adición de seguridad y pertenencia a un sitio de ASP.NET Web Pages.

  1. En el sitio web, cree un nuevo archivo CSHTML denominado ListProductsForDelete.cshtml.

  2. Reemplace el marcado existente por lo siguiente:

    @{
      var db = Database.Open("SmallBakery");
      var selectQueryString = "SELECT * FROM Product ORDER BY Name";
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title>Delete a Product</title>
        <style>
            table, th, td {
              border: solid 1px #bbbbbb;
              border-collapse: collapse;
              padding: 2px;
            }
         </style>
    </head>
    <body>
      <h1>Delete a Product</h1>
      <form method="post" action="" name="form">
        <table border="1">
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Name</th>
              <th>Description</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            @foreach (var row in db.Query(selectQueryString)) {
              <tr>
                <td><a href="@Href("~/DeleteProduct", row.Id)">Delete</a></td>
                <td>@row.Name</td>
                <td>@row.Description</td>
                <td>@row.Price</td>
              </tr>
            }
          </tbody>
        </table>
      </form>
    </body>
    </html>
    

    Esta página es similar a la página EditProducts.cshtml de la anterior. Sin embargo, en lugar de mostrar un vínculo Edit para cada producto, muestra un vínculo Delete. El vínculo Delete se crea con el siguiente código insertado en el marcado:

    <a href="@Href("~/DeleteProduct", row.Id)">Delete</a>
    

    Esto crea una dirección URL similar a esta cuando los usuarios hacen clic en el vínculo:

    http://<server>/DeleteProduct/4

    La dirección URL llama a una página denominada DeleteProduct.cshtml (que creará a continuación) y la pasa el identificador del producto que se va a eliminar (aquí, 4).

  3. Guarde el archivo, pero déjelo abierto.

  4. Cree otro archivo CHTML denominado DeleteProduct.cshtml. Reemplace el contenido existente por lo siguiente:

    @{
      var db = Database.Open("SmallBakery");
      var ProductId = UrlData[0];
      if (ProductId.IsEmpty()) {
        Response.Redirect("~/ListProductsForDelete");
      }
      var prod = db.QuerySingle("SELECT * FROM PRODUCT WHERE ID = @0", ProductId);
      if( IsPost && !ProductId.IsEmpty()) {
        var deleteQueryString = "DELETE FROM Product WHERE Id=@0";
        db.Execute(deleteQueryString, ProductId);
        Response.Redirect("~/ListProductsForDelete");
      }
    }
    
    <!DOCTYPE html>
    <html>
    <head>
        <title>Delete Product</title>
    </head>
    <body>
      <h1>Delete Product - Confirmation</h1>
      <form method="post" action="" name="form">
        <p>Are you sure you want to delete the following product?</p>
    
        <p>Name: @prod.Name <br />
           Description: @prod.Description <br />
           Price: @prod.Price</p>
        <p><input type="submit" value="Delete" /></p>
      </form>
    </body>
    </html>
    

    ListProductsForDelete.cshtml llama a esta página y permite a los usuarios confirmar que quieren eliminar un producto. Para enumerar el producto que se va a eliminar, obtendrá el identificador del producto que se va a eliminar de la dirección URL mediante el código siguiente:

    var ProductId = UrlData[0];
    

    A continuación, la página pide al usuario que haga clic en un botón para eliminar realmente el registro. Esta es una medida de seguridad importante: al realizar operaciones confidenciales en su sitio web, como actualizar o eliminar datos, estas operaciones siempre deben realizarse mediante una operación POST, no una operación GET. Si el sitio está configurado para que se pueda realizar una operación de eliminación mediante una operación GET, cualquier usuario puede pasar una dirección URL como http://<server>/DeleteProduct/4 y eliminar todo lo que desee de la base de datos. Al agregar la confirmación y codificar la página para que la eliminación solo se pueda realizar mediante POST, agregue una medida de seguridad al sitio.

    La operación de eliminación real se realiza con el código siguiente, que confirma primero que se trata de una operación POST y que el identificador no está vacío:

    if( IsPost && !ProductId.IsEmpty()) {
        var deleteQueryString = "DELETE FROM Product WHERE Id=@0";
        db.Execute(deleteQueryString, ProductId);
        Response.Redirect("~/ListProductsForDelete");
    }
    

    El código ejecuta una instrucción SQL que elimina el registro especificado y, a continuación, redirige al usuario de nuevo a la página de lista.

  5. Ejecute ListProductsForDelete.cshtml en un explorador.

    [Screenshot shows running list products for delete dot CSHTML in the browser.]

  6. Haga clic en el vínculo Eliminar para uno de los productos. Se muestra la página DeleteProduct.cshtml para confirmar que quiere eliminar ese registro.

  7. Haga clic en el botón Eliminar . El registro del producto se elimina y la página se actualiza con una lista de productos actualizada.

Sugerencia

Conectar a una base de datos

El método puede conectarse a una base de datos de dos modos. La primera consiste en usar el método Database.Open y especificar el nombre del archivo de base de datos (menos la extensión .sdf):

var db = Database.Open("SmallBakery");

El método Open supone que el archivo .sdf está en la carpeta App_Data del sitio web. Esta carpeta está diseñada específicamente para contener datos. Por ejemplo, tiene los permisos adecuados para permitir que el sitio web lea y escriba datos, y como medida de seguridad, WebMatrix no permite el acceso a archivos desde esta carpeta.

La segunda forma es usar una cadena de conexión. Una cadena de conexión contiene información sobre cómo conectarse a una base de datos. Esto puede incluir una ruta de archivo o bien el nombre de una base de datos de SQL Server en un servidor local o remoto, junto con un nombre de usuario y contraseña para conectarse con dicho servidor. Si conserva datos en una versión de SQL Server administrada centralmente, como en el sitio de un proveedor de hospedaje, siempre se usa una cadena de conexión para especificar la información de conexión de la base de datos.

En WebMatrix, las cadenas de conexión normalmente se almacenan en un archivo XML denominado Web.config. Como indica el nombre, puede usar un archivo Web.config en la raíz del sitio web para almacenar la información de configuración del sitio, incluidas las cadenas de conexión que el sitio podría necesitar. Un ejemplo de una cadena de conexión en un archivo Web.config podría ser similar al siguiente. Tenga en cuenta que $CREDENTIAL_PLACEHOLDER$ es un marcador de posición para el par clave-valor de contraseña:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
   <add
     name="SQLServerConnectionString"
     connectionString= "server=myServer;database=myDatabase;uid=username;$CREDENTIAL_PLACEHOLDER$"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

En el ejemplo, la cadena de conexión apunta a una base de datos en una instancia de SQL Server que se ejecuta en un servidor en algún lugar (en lugar de un archivo .sdf local). Tendría que sustituir los nombres adecuados para myServer y myDatabase, y especificar los valores de inicio de sesión de SQL Server para username y password. (Los valores de nombre de usuario y contraseña no son necesariamente los mismos que las credenciales de Windows o los valores que el proveedor de hospedaje le ha proporcionado para iniciar sesión en sus servidores. Compruebe con el administrador los valores exactos que necesita).

El método Database.Open es flexible, ya que permite pasar el nombre de un archivo .sdf de base de datos o el nombre de una cadena de conexión almacenado en el archivo Web.config. En el ejemplo siguiente se muestra cómo conectarse a la base de datos mediante la cadena de conexión ilustrada en el ejemplo anterior:

@{
    var db = Database.Open("SQLServerConnectionString");
}

Como se indicó, el método Database.Open le permite pasar un nombre de base de datos o una cadena de conexión, y averiguará qué usar. Esto es muy útil al implementar (publicar) el sitio web. Puede usar un archivo .sdf en la carpeta App_Data al desarrollar y probar el sitio. Después, al mover el sitio a un servidor de producción, puede usar un cadena de conexión en el archivo Web.config que tenga el mismo nombre que el archivo .sdf, pero que apunte a la base de datos del proveedor de hospedaje, todo ello sin tener que cambiar el código.

Por último, si desea trabajar directamente con una cadena de conexión, puede llamar al método Database.OpenConnectionString y pasarlo a la cadena de conexión real en lugar de solo el nombre de uno en el archivo Web.config. Esto puede ser útil en situaciones en las que, por algún motivo, no tiene acceso a la cadena de conexión (o valores en él, como el nombre de archivo .sdf) hasta que se ejecute la página. Sin embargo, para la mayoría de los escenarios, puede usar Database.Open, como se describe en este artículo.

Recursos adicionales