Uso de consultas parametrizadas com o SqlDataSource (C#)
por Scott Mitchell
Neste tutorial, continuamos nossa análise do controle SqlDataSource e aprendemos a definir consultas parametrizadas. Os parâmetros podem ser especificados de forma declarativa e programática e podem ser extraídos de vários locais, como a querystring, o estado de sessão, outros controles e muito mais.
Introdução
No tutorial anterior, vimos como usar o controle SqlDataSource para recuperar dados diretamente de um banco de dados. Usando o assistente Configurar Fonte de Dados, podemos escolher o banco de dados e, em seguida, escolher as colunas para retornar de uma tabela ou exibição; insira uma instrução SQL personalizada; ou use um procedimento armazenado. Seja selecionando colunas de uma tabela ou exibição ou inserindo uma instrução SQL personalizada, a propriedade do SelectCommand
controle SqlDataSource recebe a instrução SQL SELECT
ad hoc resultante e é essa SELECT
instrução executada quando o método sqlDataSource Select()
é invocado (programaticamente ou automaticamente de um controle da Web de dados).
As instruções SQL SELECT
usadas nas demonstrações do tutorial anterior não tinham WHERE
cláusulas. Em uma SELECT
instrução , a WHERE
cláusula pode ser usada para limitar os resultados retornados. Por exemplo, para exibir os nomes de produtos que custam mais de US$ 50,00, poderíamos usar a seguinte consulta:
SELECT ProductName
FROM Products
WHERE UnitPrice > 50.00
Normalmente, os valores usados em uma WHERE
cláusula são determinados por alguma fonte externa, como um valor de querystring, uma variável de sessão ou entrada de usuário de um controle web na página. O ideal é que essas entradas sejam especificadas por meio do uso de parâmetros. Com o Microsoft SQL Server, os parâmetros são indicados usando @parameterName
, como em:
SELECT ProductName
FROM Products
WHERE UnitPrice > @Price
O SqlDataSource dá suporte a consultas parametrizadas, tanto para instruções quanto INSERT
para SELECT
instruções , UPDATE
e DELETE
. Além disso, os valores de parâmetro podem ser extraídos automaticamente de uma variedade de fontes que a querystring, o estado da sessão, os controles na página e assim por diante ou podem ser atribuídos programaticamente. Neste tutorial, veremos como definir consultas parametrizadas, bem como especificar os valores de parâmetro declarativamente e programaticamente.
Observação
No tutorial anterior, comparamos o ObjectDataSource, que foi nossa ferramenta de escolha nos primeiros 46 tutoriais com o SqlDataSource, observando suas semelhanças conceituais. Essas semelhanças também se estendem aos parâmetros. Os parâmetros objectDataSource mapeados para os parâmetros de entrada para os métodos na Camada lógica de negócios. Com o SqlDataSource, os parâmetros são definidos diretamente na consulta SQL. Ambos os controles têm coleções de parâmetros para seus Select()
métodos , Insert()
, Update()
e Delete()
e ambos podem ter esses valores de parâmetro preenchidos de fontes predefinidas (valores de querystring, variáveis de sessão e assim por diante) ou atribuídos programaticamente.
Criando uma consulta parametrizada
O assistente Configurar Fonte de Dados do sqlDataSource oferece três caminhos para definir o comando a ser executado para recuperar registros de banco de dados:
- Escolhendo as colunas de uma tabela ou exibição existente,
- Inserindo uma instrução SQL personalizada ou
- Escolhendo um procedimento armazenado
Ao escolher colunas de uma tabela ou exibição existente, os parâmetros da WHERE
cláusula devem ser especificados por meio da caixa de diálogo Adicionar WHERE
Cláusula. No entanto, ao criar uma instrução SQL personalizada, você pode inserir os parâmetros diretamente na WHERE
cláusula (usando @parameterName
para denotar cada parâmetro). Um procedimento armazenado consiste em uma ou mais instruções SQL e essas instruções podem ser parametrizadas. Os parâmetros usados nas instruções SQL, no entanto, devem ser passados como parâmetros de entrada para o procedimento armazenado.
Como a criação de uma consulta parametrizada depende de como o SqlDataSource s SelectCommand
é especificado, vamos dar uma olhada nas três abordagens. Para começar, abra a ParameterizedQueries.aspx
página na SqlDataSource
pasta , arraste um controle SqlDataSource da Caixa de Ferramentas para o Designer e defina como ID
Products25BucksAndUnderDataSource
. Em seguida, clique no link Configurar Fonte de Dados da marca inteligente do controle. Selecione o banco de dados a ser usado (NORTHWINDConnectionString
) e clique em Avançar.
Etapa 1: Adicionar uma cláusula WHERE ao escolher as colunas de uma tabela ou exibição
Ao selecionar os dados a serem retornados do banco de dados com o controle SqlDataSource, o assistente Configurar Fonte de Dados nos permite simplesmente escolher as colunas a serem retornadas de uma tabela ou exibição existente (consulte a Figura 1). Isso cria automaticamente uma instrução SQL SELECT
, que é o que é enviado ao banco de dados quando o método sqlDataSource Select()
é invocado. Como fizemos no tutorial anterior, selecione a tabela Produtos na lista suspensa e marcar as ProductID
colunas , ProductName
e UnitPrice
.
Figura 1: escolha as colunas a serem retornadas de uma tabela ou exibição (clique para exibir a imagem em tamanho real)
Para incluir uma WHERE
cláusula na SELECT
instrução , clique no WHERE
botão , que abre a caixa de diálogo Adicionar WHERE
Cláusula (consulte Figura 2). Para adicionar um parâmetro para limitar os resultados retornados pela SELECT
consulta, primeiro escolha a coluna para filtrar os dados. Em seguida, escolha o operador a ser usado para filtragem (=, <, <=, >e assim por diante). Por fim, escolha a origem do valor do parâmetro, como no estado querystring ou session. Depois de configurar o parâmetro, clique no botão Adicionar para incluí-lo na SELECT
consulta.
Para este exemplo, vamos retornar apenas os resultados em que o UnitPrice
valor é menor ou igual a US$ 25,00. Portanto, escolha UnitPrice
na lista suspensa Coluna e <= na lista suspensa Operador. Ao usar um valor de parâmetro embutido em código (como US$ 25,00) ou se o valor do parâmetro for especificado programaticamente, selecione Nenhum na lista suspensa Origem. Em seguida, insira o valor do parâmetro embutido em código na caixa de texto Valor 25.00 e conclua o processo clicando no botão Adicionar.
Figura 2: Limitar os resultados retornados da caixa de diálogo Adicionar WHERE
Cláusula (Clique para exibir a imagem em tamanho real)
Depois de adicionar o parâmetro, clique em OK para retornar ao assistente Configurar Fonte de Dados. A SELECT
instrução na parte inferior do assistente agora deve incluir uma WHERE
cláusula com um parâmetro chamado @UnitPrice
:
SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)
Observação
Se você especificar várias condições na WHERE
cláusula da caixa de diálogo Adicionar WHERE
Cláusula, o assistente as unirá ao AND
operador . Se você precisar incluir um OR
na WHERE
cláusula (como WHERE UnitPrice <= @UnitPrice OR Discontinued = 1
) , precisará compilar a SELECT
instrução por meio da tela de instrução SQL personalizada.
Conclua a configuração do SqlDataSource (clique em Avançar e em Concluir) e inspecione a marcação declarativa do SqlDataSource. A marcação agora inclui uma <SelectParameters>
coleção, que explica as fontes para os parâmetros no 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>
Quando o método sqlDataSource é Select()
invocado, o valor do UnitPrice
parâmetro (25,00) é aplicado ao @UnitPrice
parâmetro no SelectCommand
antes de ser enviado ao banco de dados. O resultado líquido é que apenas os produtos menores ou iguais a US$ 25,00 são retornados da Products
tabela. Para confirmar isso, adicione um GridView à página, associe-o a essa fonte de dados e exiba a página por meio de um navegador. Você só deve ver os produtos listados que são menores ou iguais a US$ 25,00, como confirma a Figura 3.
Figura 3: Somente os produtos menores ou iguais a US$ 25,00 são exibidos (clique para exibir a imagem em tamanho real)
Etapa 2: Adicionar parâmetros a uma instrução SQL personalizada
Ao adicionar uma instrução SQL personalizada, você pode inserir a WHERE
cláusula explicitamente ou especificar um valor na célula Filter do Construtor de Consultas. Para demonstrar isso, vamos exibir apenas esses produtos em um GridView cujos preços são inferiores a um determinado limite. Comece adicionando um TextBox à ParameterizedQueries.aspx
página para coletar esse valor de limite do usuário. Defina a propriedade MaxPrice
TextBox como ID
. Adicione um controle Web Button e defina sua Text
propriedade como Exibir Produtos Correspondentes.
Em seguida, arraste um GridView para a página e, de sua marca inteligente, escolha criar um novo SqlDataSource chamado ProductsFilteredByPriceDataSource
. No assistente Configurar Fonte de Dados, prossiga para a tela Especificar uma instrução SQL personalizada ou procedimento armazenado (consulte a Figura 4) e insira a seguinte consulta:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice
Depois de inserir a consulta (manualmente ou por meio do Construtor de Consultas), clique em Avançar.
Figura 4: retornar somente os produtos menores ou iguais a um valor de parâmetro (clique para exibir a imagem em tamanho real)
Como a consulta inclui parâmetros, a próxima tela do assistente nos solicita a origem dos valores de parâmetros. Escolha Controle na lista suspensa Origem do parâmetro e MaxPrice
(o valor do ID
controle TextBox) na lista suspensa ControlID. Você também pode inserir um valor padrão opcional a ser usado no caso em que o usuário não inseriu nenhum texto no MaxPrice
TextBox. Por enquanto, não insira um valor padrão.
Figura 5: a MaxPrice
propriedade TextBox s Text
é usada como a origem do parâmetro (clique para exibir a imagem em tamanho real)
Conclua o assistente Configurar Fonte de Dados clicando em Avançar e, em seguida, Concluir. A marcação declarativa para GridView, TextBox, Button e SqlDataSource segue:
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>
Observe que o parâmetro na seção SqlDataSource s <SelectParameters>
é um ControlParameter
, que inclui propriedades adicionais como ControlID
e PropertyName
. Quando o método sqlDataSource é Select()
invocado, o ControlParameter
pega o valor da propriedade de controle Web especificada e o atribui ao parâmetro correspondente no SelectCommand
. Neste exemplo, a MaxPrice
propriedade s Text é usada como o valor do @MaxPrice
parâmetro.
Reserve um minuto para exibir esta página por meio de um navegador. Ao visitar a página pela primeira vez ou sempre que a MaxPrice
Caixa de Texto não tem um valor, nenhum registro é exibido no GridView.
Figura 6: Nenhum registro é exibido quando a MaxPrice
Caixa de Texto está vazia (clique para exibir a imagem em tamanho real)
O motivo pelo qual nenhum produto é mostrado é porque, por padrão, uma cadeia de caracteres vazia para um valor de parâmetro é convertida em um valor de banco de dados NULL
. Como a comparação de [UnitPrice] <= NULL
sempre é avaliada como False, nenhum resultado é retornado.
Insira um valor na caixa de texto, como 5,00, e clique no botão Exibir Produtos Correspondentes. No postback, o SqlDataSource informa ao GridView que uma de suas fontes de parâmetro foi alterada. Consequentemente, o GridView é reassociado ao SqlDataSource, exibindo esses produtos menores ou iguais a US$ 5,00.
Figura 7: Produtos menores ou iguais a US$ 5,00 são exibidos (clique para exibir a imagem em tamanho real)
Inicialmente exibindo todos os produtos
Em vez de não exibir nenhum produto quando a página for carregada pela primeira vez, talvez queiramos exibir todos os produtos. Uma maneira de listar todos os produtos sempre que o MaxPrice
TextBox estiver vazio é definir o valor padrão do parâmetro como um valor insanamente alto, como 10000000, pois é improvável que a Northwind Traders tenha estoque cujo preço unitário exceda US$ 1.000.000. No entanto, essa abordagem é miopia e pode não funcionar em outras situações.
Em tutoriais anteriores – Parâmetros Declarativos e Filtragem Mestre/Detalhes com uma DropDownList , enfrentamos um problema semelhante. Nossa solução era colocar essa lógica na Camada de Lógica de Negócios. Especificamente, a BLL examinou o valor de entrada e, se fosse NULL
ou algum valor reservado, a chamada foi roteada para o método DAL que retornou todos os registros. Se o valor de entrada fosse um valor de filtragem normal, uma chamada foi feita para o método DAL que executou uma instrução SQL que usava uma cláusula parametrizada WHERE
com o valor fornecido.
Infelizmente, ignoramos a arquitetura ao usar o SqlDataSource. Em vez disso, precisamos personalizar a instrução SQL para capturar de forma inteligente todos os registros se o @MaximumPrice
parâmetro for NULL
ou algum valor reservado. Para este exercício, vamos tê-lo para que, se o @MaximumPrice
parâmetro for igual a -1.0
, todos os registros sejam retornados (-1.0
funciona como um valor reservado, pois nenhum produto pode ter um valor negativo UnitPrice
). Para fazer isso, podemos usar a seguinte instrução SQL:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0
Essa WHERE
cláusula retornará todos os registros se o parâmetro for igual -1.0
a @MaximumPrice
. Se o valor do parâmetro não -1.0
for , somente os produtos cujo UnitPrice
é menor ou igual ao valor do @MaximumPrice
parâmetro serão retornados. Ao definir o valor padrão do @MaximumPrice
parâmetro como -1.0
, na primeira carga de página (ou sempre que o MaxPrice
TextBox estiver vazio), @MaximumPrice
terá um valor de -1.0
e todos os produtos serão exibidos.
Figura 8: Agora todos os produtos são exibidos quando a MaxPrice
TextBox está vazia (clique para exibir a imagem em tamanho real)
Há algumas ressalvas a serem observadas com essa abordagem. Primeiro, perceba que o tipo de dados do parâmetro é inferido pelo uso dele na consulta SQL. Se você alterar a WHERE
cláusula de @MaximumPrice = -1.0
para @MaximumPrice = -1
, o runtime tratará o parâmetro como um inteiro. Se você tentar atribuir o MaxPrice
TextBox a um valor decimal (como 5,00 ), ocorrerá um erro porque ele não poderá converter 5,00 em um inteiro. Para corrigir isso, certifique-se de usar @MaximumPrice = -1.0
na WHERE
cláusula ou, melhor ainda, definir a ControlParameter
propriedade do Type
objeto como Decimal .
Em segundo lugar, ao adicionar o OR @MaximumPrice = -1.0
à WHERE
cláusula , o mecanismo de consulta não pode usar um índice em UnitPrice
(supondo que exista um), resultando assim em uma verificação de tabela. Isso poderá afetar o desempenho se houver um número suficientemente grande de registros na Products
tabela. Uma abordagem melhor seria mover essa lógica para um procedimento armazenado em que uma instrução IF
executasse uma SELECT
consulta da Products
tabela sem uma WHERE
cláusula quando todos os registros precisassem ser retornados ou uma cuja WHERE
cláusula contém apenas os UnitPrice
critérios, para que um índice possa ser usado.
Etapa 3: Criando e usando procedimentos armazenados parametrizados
Os procedimentos armazenados podem incluir um conjunto de parâmetros de entrada que podem ser usados nas instruções SQL definidas dentro do procedimento armazenado. Ao configurar o SqlDataSource para usar um procedimento armazenado que aceita parâmetros de entrada, esses valores de parâmetro podem ser especificados usando as mesmas técnicas que com instruções SQL ad hoc.
Para ilustrar o uso de procedimentos armazenados no SqlDataSource, vamos criar um novo procedimento armazenado no banco de dados Northwind chamado GetProductsByCategory
, que aceita um parâmetro chamado @CategoryID
e retorna todas as colunas dos produtos cuja CategoryID
coluna corresponde @CategoryID
a . Para criar um procedimento armazenado, acesse a Explorer servidor e faça uma busca detalhada no NORTHWND.MDF
banco de dados. (Se você não vir o servidor Explorer, abra-o acessando o menu Exibir e selecionando a opção Servidor Explorer.)
NORTHWND.MDF
No banco de dados, clique com o botão direito do mouse na pasta Procedimentos Armazenados, escolha Adicionar Novo Procedimento Armazenado e insira a seguinte sintaxe:
CREATE PROCEDURE dbo.GetProductsByCategory
(
@CategoryID int
)
AS
SELECT *
FROM Products
WHERE CategoryID = @CategoryID
Clique no ícone Salvar (ou Ctrl+S) para salvar o procedimento armazenado. Você pode testar o procedimento armazenado clicando com o botão direito do mouse na pasta Procedimentos Armazenados e escolhendo Executar. Isso solicitará os parâmetros do procedimento armazenado (@CategoryID
, nesta instância), após os quais os resultados serão exibidos na janela Saída.
Figura 9: o GetProductsByCategory
procedimento armazenado quando executado com um @CategoryID
de 1 (clique para exibir a imagem em tamanho real)
Vamos usar esse procedimento armazenado para exibir todos os produtos na categoria Bebidas em um GridView. Adicione um novo GridView à página e associe-o a um novo SqlDataSource chamado BeverageProductsDataSource
. Continue na tela Especificar uma instrução SQL personalizada ou procedimento armazenado, selecione o botão de opção Procedimento armazenado e escolha o GetProductsByCategory
procedimento armazenado na lista suspensa.
Figura 10: Selecione o GetProductsByCategory
Procedimento Armazenado na Lista de Drop-Down (Clique para exibir a imagem em tamanho real)
Como o procedimento armazenado aceita um parâmetro de entrada (@CategoryID
), clicar em Avançar nos solicita que especifique a origem desse valor de parâmetro. As Bebidas são 1, portanto, deixe a lista suspensa Origem do parâmetro em Nenhum e insira CategoryID
1 na caixa de texto DefaultValue.
Figura 11: Usar um valor de Hard-Coded de 1 para retornar os produtos na categoria bebidas (clique para exibir a imagem em tamanho real)
Como mostra a marcação declarativa a seguir, ao usar um procedimento armazenado, a propriedade s SelectCommand
SqlDataSource é definida como o nome do procedimento armazenado e a SelectCommandType
propriedade é definida StoredProcedure
como , indicando que o SelectCommand
é o nome de um procedimento armazenado em vez de uma instrução 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>
Teste a página em um navegador. Somente os produtos que pertencem à categoria Bebidas são exibidos, embora todos os campos do produto sejam exibidos, pois o GetProductsByCategory
procedimento armazenado retorna todas as colunas da Products
tabela. É claro que poderíamos limitar ou personalizar os campos exibidos no GridView na caixa de diálogo Editar Colunas do GridView.
Figura 12: Todas as bebidas são exibidas (clique para exibir a imagem em tamanho real)
Etapa 4: Invocar programaticamente uma instrução Select() do SqlDataSource
Os exemplos que vimos no tutorial anterior e neste tutorial até agora associaram os controles SqlDataSource diretamente a um GridView. No entanto, os dados do controle SqlDataSource podem ser acessados e enumerados programaticamente no código. Isso pode ser particularmente útil quando você precisa consultar dados para inspecioná-los, mas não precisa exibi-los. Em vez de precisar escrever todo o código de ADO.NET clichê para se conectar ao banco de dados, especificar o comando e recuperar os resultados, você pode permitir que o SqlDataSource manipule esse código monótono.
Para ilustrar o trabalho com os dados do SqlDataSource programaticamente, imagine que seu chefe tenha abordado você com uma solicitação para criar uma página da Web que exibe o nome de uma categoria selecionada aleatoriamente e seus produtos associados. Ou seja, quando um usuário visita essa página, queremos escolher aleatoriamente uma categoria da Categories
tabela, exibir o nome da categoria e, em seguida, listar os produtos que pertencem a essa categoria.
Para fazer isso, precisamos de dois controles SqlDataSource um para pegar uma categoria aleatória da Categories
tabela e outro para obter os produtos da categoria. Criaremos o SqlDataSource que recupera um registro de categoria aleatório nesta etapa; A etapa 5 analisa a criação do SqlDataSource que recupera os produtos da categoria.
Comece adicionando um SqlDataSource a ParameterizedQueries.aspx
e defina como RandomCategoryDataSource
ID
. Configure-o para que ele use a seguinte consulta SQL:
SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()
ORDER BY NEWID()
retorna os registros classificados em ordem aleatória (consulte Usando NEWID()
para classificar registros aleatoriamente). SELECT TOP 1
retorna o primeiro registro do conjunto de resultados. Juntas, essa consulta retorna os CategoryID
valores de coluna e CategoryName
de uma única categoria selecionada aleatoriamente.
Para exibir o valor da categoria, CategoryName
adicione um controle Web Label à página, defina sua ID
propriedade CategoryNameLabel
como e desmarque sua Text
propriedade. Para recuperar programaticamente os dados de um controle SqlDataSource, precisamos invocar seu Select()
método. O Select()
método espera um único parâmetro de entrada do tipo DataSourceSelectArguments
, que especifica como os dados devem ser remetente antes de serem retornados. Isso pode incluir instruções sobre como classificar e filtrar os dados e é usado pelos controles da Web de dados ao classificar ou paginar os dados de um controle SqlDataSource. Porém, para nosso exemplo, não precisamos que os dados sejam modificados antes de serem retornados e, portanto, passaremos o DataSourceSelectArguments.Empty
objeto .
O Select()
método retorna um objeto que implementa IEnumerable
. O tipo preciso retornado depende do valor da propriedade s do DataSourceMode
controle SqlDataSource. Conforme discutido no tutorial anterior, essa propriedade pode ser definida como um valor de DataSet
ou DataReader
. Se definido como DataSet
, o Select()
método retornará um objeto DataView ; se definido como DataReader
, retornará um objeto que implementa IDataReader
. Como o RandomCategoryDataSource
SqlDataSource tem sua DataSourceMode
propriedade definida DataSet
como (o padrão), trabalharemos com um objeto DataView.
O código a seguir ilustra como recuperar os registros do RandomCategoryDataSource
SqlDataSource como um DataView, bem como ler o CategoryName
valor da coluna da primeira linha 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]
retorna o primeiro DataRowView
no DataView. randomCategoryView[0]["CategoryName"]
retorna o valor da CategoryName
coluna nesta primeira linha. Observe que o DataView é de tipo flexível. Para fazer referência a um valor de coluna específico, precisamos passar o nome da coluna como uma cadeia de caracteres ( CategoryName, nesse caso). A Figura 13 mostra a mensagem exibida no CategoryNameLabel
ao exibir a página. É claro que o nome real da categoria exibido é selecionado aleatoriamente pelo RandomCategoryDataSource
SqlDataSource em cada visita à página (incluindo postbacks).
Figura 13: o nome da categoria selecionada aleatoriamente é exibido (clique para exibir a imagem em tamanho real)
Observação
Se a propriedade s do DataSourceMode
controle SqlDataSource tivesse sido definida DataReader
como , o valor retornado do Select()
método precisaria ser convertido em IDataReader
. Para ler o CategoryName
valor da coluna da primeira linha, usaríamos código como:
if (randomCategoryReader.Read())
{
string categoryName = randomCategoryReader["CategoryName"].ToString();
...
}
Com o SqlDataSource selecionando aleatoriamente uma categoria, estamos prontos para adicionar o GridView que lista os produtos da categoria.
Observação
Em vez de usar um controle Web Label para exibir o nome da categoria, poderíamos ter adicionado um FormView ou DetailsView à página, associando-o ao SqlDataSource. No entanto, o uso do Rótulo nos permitiu explorar como invocar programaticamente a instrução sqlDataSource Select()
e trabalhar com seus dados resultantes no código.
Etapa 5: Atribuindo valores de parâmetro programaticamente
Todos os exemplos que vimos até agora neste tutorial usaram um valor de parâmetro embutido em código ou um obtido de uma das fontes de parâmetro predefinidas (um valor querystring, um controle da Web na página e assim por diante). No entanto, os parâmetros do controle SqlDataSource também podem ser definidos programaticamente. Para concluir nosso exemplo atual, precisamos de um SqlDataSource que retorne todos os produtos pertencentes a uma categoria especificada. Esse SqlDataSource terá um CategoryID
parâmetro cujo valor precisa ser definido com base no valor da CategoryID
coluna retornado pelo RandomCategoryDataSource
SqlDataSource no Page_Load
manipulador de eventos.
Comece adicionando um GridView à página e associe-o a um novo SqlDataSource chamado ProductsByCategoryDataSource
. Assim como fizemos na Etapa 3, configure o SqlDataSource para que ele invoque o GetProductsByCategory
procedimento armazenado. Deixe a lista suspensa Origem do parâmetro definida como Nenhum, mas não insira um valor padrão, pois definiremos esse valor padrão programaticamente.
Figura 14: Não especificar uma fonte de parâmetro ou valor padrão (clique para exibir a imagem em tamanho real)
Depois de concluir o assistente sqlDataSource, a marcação declarativa resultante deve ser semelhante à seguinte:
<asp:SqlDataSource ID="ProductsByCategoryDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Name="CategoryID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
Podemos atribuir o DefaultValue
CategoryID
do parâmetro programaticamente no Page_Load
manipulador de eventos:
// Assign the ProductsByCategoryDataSource's
// CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
randomCategoryView[0]["CategoryID"].ToString();
Com essa adição, a página inclui um GridView que mostra os produtos associados à categoria selecionada aleatoriamente.
Figura 15: Não especificar uma fonte de parâmetro ou valor padrão (clique para exibir a imagem em tamanho real)
Resumo
O SqlDataSource permite que os desenvolvedores de página definam consultas parametrizadas cujos valores de parâmetro podem ser codificados, extraídos de fontes de parâmetro predefinidas ou atribuídos programaticamente. Neste tutorial, vimos como criar uma consulta parametrizada do assistente Configurar Fonte de Dados para consultas SQL ad hoc e procedimentos armazenados. Também examinamos o uso de fontes de parâmetro embutidas em código, um controle web como uma fonte de parâmetro e especificando programaticamente o valor do parâmetro.
Assim como no ObjectDataSource, o SqlDataSource também fornece recursos para modificar seus dados subjacentes. No próximo tutorial, veremos como definir INSERT
instruções , UPDATE
e DELETE
com o SqlDataSource. Depois que essas instruções tiverem sido adicionadas, poderemos utilizar os recursos internos de inserção, edição e exclusão inerentes aos controles GridView, DetailsView e FormView.
Programação feliz!
Sobre o autor
Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos Especiais
Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Scott Clyde, Randell Schmidt e Ken Pespisa. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, solte-me uma linha em mitchell@4GuysFromRolla.com.