Adicionar mais colunas DataTable (VB)
por Scott Mitchell
Ao usar o Assistente tableAdapter para criar um Conjunto de Dados Tipado, o DataTable correspondente contém as colunas retornadas pela consulta de banco de dados main. Mas há ocasiões em que o DataTable precisa incluir colunas adicionais. Neste tutorial, aprendemos por que os procedimentos armazenados são recomendados quando precisamos de colunas adicionais do DataTable.
Introdução
Ao adicionar um TableAdapter a um Conjunto de Dados Tipado, o esquema de DataTable correspondente é determinado pela consulta main do TableAdapter. Por exemplo, se a consulta main retornar os campos de dados A, B e C, o DataTable terá três colunas correspondentes chamadas A, B e C. Além de sua consulta main, um TableAdapter pode incluir consultas adicionais que retornam, talvez, um subconjunto dos dados com base em algum parâmetro. Por exemplo, além da ProductsTableAdapter
consulta s main, que retorna informações sobre todos os produtos, ela também contém métodos como GetProductsByCategoryID(categoryID)
e GetProductByProductID(productID)
, que retornam informações específicas do produto com base em um parâmetro fornecido.
O modelo de ter o esquema do DataTable reflete a consulta main do TableAdapter funciona bem se todos os métodos de TableAdapter retornarem os mesmos ou menos campos de dados do que os especificados na consulta main. Se um método TableAdapter precisar retornar campos de dados adicionais, devemos expandir o esquema do DataTable adequadamente. No tutorial Master/Detail Using a Bulleted List of Master Records with a Details DataList, adicionamos um método ao CategoriesTableAdapter
que retornava os CategoryID
campos de dados , CategoryName
e Description
definidos na consulta main mais NumberOfProducts
, um campo de dados adicional que relatava o número de produtos associados a cada categoria. Adicionamos manualmente uma nova coluna ao CategoriesDataTable
para capturar o NumberOfProducts
valor do campo de dados desse novo método.
Conforme discutido no tutorial Carregando Arquivos, é necessário ter muito cuidado com TableAdapters que usam instruções SQL ad hoc e têm métodos cujos campos de dados não correspondem precisamente à consulta main. Se o assistente de Configuração do TableAdapter for executado novamente, ele atualizará todos os métodos de TableAdapter para que sua lista de campos de dados corresponda à consulta main. Consequentemente, todos os métodos com listas de colunas personalizadas reverter à lista de colunas da consulta main e não retornarão os dados esperados. Esse problema não surge ao usar procedimentos armazenados.
Neste tutorial, veremos como estender um esquema do DataTable para incluir colunas adicionais. Devido à fragilidade do TableAdapter ao usar instruções SQL ad hoc, neste tutorial usaremos procedimentos armazenados. Consulte os tutoriais Criando novos procedimentos armazenados para os TableAdapters do Conjunto de Dados Tipados e Usando Procedimentos Armazenados Existentes para os tutoriais TableAdapters do Conjunto de Dados Tipados para obter mais informações sobre como configurar um TableAdapter para usar procedimentos armazenados.
Etapa 1: Adicionar umaPriceQuartile
coluna aoProductsDataTable
No tutorial Criando novos procedimentos armazenados para o TableAdapters do Conjunto de Dados Tipado , criamos um Conjunto de Dados Digitado chamado NorthwindWithSprocs
. Atualmente, esse Conjunto de Dados contém duas DataTables: ProductsDataTable
e EmployeesDataTable
. O ProductsTableAdapter
tem os três métodos a seguir:
GetProducts
- a consulta main, que retorna todos os registros daProducts
tabelaGetProductsByCategoryID(categoryID)
– retorna todos os produtos com a categoryID especificada.GetProductByProductID(productID)
– retorna o produto específico com o productID especificado.
A consulta main e os dois métodos adicionais retornam o mesmo conjunto de campos de dados, ou seja, todas as colunas da Products
tabela. Não há subconsultas correlacionadas ou JOIN
s extraindo dados relacionados das Categories
tabelas ou Suppliers
. Portanto, o ProductsDataTable
tem uma coluna correspondente para cada campo na Products
tabela.
Para este tutorial, vamos adicionar um método ao ProductsTableAdapter
chamado GetProductsWithPriceQuartile
que retorna todos os produtos. Além dos campos de dados do produto padrão, GetProductsWithPriceQuartile
também incluirá um PriceQuartile
campo de dados que indica sob qual quartil o preço do produto cai. Por exemplo, aqueles produtos cujos preços estão nos 25% mais caros terão um PriceQuartile
valor de 1, enquanto aqueles cujos preços caem nos 25% inferiores terão um valor de 4. Antes de nos preocuparmos em criar o procedimento armazenado para retornar essas informações, no entanto, primeiro precisamos atualizar o ProductsDataTable
para incluir uma coluna para manter os PriceQuartile
resultados quando o GetProductsWithPriceQuartile
método é usado.
Abra o NorthwindWithSprocs
DataSet e clique com o botão direito do mouse no ProductsDataTable
. Escolha Adicionar no menu de contexto e escolha Coluna.
Figura 1: Adicionar uma nova coluna ao ProductsDataTable
(Clique para exibir a imagem em tamanho real)
Isso adicionará uma nova coluna à DataTable chamada Column1 do tipo System.String
. Precisamos atualizar o nome desta coluna para PriceQuartile e seu tipo para System.Int32
, pois ele será usado para manter um número entre 1 e 4. Selecione a coluna recém-adicionada no e, no ProductsDataTable
janela Propriedades, defina a Name
propriedade como PriceQuartile e a DataType
propriedade como System.Int32
.
Figura 2: definir as propriedades e DataType
as Name
novas colunas (clique para exibir a imagem em tamanho real)
Como mostra a Figura 2, há propriedades adicionais que podem ser definidas, como se os valores na coluna devem ser exclusivos, se a coluna for uma coluna de incremento automático, se os valores de banco de dados NULL
são permitidos ou não e assim por diante. Deixe esses valores definidos como seus padrões.
Etapa 2: Criando oGetProductsWithPriceQuartile
método
Agora que o ProductsDataTable
foi atualizado para incluir a PriceQuartile
coluna, estamos prontos para criar o GetProductsWithPriceQuartile
método . Comece clicando com o botão direito do mouse no TableAdapter e escolhendo Adicionar Consulta no menu de contexto. Isso apresenta o assistente de Configuração de Consulta TableAdapter, que primeiro nos solicita se queremos usar instruções SQL ad hoc ou um procedimento armazenado novo ou existente. Como ainda não temos um procedimento armazenado que retorna os dados do quartil de preço, vamos permitir que o TableAdapter crie esse procedimento armazenado para nós. Selecione a opção Criar procedimento armazenado e clique em Avançar.
Figura 3: Instrua o Assistente tableAdapter a criar o procedimento armazenado para nós (clique para exibir a imagem em tamanho real)
Na tela subsequente, mostrada na Figura 4, o assistente nos pergunta que tipo de consulta adicionar. Como o GetProductsWithPriceQuartile
método retornará todas as colunas e registros da Products
tabela, selecione a opção SELECT que retorna linhas e clique em Avançar.
Figura 4: Nossa consulta será uma SELECT
instrução que retorna várias linhas (clique para exibir a imagem em tamanho real)
Em seguida, é solicitado que a SELECT
consulta seja solicitada. Insira a seguinte consulta no assistente:
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartile
FROM Products
A consulta acima usa SQL Server nova NTILE
função de 2005 para dividir os resultados em quatro grupos em que os grupos são determinados pelos UnitPrice
valores classificados em ordem decrescente.
Infelizmente, o Construtor de Consultas não sabe como analisar o OVER
palavra-chave e exibirá um erro ao analisar a consulta acima. Portanto, insira a consulta acima diretamente na caixa de texto no assistente sem usar o Construtor de Consultas.
Observação
Para obter mais informações sobre NTILE e outras funções de classificação do NTILE e SQL Server 2005, consulte ROW_NUMBER (Transact-SQL) e a seção Funções de classificação do SQL Server 2005 Books Online.
Depois de inserir a SELECT
consulta e clicar em Avançar, o assistente solicita que forneçamos um nome para o procedimento armazenado que ele criará. Nomeie o novo procedimento Products_SelectWithPriceQuartile
armazenado e clique em Avançar.
Figura 5: nomeie o procedimento Products_SelectWithPriceQuartile
armazenado (clique para exibir a imagem em tamanho real)
Por fim, somos solicitados a nomear os métodos TableAdapter. Deixe as caixas de seleção Preencher uma DataTable e Retornar um DataTable marcadas e nomeie os métodos FillWithPriceQuartile
e GetProductsWithPriceQuartile
.
Figura 6: nomeie os métodos TableAdapter e Clique em Concluir (clique para exibir a imagem em tamanho real)
Com a SELECT
consulta especificada e o procedimento armazenado e os métodos TableAdapter nomeados, clique em Concluir para concluir o assistente. Neste ponto, você pode receber um aviso ou dois do assistente dizendo que OVER
não há suporte para o constructo ou a instrução SQL. Esses avisos podem ser ignorados.
Depois de concluir o assistente, o TableAdapter deve incluir os FillWithPriceQuartile
métodos e GetProductsWithPriceQuartile
e o banco de dados deve incluir um procedimento armazenado chamado Products_SelectWithPriceQuartile
. Reserve um momento para verificar se o TableAdapter realmente contém esse novo método e se o procedimento armazenado foi adicionado corretamente ao banco de dados. Ao verificar o banco de dados, se você não vir o procedimento armazenado, tente clicar com o botão direito do mouse na pasta Procedimentos Armazenados e escolher Atualizar.
Figura 7: Verificar se um novo método foi adicionado ao TableAdapter
Figura 8: Verifique se o banco de dados contém o Products_SelectWithPriceQuartile
procedimento armazenado (clique para exibir a imagem em tamanho real)
Observação
Um dos benefícios de usar procedimentos armazenados em vez de instruções SQL ad hoc é que executar novamente o assistente de Configuração tableAdapter não modificará as listas de colunas de procedimentos armazenados. Verifique isso clicando com o botão direito do mouse no TableAdapter, escolhendo a opção Configurar no menu de contexto para iniciar o assistente e, em seguida, clicando em Concluir para concluí-lo. Em seguida, vá para o banco de dados e exiba o Products_SelectWithPriceQuartile
procedimento armazenado. Observe que sua lista de colunas não foi modificada. Se tivéssemos usado instruções SQL ad hoc, executar novamente o assistente de Configuração tableAdapter teria revertido essa lista de colunas de consulta para corresponder à lista de colunas de consulta main, removendo assim a instrução NTILE da consulta usada pelo GetProductsWithPriceQuartile
método .
Quando o método s da Camada de GetProductsWithPriceQuartile
Acesso a Dados é invocado, o TableAdapter executa o Products_SelectWithPriceQuartile
procedimento armazenado e adiciona uma linha ao ProductsDataTable
para cada registro retornado. Os campos de dados retornados pelo procedimento armazenado são mapeados para as ProductsDataTable
colunas s. Como há um PriceQuartile
campo de dados retornado do procedimento armazenado, seu valor é atribuído à ProductsDataTable
coluna s PriceQuartile
.
Para esses métodos TableAdapter cujas consultas não retornam um PriceQuartile
campo de dados, o PriceQuartile
valor da coluna é o valor especificado por sua DefaultValue
propriedade. Como mostra a Figura 2, esse valor é definido como DBNull
, o padrão. Se preferir um valor padrão diferente, basta definir a DefaultValue
propriedade adequadamente. Apenas verifique se o DefaultValue
valor é válido considerando as colunas s DataType
(ou seja, System.Int32
para a PriceQuartile
coluna).
Neste ponto, executamos as etapas necessárias para adicionar uma coluna adicional a uma DataTable. Para verificar se essa coluna adicional funciona conforme o esperado, vamos criar uma página ASP.NET que exibe o nome, o preço e o quartil de preço de cada produto. Antes disso, porém, primeiro precisamos atualizar a Camada de Lógica de Negócios para incluir um método que chama o método da DAL.GetProductsWithPriceQuartile
Atualizaremos a BLL em seguida, na Etapa 3, e criaremos a página ASP.NET na Etapa 4.
Etapa 3: Aumentando a camada de lógica de negócios
Antes de usarmos o novo GetProductsWithPriceQuartile
método da Camada de Apresentação, devemos primeiro adicionar um método correspondente à BLL. Abra o arquivo de ProductsBLLWithSprocs
classe e adicione o seguinte código:
<System.ComponentModel.DataObjectMethodAttribute_
(System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductsWithPriceQuartile() As NorthwindWithSprocs.ProductsDataTable
Return Adapter.GetProductsWithPriceQuartile()
End Function
Assim como os outros métodos de recuperação de dados no ProductsBLLWithSprocs
, o GetProductsWithPriceQuartile
método simplesmente chama o método correspondente GetProductsWithPriceQuartile
do DAL e retorna seus resultados.
Etapa 4: Exibindo as informações do quartil de preço em uma página da Web ASP.NET
Com a adição de BLL concluída, estamos prontos para criar uma página de ASP.NET que mostra o quartil de preço para cada produto. Abra a AddingColumns.aspx
página na AdvancedDAL
pasta e arraste um GridView da Caixa de Ferramentas para o Designer, definindo sua ID
propriedade como Products
. Na marca inteligente gridView, associe-a a um novo ObjectDataSource chamado ProductsDataSource
. Configure o ObjectDataSource para usar o ProductsBLLWithSprocs
método da classe s GetProductsWithPriceQuartile
. Como essa será uma grade somente leitura, defina as listas suspensas nas guias UPDATE, INSERT e DELETE como (Nenhum) .
Figura 9: configurar o ObjectDataSource para usar a ProductsBLLWithSprocs
classe (clique para exibir a imagem em tamanho real)
Figura 10: recuperar informações do produto do GetProductsWithPriceQuartile
método (clique para exibir a imagem em tamanho real)
Depois de concluir o assistente Configurar Fonte de Dados, o Visual Studio adicionará automaticamente um BoundField ou CheckBoxField ao GridView para cada um dos campos de dados retornados pelo método . Um desses campos de dados é PriceQuartile
, que é a coluna que adicionamos ao ProductsDataTable
na Etapa 1.
Edite os campos de GridView, removendo todos, exceto , ProductName
UnitPrice
e PriceQuartile
BoundFields. Configure o UnitPrice
BoundField para formatar seu valor como uma moeda e ter o UnitPrice
e PriceQuartile
BoundFields alinhados à direita e ao centro, respectivamente. Por fim, atualize as propriedades BoundFields restantes HeaderText
para Produto, Preço e Quartil de Preço, respectivamente. Além disso, marcar a caixa de seleção Habilitar Classificação da marca inteligente GridView.
Após essas modificações, a marcação declarativa de GridView e ObjectDataSource deve ser semelhante à seguinte:
<asp:GridView ID="Products" runat="server" AllowSorting="True"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile"
SortExpression="PriceQuartile">
<ItemStyle HorizontalAlign="Center" />
</asp:BoundField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsWithPriceQuartile"
TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>
A Figura 11 mostra esta página quando visitada por meio de um navegador. Observe que, inicialmente, os produtos são ordenados por seu preço em ordem decrescente com cada produto atribuído um valor apropriado PriceQuartile
. É claro que esses dados podem ser classificados por outros critérios com o valor da coluna Quartil de Preço ainda refletindo a classificação do produto em relação ao preço (consulte Figura 12).
Figura 11: Os produtos são ordenados por seus preços (clique para exibir a imagem em tamanho real)
Figura 12: Os produtos são ordenados por seus nomes (clique para exibir a imagem em tamanho real)
Observação
Com algumas linhas de código, poderíamos aumentar o GridView para que ele colorisse as linhas do produto com base em seu PriceQuartile
valor. Podemos colorir esses produtos no primeiro quartil um verde claro, aqueles no segundo quartil um amarelo claro, e assim por diante. Eu encorajo você a ter um momento para adicionar essa funcionalidade. Se você precisar de um atualizador na formatação de um GridView, consulte o tutorial Formatação Personalizada baseada em dados .
Uma abordagem alternativa – criando outro tableAdapter
Como vimos neste tutorial, ao adicionar um método a um TableAdapter que retorna campos de dados diferentes daqueles escritos pela consulta main, podemos adicionar colunas correspondentes à DataTable. Essa abordagem, no entanto, funciona bem somente se houver um pequeno número de métodos no TableAdapter que retornam campos de dados diferentes e se esses campos de dados alternativos não variarem muito da consulta main.
Em vez de adicionar colunas à DataTable, você pode adicionar outro TableAdapter ao DataSet que contém os métodos do primeiro TableAdapter que retornam campos de dados diferentes. Para este tutorial, em vez de adicionar a PriceQuartile
coluna ao ProductsDataTable
(em que ela é usada apenas pelo GetProductsWithPriceQuartile
método ), poderíamos ter adicionado um TableAdapter adicional ao DataSet chamado ProductsWithPriceQuartileTableAdapter
que usava o Products_SelectWithPriceQuartile
procedimento armazenado como sua consulta main. ASP.NET páginas que precisavam obter informações do produto com o quartil de preço usariam o ProductsWithPriceQuartileTableAdapter
, enquanto aquelas que não podiam continuar a usar o ProductsTableAdapter
.
Ao adicionar um novo TableAdapter, os DataTables permanecem sem verniz e suas colunas espelho precisamente os campos de dados retornados pelos métodos tableAdapter. No entanto, tableAdapters adicionais podem introduzir tarefas repetitivas e funcionalidades. Por exemplo, se essas páginas ASP.NET que exibiam a PriceQuartile
coluna também precisassem fornecer suporte de inserção, atualização e exclusão, o ProductsWithPriceQuartileTableAdapter
precisaria ter suas InsertCommand
propriedades , UpdateCommand
e DeleteCommand
configuradas corretamente. Embora essas propriedades espelho os ProductsTableAdapter
s, essa configuração introduz uma etapa extra. Além disso, agora há duas maneiras de atualizar, excluir ou adicionar um produto ao banco de dados – por meio das ProductsTableAdapter
classes e ProductsWithPriceQuartileTableAdapter
.
O download deste tutorial inclui uma ProductsWithPriceQuartileTableAdapter
classe no NorthwindWithSprocs
DataSet que ilustra essa abordagem alternativa.
Resumo
Na maioria dos cenários, todos os métodos em um TableAdapter retornarão o mesmo conjunto de campos de dados, mas há momentos em que um método ou dois específicos podem precisar retornar um campo adicional. Por exemplo, no tutorial Master/Detail Using a Bulleted List of Master Records with a Details DataList, adicionamos um método ao CategoriesTableAdapter
que, além dos campos de dados da consulta main, retornamos um NumberOfProducts
campo que relatava o número de produtos associados a cada categoria. Neste tutorial, analisamos a ProductsTableAdapter
adição de um método no que retornou um PriceQuartile
campo além dos campos de dados da consulta main. Para capturar campos de dados adicionais retornados pelos métodos TableAdapter, precisamos adicionar colunas correspondentes à DataTable.
Se você planeja adicionar manualmente colunas ao DataTable, é recomendável que o TableAdapter use procedimentos armazenados. Se o TableAdapter usar instruções SQL ad hoc, sempre que o assistente de Configuração de TableAdapter for executado, todos os métodos listam listas de dados reverter para os campos de dados retornados pela consulta main. Esse problema não se estende aos procedimentos armazenados, razão pela qual eles são recomendados e usados neste tutorial.
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 Randy Schmidt, Jacky Goor, Bernadete Leigh e Hilton Giesenow. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, solte-me uma linha em mitchell@4GuysFromRolla.com.