Compartir a través de


Usar consultas parametrizadas con SqlDataSource (C#)

de Scott Mitchell

Descargar PDF

En este tutorial, seguimos examinando el control SqlDataSource y aprendemos a definir consultas parametrizadas. Los parámetros se pueden especificar mediante declaración y mediante programación, y se pueden extraer de una serie de ubicaciones, como la cadena de consulta, el estado de sesión, otros controles, etc.

Introducción

En el tutorial anterior vimos cómo usar el control SqlDataSource para recuperar datos directamente de una base de datos. Con el Asistente para configurar orígenes de datos, podemos elegir la base de datos y luego: elegir las columnas que se devolverán de una tabla o vista; escribir una instrucción SQL personalizada; o utilizar un procedimiento almacenado. Tanto si se seleccionan columnas de una tabla o vista como si se escribe una instrucción SQL personalizada, a la propiedad del SelectCommand control SqlDataSource se le asigna la instrucción SQL SELECT ad hoc resultante y se trata de esta SELECT instrucción que se ejecuta cuando se invoca el método SqlDataSource Select() (ya sea mediante programación o automáticamente desde un control web de datos).

Las instrucciones SQL SELECT usadas en las demostraciones del tutorial anterior carecen WHERE de cláusulas. En una SELECT instrucción, la WHERE cláusula puede usarse para limitar los resultados devueltos. Por ejemplo, para mostrar los nombres de los productos que cuestan más de 50,00 USD, podríamos usar la consulta siguiente:

SELECT ProductName
FROM Products
WHERE UnitPrice > 50.00

Normalmente, algunos orígenes externos determinan los valores usados en una WHERE cláusula, como un valor de cadena de consulta, una variable de sesión o una entrada de usuario de un control web en la página. Idealmente, estas entradas se especifican mediante el uso de parámetros. Con Microsoft SQL Server, los parámetros se indican mediante @parameterName, como en:

SELECT ProductName
FROM Products
WHERE UnitPrice > @Price

SqlDataSource admite consultas parametrizadas, tanto para las instrucciones SELECT como para las instrucciones INSERT, UPDATE y DELETE. Además, los valores de parámetro se pueden extraer automáticamente de una variedad de orígenes la cadena de consulta, el estado de sesión, los controles de la página, etc. o se pueden asignar mediante programación. En este tutorial, veremos cómo definir consultas parametrizadas, así como cómo especificar los valores de parámetro tanto mediante declaración como mediante programación.

Nota:

En el tutorial anterior comparamos objectDataSource, que ha sido nuestra herramienta preferida en los primeros 46 tutoriales con SqlDataSource, teniendo en cuenta sus similitudes conceptuales. Estas similitudes también se extienden a los parámetros. Los parámetros de ObjectDataSource están asignados a los parámetros de entrada de los métodos en la capa de lógica de negocios. Con SqlDataSource, los parámetros se definen directamente dentro de la consulta SQL. Ambos controles tienen colecciones de parámetros para sus Select()métodos , Insert(), Update()y Delete() , y ambos pueden tener estos valores de parámetro rellenados a partir de orígenes predefinidos (valores de cadena de consulta, variables de sesión, etc.) o asignados mediante programación.

Creación de una consulta parametrizada

El Asistente para configurar orígenes de datos del control SqlDataSource ofrece tres vías para definir el comando que se va a ejecutar para recuperar registros de base de datos:

  • Al seleccionar las columnas de una tabla o vista existente,
  • Al escribir una instrucción SQL personalizada, o
  • Al elegir un procedimiento almacenado

Al seleccionar columnas de una tabla o vista existente, los parámetros de la WHERE cláusula deben especificarse mediante el cuadro de diálogo Agregar WHERE cláusula. Sin embargo, al crear una instrucción SQL personalizada, puede escribir los parámetros directamente en la WHERE cláusula (usando @parameterName para indicar cada parámetro). Un procedimiento almacenado consta de una o varias instrucciones SQL y estas instrucciones se pueden parametrizar. Los parámetros usados en las instrucciones SQL, sin embargo, deben pasarse como parámetros de entrada al procedimiento almacenado.

Dado que la creación de una consulta parametrizada depende de cómo se especifica SelectCommand SqlDataSource, veamos los tres enfoques. Para empezar, abra la página ParameterizedQueries.aspx en la carpeta SqlDataSource, arrastre un control SqlDataSource desde las herramientas al Diseñador y establezca su ID a Products25BucksAndUnderDataSource. A continuación, haga clic en el vínculo Configurar origen de datos desde la etiqueta inteligente del control. Seleccione la base de datos para usar (NORTHWINDConnectionString) y haga clic en Siguiente.

Paso 1: Agregar una cláusula WHERE al seleccionar las columnas de una tabla o vista

Al seleccionar los datos que se van a devolver de la base de datos con el control SqlDataSource, el Asistente para configurar orígenes de datos nos permite elegir simplemente las columnas que se van a devolver de una tabla o vista existente (vea la figura 1). Al hacerlo, se compila automáticamente una instrucción SQLSELECT, que es lo que se envía a la base de datos cuando se invoca el método SqlDataSource.Select() Como hicimos en el tutorial anterior, seleccione la tabla Products en la lista desplegable y compruebe las ProductIDcolumnas , ProductNamey UnitPrice .

Selección de las columnas que se van a devolver desde una tabla o vista

Figura 1: Selección de las columnas que se van a devolver de una tabla o vista (haga clic para ver la imagen de tamaño completo)

Para incluir una WHERE cláusula en la SELECT instrucción, haga clic en el botón WHERE, que abre el cuadro de diálogo Agregar cláusula WHERE (vea la figura 2). Para agregar un parámetro para limitar los resultados devueltos por la SELECT consulta, primero elija la columna por la que filtrar los datos. A continuación, elija el operador que se va a usar para filtrar (=, <, <=, >, etc.). Por último, elija el origen del valor del parámetro, como desde la cadena de consulta o el estado de sesión. Después de configurar el parámetro, haga clic en el botón Agregar para incluirlo en la SELECT consulta.

En este ejemplo, vamos a devolver solo los resultados en los que el UnitPrice valor sea menor o igual que 25,00 USD. Por lo tanto, elija UnitPrice en la lista desplegable de Columna y <= en la lista desplegable de Operador. Al usar un valor de parámetro codificado de forma rígida (por ejemplo, $25,00) o si el valor del parámetro se va a especificar mediante programación, seleccione Ninguno en la lista desplegable Origen. A continuación, escriba el valor del parámetro codificado de forma rígida en el cuadro de texto Valor 25.00 y complete el proceso haciendo clic en el botón Agregar.

Limitar los resultados devueltos desde el cuadro de diálogo Agregar cláusula WHERE

Figura 2: Limitar los resultados devueltos desde el cuadro de diálogo Agregar WHERE cláusula (haga clic para ver la imagen de tamaño completo)

Después de agregar el parámetro, haga clic en Aceptar para volver al Asistente para configurar orígenes de datos. La SELECT instrucción de la parte inferior del asistente ahora debe incluir una WHERE cláusula con un parámetro llamado @UnitPrice:

SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)

Nota:

Si especifica varias condiciones en la cláusula WHERE del cuadro de diálogo Agregar cláusula WHERE, el asistente las une con el operador AND. Si necesita incluir un OR en la cláusula WHERE (como WHERE UnitPrice <= @UnitPrice OR Discontinued = 1), tendrá que crear la instrucción SELECT a través de la pantalla de instrucciones SQL personalizadas.

Complete la configuración de SqlDataSource (haga clic en Siguiente y, a continuación, en Finalizar) y, a continuación, inspeccione el marcado declarativo de SqlDataSource. El marcado ahora incluye una colección <SelectParameters>, que detalla las fuentes de los parámetros en SelectCommand.

<asp:SqlDataSource ID="Products25BucksAndUnderDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice]
        FROM [Products] WHERE ([UnitPrice] <= @UnitPrice)">
    <SelectParameters>
        <asp:Parameter DefaultValue="25.00" Name="UnitPrice" Type="Decimal" />
    </SelectParameters>
</asp:SqlDataSource>

Cuando se invoca el método Select() de SqlDataSource, el valor del parámetro UnitPrice (25.00) se aplica al parámetro @UnitPrice en SelectCommand antes de enviarse a la base de datos. El resultado neto es que solo se devuelven de la Products tabla los productos menores o iguales a 25,00 USD. Para confirmarlo, agregue una clase GridView a la página, vincule a este origen de datos y, a continuación, vea la página a través de un explorador. Solo debería ver los productos enumerados que son menores o iguales a 25,00 USD, como confirma la figura 3.

Solo se muestran los productos menores o iguales a 25,00 USD.

Figura 3: Solo se muestran los productos menores o iguales a 25,00 USD (haga clic para ver la imagen de tamaño completo)

Paso 2: Agregar parámetros a una instrucción SQL personalizada

Al agregar una instrucción SQL personalizada, puede especificar explícitamente la WHERE cláusula o especificar un valor en la celda Filtro del Generador de consultas. Para demostrar esto, vamos a mostrar solo esos productos en un GridView cuyos precios son inferiores a un umbral determinado. Empiece agregando un TextBox a la ParameterizedQueries.aspx página para recopilar este valor de umbral del usuario. Establezca la propiedad ID del TextBox en MaxPrice. Agregue un control Web Button y establezca su Text propiedad en Mostrar productos coincidentes.

A continuación, arrastre gridView a la página y, desde su etiqueta inteligente, elija crear un nuevo objeto SqlDataSource denominado ProductsFilteredByPriceDataSource. En el Asistente para configurar orígenes de datos, vaya a la pantalla Especificar una instrucción SQL personalizada o un procedimiento almacenado (vea la figura 4) y escriba la consulta siguiente:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice

Después de escribir la consulta (manualmente o a través del Generador de consultas), haga clic en Siguiente.

Devolver solo esos productos menores o iguales a un valor de parámetro

Figura 4: Devolver solo los productos menores o iguales a un valor de parámetro (haga clic para ver la imagen de tamaño completo)

Dado que la consulta incluye parámetros, la siguiente pantalla del asistente nos pide el origen de los valores de parámetros. Elija Control en la lista desplegable fuente de parámetro y MaxPrice (el valor del control ID TextBox) en la lista desplegable ControlID. También puede escribir un valor predeterminado opcional que se usará en el caso de que el usuario no haya escrito ningún texto en el MaxPrice TextBox. Por el momento, no escriba un valor predeterminado.

La propiedad Text de la TextBox MaxPrice se usa como el origen del parámetro.

Figura 5: La MaxPrice propiedad textbox s Text se usa como origen de parámetros (haga clic para ver la imagen de tamaño completo)

Complete el Asistente para configurar orígenes de datos; para ello, haga clic en Siguiente y, a continuación, en Finalizar. A continuación se muestra el marcado declarativo para GridView, TextBox, Button y SqlDataSource:

Maximum price:
$<asp:TextBox ID="MaxPrice" runat="server" Columns="5" />
 
<asp:Button ID="DisplayProductsLessThanButton" runat="server"
    Text="Display Matching Products" />
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataSourceID="ProductsFilteredByPriceDataSource" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            HtmlEncode="False" DataFormatString="{0:c}"
            SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsFilteredByPriceDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT ProductName, UnitPrice 
        FROM Products WHERE UnitPrice <= @MaximumPrice">
    <SelectParameters>
        <asp:ControlParameter ControlID="MaxPrice" Name="MaximumPrice"
            PropertyName="Text" />
    </SelectParameters>
</asp:SqlDataSource>

Tenga en cuenta que el parámetro dentro de la sección SqlDataSource es un <SelectParameters>, que incluye propiedades adicionales como ControlParameter y ControlID. Cuando se invoca el método SqlDataSourceSelect(), ControlParameter toma el valor de la propiedad de control web especificada y lo asigna al parámetro correspondiente en .SelectCommand En este ejemplo, la MaxPrice propiedad Text se usa como valor del parámetro @MaxPrice.

Dedique un minuto a ver esta página a través de un explorador. Cuando se visita por primera vez la página o cada vez que textBox MaxPrice carece de un valor, no se muestran registros en GridView.

No se muestran registros cuando el cuadro de texto MaxPrice está vacío

Figura 6: No se muestran registros cuando el MaxPrice cuadro de texto está vacío (haga clic para ver la imagen de tamaño completo)

El motivo por el que no se muestra ningún producto es porque, de forma predeterminada, se convierte una cadena vacía para un valor de parámetro en un valor de base de datos NULL . Puesto que la comparación de [UnitPrice] <= NULL siempre se evalúa como False, no se devuelve ningún resultado.

Escriba un valor en el cuadro de texto, como 5.00, y haga clic en el botón Mostrar productos coincidentes. En postback, SqlDataSource informa a GridView de que uno de sus orígenes de parámetros ha cambiado. Por lo tanto, GridView se vuelve a enlazar con SqlDataSource, mostrando esos productos con un precio de $5,00 o menos.

Se muestran productos menores o iguales a 5,00 USD.

Figura 7: Se muestran los productos menores o iguales a 5,00 USD (haga clic para ver la imagen de tamaño completo)

Mostrar inicialmente todos los productos

En lugar de mostrar ningún producto cuando la página se carga por primera vez, es posible que deseemos mostrar todos los productos. Una manera de enumerar todos los productos siempre que textBox MaxPrice está vacío es establecer el valor predeterminado del parámetro en algún valor insanemente alto, como 10000000, ya que es poco probable que Northwind Traders tenga inventario cuyo precio unitario supere los 1000 000 000 USD. Sin embargo, este enfoque es miope y podría no funcionar en otras situaciones.

En tutoriales anteriores - Parámetros Declarativos y Filtrado Maestro/Detalle Con Una Lista Desplegable nos hemos enfrentado a un problema similar. Nuestra solución fue poner esta lógica en la capa lógica de negocios. En concreto, el BLL examinó el valor entrante y, si era NULL o algún valor reservado, la llamada se enrutaba al método DAL que devolvía todos los registros. Si el valor entrante era un valor de filtrado normal, se realizó una llamada al método DAL que ejecutó una instrucción SQL que usó una cláusula parametrizada WHERE con el valor proporcionado.

Desafortunadamente, se omite la arquitectura al usar SqlDataSource. En su lugar, es necesario personalizar la instrucción SQL para capturar de forma inteligente todos los registros si el @MaximumPrice parámetro es NULL o algún valor reservado. Para este ejercicio, vamos a tenerlo para que, si el @MaximumPrice parámetro es igual a -1.0, se devolverán todos los registros (-1.0 funciona como un valor reservado, ya que ningún producto puede tener un valor negativo UnitPrice ). Para ello, podemos usar la siguiente instrucción SQL:

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0

Esta WHERE cláusula devuelve todos los registros si el @MaximumPrice parámetro es igual a -1.0. Si el valor del parámetro no -1.0es , solo se devuelven los productos cuyo UnitPrice valor sea menor o igual que el valor del @MaximumPrice parámetro. Al establecer el valor predeterminado del parámetro @MaximumPrice a -1.0, en la primera carga de la página (o siempre que el MaxPrice TextBox esté vacío), @MaximumPrice tendrá un valor de -1.0 y se mostrarán todos los productos.

Ahora todos los productos se muestran cuando el cuadro de texto MaxPrice está vacío

Figura 8: Ahora todos los productos se muestran cuando textBox MaxPrice está vacío (haga clic para ver la imagen de tamaño completo)

Hay un par de advertencias que se deben tener en cuenta con este enfoque. En primer lugar, tenga en cuenta que el tipo de datos del parámetro se deduce por su uso en la consulta SQL. Si cambia la cláusula de WHERE de @MaximumPrice = -1.0 a @MaximumPrice = -1, el entorno de ejecución trata el parámetro como un entero. Si, a continuación, intenta asignar textBox MaxPrice a un valor decimal (como 5,00 ), se producirá un error porque no puede convertir 5,00 en un entero. Para solucionar este problema, asegúrese de usar @MaximumPrice = -1.0 en la cláusula WHERE o, mejor aún, establezca la propiedad ControlParameter del objeto Type en Decimal.

En segundo lugar, al agregar el OR @MaximumPrice = -1.0 a la cláusula WHERE, el motor de consultas no puede usar un índice en UnitPrice (suponiendo que exista uno), lo que da lugar a un escaneo de tabla. Esto puede afectar al rendimiento si hay un número suficientemente grande de registros en la Products tabla. Un mejor enfoque sería mover esta lógica a un procedimiento almacenado en el que una IF instrucción realizaría una SELECT consulta desde la Products tabla sin una WHERE cláusula cuando se deban devolver todos los registros o una cuya WHERE cláusula contiene solo los UnitPrice criterios, de modo que se pueda usar un índice.

Paso 3: Crear y usar procedimientos almacenados con parámetros

Los procedimientos almacenados pueden incluir un conjunto de parámetros de entrada que se pueden usar en las instrucciones SQL definidas en el procedimiento almacenado. Al configurar SqlDataSource para usar un procedimiento almacenado que acepta parámetros de entrada, estos valores de parámetro se pueden especificar mediante las mismas técnicas que con instrucciones SQL ad hoc.

Para ilustrar el uso de procedimientos almacenados en SqlDataSource, vamos a crear un nuevo procedimiento almacenado en la base de datos Northwind denominada GetProductsByCategory, que acepta un parámetro denominado @CategoryID y devuelve todas las columnas de los productos cuya CategoryID columna coincide @CategoryIDcon . Para crear un procedimiento almacenado, vaya al Explorador de servidores y explore en profundidad la NORTHWND.MDF base de datos. (Si no ve el Explorador de servidores, ábralo yendo al menú "Ver" y seleccionando la opción Explorador de servidores).

En la base de datos, haga clic con el NORTHWND.MDF botón derecho en la carpeta Procedimientos almacenados, elija Agregar nuevo procedimiento almacenado y escriba la sintaxis siguiente:

CREATE PROCEDURE dbo.GetProductsByCategory
(
      @CategoryID int
)
AS
SELECT *
FROM Products
WHERE CategoryID = @CategoryID

Haga clic en el icono Guardar (o Ctrl+S) para guardar el procedimiento almacenado. Para probar el procedimiento almacenado, haga clic con el botón derecho en él en la carpeta Procedimientos almacenados y elija Ejecutar. Esto le pedirá los parámetros del procedimiento almacenado (@CategoryID, en esta instancia), después de lo cual los resultados se mostrarán en la ventana Salida.

Procedimiento almacenado GetProductsByCategory cuando se ejecuta con una clase <span= @CategoryID de 1" />

Figura 9: Procedimiento GetProductsByCategory almacenado cuando se ejecuta con un @CategoryID de 1 (haga clic para ver la imagen de tamaño completo)

Vamos a usar este procedimiento almacenado para mostrar todos los productos de la categoría Bebidas en un GridView. Agregue una nueva clase GridView a la página y enlazarla a un nuevo objeto SqlDataSource denominado BeverageProductsDataSource. Continúe con la pantalla Especificar una instrucción SQL personalizada o un procedimiento almacenado, seleccione el botón de radio Procedimiento almacenado y elija el GetProductsByCategory procedimiento almacenado en la lista desplegable.

Seleccione el procedimiento almacenado GetProductsByCategory en la lista de Drop-Down

Figura 10: Seleccionar el procedimiento almacenado en la lista de Drop-Down (GetProductsByCategory la imagen de tamaño completo)

Dado que el procedimiento almacenado acepta un parámetro de entrada (@CategoryID), al hacer clic en Siguiente se nos pide que especifiquemos el origen para este valor de parámetro. La bebida CategoryID es 1, por lo que deje la lista desplegable del origen del parámetro en Ninguno y escriba 1 en el cuadro de texto ValorPredeterminado.

Utilice un valor de Hard-Coded de 1 para devolver los productos de la categoría bebidas

Figura 11: Usar un valor de Hard-Coded de 1 para devolver los productos en la categoría bebidas (haga clic para ver la imagen de tamaño completo)

Como se muestra en el marcado declarativo siguiente, cuando se usa un procedimiento almacenado, la propiedad SqlDataSource se establece en SelectCommand el nombre del procedimiento almacenado y la SelectCommandType propiedad se establece en StoredProcedure, lo que indica que SelectCommand representa un procedimiento almacenado en lugar de una instrucción SQL ad hoc.

<asp:SqlDataSource ID="BeverageProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Pruebe la página en un explorador. Solo se muestran los productos que pertenecen a la categoría Bebidas, aunque se muestran todos los campos de producto, ya que el GetProductsByCategory procedimiento almacenado devuelve todas las columnas de la Products tabla. Por supuesto, podríamos limitar o personalizar los campos mostrados en GridView desde el cuadro de diálogo Editar columnas de GridView.

Se muestran todas las bebidas

Figura 12: Se muestran todas las bebidas (haga clic para ver la imagen de tamaño completo)

Paso 4: Invocación mediante programación de una instrucción Select() de SqlDataSource

Los ejemplos que hemos visto en el tutorial anterior y este tutorial hasta ahora han enlazado controles SqlDataSource directamente a gridView. Sin embargo, los datos del control SqlDataSource se pueden tener acceso mediante programación y enumerarse en el código. Esto puede ser especialmente útil cuando necesita consultar datos para inspeccionarlos, pero no es necesario mostrarlos. En lugar de tener que escribir todo el código reutilizable ADO.NET para conectarse a la base de datos, especificar el comando y recuperar los resultados, puede permitir que SqlDataSource controle este código monotono.

Para ilustrar cómo trabajar con los datos de SqlDataSource mediante programación, imagine que su jefe se ha acercado a usted con una solicitud para crear una página web que muestre el nombre de una categoría seleccionada aleatoriamente y sus productos asociados. Es decir, cuando un usuario visita esta página, queremos elegir aleatoriamente una categoría de la Categories tabla, mostrar el nombre de categoría y, a continuación, enumerar los productos que pertenecen a esa categoría.

Para ello, necesitamos dos controles SqlDataSource uno para obtener una categoría aleatoria de la Categories tabla y otra para obtener los productos de la categoría. Construiremos el SqlDataSource que recupera un registro de categoría aleatorio en este paso; En el paso 5 analizaremos la creación del objeto SqlDataSource que recupera los productos de la categoría.

Empiece agregando un SqlDataSource a ParameterizedQueries.aspx y establezca su propiedad ID a RandomCategoryDataSource. Configúrelo para que use la siguiente consulta SQL:

SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()

ORDER BY NEWID() devuelve los registros ordenados en orden aleatorio (vea Using NEWID() to Randomly Sort Records). SELECT TOP 1 devuelve el primer registro del conjunto de resultados. En conjunto, esta consulta devuelve los CategoryID valores de columna y CategoryName de una sola categoría seleccionada aleatoriamente.

Para mostrar el valor de la categoría CategoryName, agregue un control Web de etiqueta a la página, establezca su propiedad ID en CategoryNameLabel y borre su propiedad Text. Para recuperar mediante programación los datos de un control SqlDataSource, es necesario invocar su Select() método. El Select() método espera un único parámetro de entrada de tipo DataSourceSelectArguments, que especifica cómo se deben enviar mensajes a los datos antes de devolverse. Esto puede incluir instrucciones sobre la ordenación y el filtrado de los datos, y son usadas por los controles web de datos al ordenar o paginar datos desde un control SqlDataSource. Sin embargo, en nuestro ejemplo no es necesario modificar los datos antes de devolverlos y, por tanto, pasaremos el objeto DataSourceSelectArguments.Empty.

El Select() método devuelve un objeto que implementa IEnumerable. El tipo preciso devuelto depende del valor de la propiedad DataSourceMode del control SqlDataSource . Como se explicó en el tutorial anterior, esta propiedad se puede establecer en un valor de DataSet o DataReader. Si se establece en DataSet, el Select() método devuelve un objeto DataView ; si se establece en DataReader, devuelve un objeto que implementa IDataReader. Dado que RandomCategoryDataSource SqlDataSource tiene su DataSourceMode propiedad establecida en DataSet (valor predeterminado), trabajaremos con un objeto DataView.

En el siguiente código se ilustra cómo recuperar los registros de RandomCategoryDataSource SqlDataSource como DataView, así como cómo leer el valor de la columna CategoryName de la primera fila de DataView.

protected void Page_Load(object sender, EventArgs e)
{
    // Get the data from the SqlDataSource as a DataView
    DataView randomCategoryView =
        (DataView)RandomCategoryDataSource.Select(DataSourceSelectArguments.Empty);
    if (randomCategoryView.Count > 0)
    {
        // Assign the CategoryName value to the Label
        CategoryNameLabel.Text =
            string.Format("Here are Products in the {0} Category...",
                randomCategoryView[0]["CategoryName"].ToString());
    }
}

randomCategoryView[0] devuelve el primer DataRowView en la DataView. randomCategoryView[0]["CategoryName"] devuelve el valor de la CategoryName columna en esta primera fila. Tenga en cuenta que dataView está escrito de forma flexible. Para hacer referencia a un valor de columna determinado, es necesario pasar el nombre de la columna como una cadena ( CategoryName, en este caso). En la figura 13 se muestra el mensaje que se muestra cuando se visualiza la página en el CategoryNameLabel. Por supuesto, el nombre de categoría real que se muestra está seleccionado aleatoriamente por SqlDataSource RandomCategoryDataSource en cada visita a la página (incluidos los postbacks).

Se muestra el nombre de la categoría seleccionada aleatoriamente.

Figura 13: Se muestra el nombre de la categoría seleccionada aleatoriamente (haga clic para ver la imagen de tamaño completo)

Nota:

Si se hubiera establecido la propiedad del control SqlDataSource en DataSourceMode, el valor devuelto del método DataReader tendría que convertirse en Select(). Para leer el CategoryName valor de columna de la primera fila, usaríamos código como:

if (randomCategoryReader.Read())
{
   string categoryName = randomCategoryReader["CategoryName"].ToString();
   ...
}

Con sqlDataSource seleccionando aleatoriamente una categoría, estamos listos para agregar gridView que enumera los productos de la categoría.

Nota:

En lugar de usar un control Web de etiqueta para mostrar el nombre de la categoría, podríamos haber agregado un FormView o DetailsView a la página, enlazándolo a la SqlDataSource. Sin embargo, el uso de la etiqueta nos permitió explorar cómo invocar mediante programación la instrucción SqlDataSource y Select() trabajar con sus datos resultantes en el código.

Paso 5: Asignar valores de parámetro mediante programación

Todos los ejemplos que hemos visto hasta ahora en este tutorial han usado un valor de parámetro codificado de forma rígida o uno tomado de uno de los orígenes de parámetros predefinidos (un valor de cadena de consulta, un control web en la página, etc.). Sin embargo, los parámetros del control SqlDataSource también se pueden establecer mediante programación. Para completar nuestro ejemplo actual, necesitamos un objeto SqlDataSource que devuelva todos los productos que pertenecen a una categoría especificada. Este objeto SqlDataSource tendrá un CategoryID parámetro cuyo valor debe establecerse en función del CategoryID valor de columna devuelto por RandomCategoryDataSource SqlDataSource en el Page_Load controlador de eventos.

Comience agregando una clase GridView a la página y enlazarla a un nuevo objeto SqlDataSource denominado ProductsByCategoryDataSource. Al igual que hicimos en el paso 3, configure SqlDataSource para que invoque el GetProductsByCategory procedimiento almacenado. Deje la lista desplegable Origen de parámetros establecida en Ninguno, pero no escriba un valor predeterminado, ya que estableceremos este valor predeterminado mediante programación.

Captura de pantalla que muestra la ventana Configurar origen de datos con el origen de parámetro establecido en Ninguno.

Figura 14: No especificar un origen de parámetro o un valor predeterminado (haga clic para ver la imagen de tamaño completo)

Después de completar el asistente SqlDataSource, el marcado declarativo resultante debe ser similar al siguiente:

<asp:SqlDataSource ID="ProductsByCategoryDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

Podemos asignar el DefaultValue del parámetro CategoryID mediante programación en el Page_Load controlador de eventos.

// Assign the ProductsByCategoryDataSource's
// CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
    randomCategoryView[0]["CategoryID"].ToString();

Con esta adición, la página incluye un GridView que muestra los productos asociados a la categoría seleccionada aleatoriamente.

Captura de pantalla que muestra la página de su categoría seleccionada aleatoriamente.

Figura 15: No especificar un origen de parámetro o un valor predeterminado (haga clic para ver la imagen de tamaño completo)

Resumen

SqlDataSource permite a los desarrolladores de páginas definir consultas parametrizadas cuyos valores de parámetro se pueden codificar de forma rígida, extraerse de orígenes de parámetros predefinidos o asignarlos mediante programación. En este tutorial hemos visto cómo crear una consulta parametrizada desde el Asistente para configurar orígenes de datos para consultas SQL ad hoc y procedimientos almacenados. También hemos examinado el uso de orígenes de parámetros codificados de forma rígida, un control web como origen de parámetros y especificando mediante programación el valor del parámetro.

Al igual que con ObjectDataSource, SqlDataSource también proporciona funcionalidades para modificar sus datos subyacentes. En el siguiente tutorial veremos cómo definir las instrucciones INSERT, UPDATE y DELETE con SqlDataSource. Una vez agregadas estas instrucciones, podemos usar las características integradas de inserción, edición y eliminación inherentes a los controles GridView, DetailsView y FormView.

¡Feliz programación!

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 en 24 horas. Se puede contactar con él en mitchell@4GuysFromRolla.com.

Agradecimientos especiales a

Esta serie de tutoriales contó con la revisión de muchos revisores que fueron de gran ayuda. Los revisores principales de este tutorial fueron Scott Clyde, Randell Schmidt y Ken Pespisa. ¿Le interesa revisar mis próximos artículos en MSDN? Si es así, mándame un mensaje a mitchell@4GuysFromRolla.com.