Adicionar mais colunas DataTable (VB)

por Scott Mitchell

Baixar PDF

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 CategoryIDcampos de dados , CategoryNamee 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 umaPriceQuartilecoluna 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 da Products tabela
  • GetProductsByCategoryID(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.

Adicionar uma nova coluna ao ProductsDataTable

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.

Definir as propriedades Nome e DataType da Nova Coluna

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 oGetProductsWithPriceQuartilemé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.

Instrua o Assistente tableAdapter a criar o procedimento armazenado para nós

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.

Nossa consulta será uma instrução SELECT que retorna várias linhas

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.

Nomeie o procedimento armazenado Products_SelectWithPriceQuartile

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.

Nomeie os métodos TableAdapter s e clique em Concluir

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.

Verificar se um novo método foi adicionado ao TableAdapter

Figura 7: Verificar se um novo método foi adicionado ao TableAdapter

Verifique se o banco de dados contém o procedimento armazenado Products_SelectWithPriceQuartile

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) .

Configurar o ObjectDataSource para usar a classe ProductsBLLWithSprocs

Figura 9: configurar o ObjectDataSource para usar a ProductsBLLWithSprocs classe (clique para exibir a imagem em tamanho real)

Recuperar informações do produto do método GetProductsWithPriceQuartile

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 , ProductNameUnitPricee 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).

Os produtos são ordenados por seus preços

Figura 11: Os produtos são ordenados por seus preços (clique para exibir a imagem em tamanho real)

Os produtos são ordenados por seus nomes

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 InsertCommandpropriedades , UpdateCommande 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.