Trabalhar com colunas computadas (C#)

por Scott Mitchell

Baixar PDF

Ao criar uma tabela de banco de dados, o Microsoft SQL Server permite definir uma coluna computada cujo valor é calculado a partir de uma expressão que geralmente faz referência a outros valores no mesmo registro de banco de dados. Esses valores são somente leitura no banco de dados, o que requer considerações especiais ao trabalhar com TableAdapters. Neste tutorial, aprendemos a enfrentar os desafios colocados pelas colunas computadas.

Introdução

O Microsoft SQL Server permite colunas computadas, que são colunas cujos valores são calculados a partir de uma expressão que geralmente faz referência aos valores de outras colunas na mesma tabela. Por exemplo, um modelo de dados de acompanhamento de tempo pode ter uma tabela chamada ServiceLog com colunas, incluindo ServicePerformed, EmployeeID, Ratee Duration, entre outras. Embora o valor devido por item de serviço (sendo a taxa multiplicada pela duração) possa ser calculado por meio de uma página da Web ou de outra interface programática, pode ser útil incluir uma coluna na ServiceLog tabela chamada AmountDue que relatou essas informações. Essa coluna pode ser criada como uma coluna normal, mas ela precisará ser atualizada sempre que os valores de Rate coluna ou Duration forem alterados. Uma abordagem melhor seria tornar a AmountDue coluna uma coluna computada usando a expressão Rate * Duration. Isso faria com que SQL Server calculassem automaticamente o valor da AmountDue coluna sempre que ele fosse referenciado em uma consulta.

Como um valor de coluna computada é determinado por uma expressão, essas colunas são somente leitura e, portanto, não podem ter valores atribuídos a elas em INSERT instruções ou UPDATE . No entanto, quando colunas computadas fazem parte da consulta main para um TableAdapter que usa instruções SQL ad hoc, elas são automaticamente incluídas nas instruções e UPDATE geradas INSERT automaticamente. Consequentemente, as consultas e UPDATE as propriedades de TableAdapter INSERT e e InsertCommandUpdateCommand devem ser atualizadas para remover referências a colunas computadas.

Um desafio de usar colunas computadas com um TableAdapter que usa instruções SQL ad hoc é que as consultas e UPDATE tableAdapter INSERT são regeneradas automaticamente sempre que o assistente de Configuração do TableAdapter é concluído. Portanto, as colunas computadas removidas manualmente das INSERT consultas e UPDATE reaparecerão se o assistente for executado novamente. Embora os TableAdapters que usam procedimentos armazenados não sofram com essa fragilidade, eles têm suas próprias peculiaridades que abordaremos na Etapa 3.

Neste tutorial, adicionaremos uma coluna computada à Suppliers tabela no banco de dados Northwind e, em seguida, criaremos um TableAdapter correspondente para trabalhar com esta tabela e sua coluna computada. Faremos com que nosso TableAdapter use procedimentos armazenados em vez de instruções SQL ad hoc para que nossas personalizações não sejam perdidas quando o assistente de Configuração tableAdapter for usado.

Vamos começar!

Etapa 1: Adicionar uma coluna computada àSupplierstabela

O banco de dados Northwind não tem colunas computadas, portanto, precisaremos adicionar uma. Para este tutorial, vamos adicionar uma coluna computada à Suppliers tabela chamada FullContactName que retorna o nome, o título e a empresa para a qual trabalham no seguinte formato: ContactName (ContactTitle, CompanyName). Essa coluna computada pode ser usada em relatórios ao exibir informações sobre fornecedores.

Comece abrindo a definição da Suppliers tabela clicando com o botão direito do Suppliers mouse na tabela no servidor Explorer e escolhendo Abrir Definição de Tabela no menu de contexto. Isso exibirá as colunas da tabela e suas propriedades, como seu tipo de dados, se permitirem NULL e assim por diante. Para adicionar uma coluna computada, comece digitando o nome da coluna na definição da tabela. Em seguida, insira sua expressão na caixa de texto (Fórmula) na seção Especificação de Coluna Computada no janela Propriedades coluna (consulte a Figura 1). Nomeie a coluna FullContactName computada e use a seguinte expressão:

ContactName + ' (' + CASE WHEN ContactTitle IS NOT NULL THEN 
    ContactTitle + ', ' ELSE '' END + CompanyName + ')'

Observe que as cadeias de caracteres podem ser concatenadas no SQL usando o + operador . A CASE instrução pode ser usada como condicional em uma linguagem de programação tradicional. Na expressão acima, a CASE instrução pode ser lida como: se ContactTitle não NULL for, gere o ContactTitle valor concatenado com uma vírgula, caso contrário, não emita nada. Para obter mais informações sobre a utilidade da CASE instrução, consulte Instruções SQLCASE.

Observação

Em vez de usar uma CASE instrução aqui, poderíamos ter usado ISNULL(ContactTitle, '')alternativamente . ISNULL(checkExpression, replacementValue) retornará checkExpression se não for NULL, caso contrário, retornará replacementValue. Enquanto ou ISNULLCASE funcionará nessa instância, há cenários mais complexos em que a flexibilidade da CASE instrução não pode ser correspondida por ISNULL.

Depois de adicionar essa coluna computada, sua tela deverá ser semelhante à captura de tela na Figura 1.

Adicionar uma coluna computada chamada FullContactName à tabela Fornecedores

Figura 1: Adicionar uma coluna computada chamada FullContactName à Suppliers tabela (clique para exibir a imagem em tamanho real)

Depois de nomear a coluna computada e inserir sua expressão, salve as alterações na tabela clicando no ícone Salvar na barra de ferramentas, clicando em Ctrl+S ou acessando o menu Arquivo e escolhendo Salvar Suppliers.

Salvar a tabela deve atualizar a Explorer do Servidor, incluindo a coluna just-added na Suppliers lista de colunas da tabela. Além disso, a expressão inserida na caixa de texto (Fórmula) será ajustada automaticamente a uma expressão equivalente que remove espaços em branco desnecessários, envolve nomes de coluna com colchetes ([]) e inclui parênteses para mostrar mais explicitamente a ordem das operações:

(((([ContactName]+' (')+case when [ContactTitle] IS NOT NULL 
    then [ContactTitle]+', ' else '' end)+[CompanyName])+')')

Para obter mais informações sobre colunas computadas no Microsoft SQL Server, consulte a documentação técnica. Também marcar como especificar colunas computadas para um passo a passo da criação de colunas computadas.

Observação

Por padrão, as colunas computadas não são armazenadas fisicamente na tabela, mas são recalculadas sempre que são referenciadas em uma consulta. Ao verificar a caixa de seleção É Persistente, no entanto, você pode instruir SQL Server a armazenar fisicamente a coluna computada na tabela. Isso permite que um índice seja criado na coluna computada, o que pode melhorar o desempenho de consultas que usam o valor da coluna computada em suas WHERE cláusulas. Consulte Criando índices em colunas computadas para obter mais informações.

Etapa 2: Exibindo os valores das colunas computadas

Antes de começarmos a trabalhar na Camada de Acesso a Dados, vamos levar um minuto para exibir os FullContactName valores. Na Explorer do Servidor, clique com o botão direito do mouse no nome da Suppliers tabela e escolha Nova Consulta no menu de contexto. Isso abrirá uma janela consulta que nos solicitará a escolha de quais tabelas incluir na consulta. Adicione a Suppliers tabela e clique em Fechar. Em seguida, marcar as CompanyNamecolunas , ContactName, ContactTitlee FullContactName da tabela Fornecedores. Por fim, clique no ícone de ponto de exclamação vermelho na Barra de ferramentas para executar a consulta e exibir os resultados.

Como mostra a Figura 2, os resultados incluem FullContactName, que lista as CompanyNamecolunas , ContactNamee ContactTitle usando o formato ldquo;ContactName (ContactTitle, CompanyName) .

O FullContactName usa o formato ContactName (ContactTitle, CompanyName)

Figura 2: o FullContactName usa o formato ContactName (ContactTitle, CompanyName) (clique para exibir a imagem em tamanho real)

Etapa 3: adicionando oSuppliersTableAdapterà camada de acesso a dados

Para trabalhar com as informações do fornecedor em nosso aplicativo, precisamos primeiro criar um TableAdapter e o DataTable em nosso DAL. O ideal é que isso seja feito usando as mesmas etapas simples examinadas em tutoriais anteriores. No entanto, trabalhar com colunas computadas introduz algumas rugas que merecem discussão.

Se você estiver usando um TableAdapter que usa instruções SQL ad hoc, poderá simplesmente incluir a coluna computada na consulta main do TableAdapter por meio do assistente de Configuração do TableAdapter. Isso, no entanto, gerará INSERT automaticamente e UPDATE instruções que incluem a coluna computada. Se você tentar executar um desses métodos, um SqlException com a mensagem ColumnName não poderá ser modificado porque é uma coluna computada ou o resultado de um operador UNION será gerado. Embora a INSERT instrução e UPDATE possa ser ajustada manualmente por meio das propriedades e UpdateCommand do InsertCommand TableAdapter, essas personalizações serão perdidas sempre que o assistente de Configuração do TableAdapter for executado novamente.

Devido à fragilidade de TableAdapters que usam instruções SQL ad hoc, é recomendável usar procedimentos armazenados ao trabalhar com colunas computadas. Se você estiver usando procedimentos armazenados existentes, basta configurar o TableAdapter conforme discutido no tutorial Usando procedimentos armazenados existentes para o TableAdapters do Typed DataSet . Se você tiver o assistente TableAdapter, crie os procedimentos armazenados para você, no entanto, é importante omitir inicialmente todas as colunas computadas da consulta main. Se você incluir uma coluna computada na consulta main, o assistente de Configuração de TableAdapter informará, após a conclusão, que ele não pode criar os procedimentos armazenados correspondentes. Em suma, precisamos configurar inicialmente o TableAdapter usando uma consulta de main sem coluna computada e, em seguida, atualizar manualmente o procedimento armazenado correspondente e os TableAdapter s SelectCommand para incluir a coluna computada. Essa abordagem é semelhante à usada no tutorial Atualizando o TableAdapter to UseJOINs .

Para este tutorial, vamos adicionar um novo TableAdapter e fazer com que ele crie automaticamente os procedimentos armazenados para nós. Consequentemente, precisaremos omitir inicialmente a FullContactName coluna computada da consulta main.

Comece abrindo o NorthwindWithSprocs DataSet na ~/App_Code/DAL pasta . Clique com o botão direito do mouse no Designer e, no menu de contexto, escolha adicionar um novo TableAdapter. Isso iniciará o assistente de Configuração de TableAdapter. Especifique o banco de dados para consultar dados de (NORTHWNDConnectionString de Web.config) e clique em Avançar. Como ainda não criamos procedimentos armazenados para consultar ou modificar a Suppliers tabela, selecione a opção Criar novos procedimentos armazenados para que o assistente os crie para nós e clique em Avançar.

Escolha a opção Criar novos procedimentos armazenados

Figura 3: escolha a opção Criar novos procedimentos armazenados (Clique para exibir a imagem em tamanho real)

A etapa subsequente nos solicita a consulta main. Insira a consulta a seguir, que retorna as SupplierIDcolunas , CompanyName, ContactNamee ContactTitle para cada fornecedor. Observe que essa consulta omite propositalmente a coluna computada (FullContactName); atualizaremos o procedimento armazenado correspondente para incluir esta coluna na Etapa 4.

SELECT SupplierID, CompanyName, ContactName, ContactTitle
FROM Suppliers

Depois de inserir a consulta main e clicar em Avançar, o assistente nos permite nomear os quatro procedimentos armazenados que ele gerará. Nomeie esses procedimentos armazenados Suppliers_Select, Suppliers_Insert, Suppliers_Updatee Suppliers_Delete, como ilustra a Figura 4.

Personalizar os nomes dos procedimentos armazenados gerados automaticamente

Figura 4: Personalizar os nomes dos procedimentos armazenados gerados automaticamente (clique para exibir a imagem em tamanho real)

A próxima etapa do assistente nos permite nomear os métodos de TableAdapter e especificar os padrões usados para acessar e atualizar dados. Deixe as três caixas de seleção marcadas, mas renomeie o GetData método como GetSuppliers. Clique em Concluir para concluir o assistente.

Renomear o método GetData para GetSuppliers

Figura 5: renomeie o GetData método para GetSuppliers (Clique para exibir a imagem em tamanho real)

Ao clicar em Concluir, o assistente criará os quatro procedimentos armazenados e adicionará o TableAdapter e o DataTable correspondente ao Conjunto de Dados Tipado.

Etapa 4: Incluindo a coluna computada na consulta principal do TableAdapter

Agora precisamos atualizar o TableAdapter e o DataTable criados na Etapa 3 para incluir a FullContactName coluna computada. Isso envolve duas etapas:

  1. Atualizando o Suppliers_Select procedimento armazenado para retornar a FullContactName coluna computada e
  2. Atualizando a DataTable para incluir uma coluna correspondente FullContactName .

Comece navegando até o servidor Explorer e fazendo uma busca detalhada na pasta Procedimentos Armazenados. Abra o Suppliers_Select procedimento armazenado e atualize a SELECT consulta para incluir a FullContactName coluna computada:

SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers

Salve as alterações no procedimento armazenado clicando no ícone Salvar na Barra de Ferramentas, pressionando Ctrl+S ou escolhendo a opção Salvar Suppliers_Select no menu Arquivo.

Em seguida, retorne ao Designer DataSet, clique com o botão direito do SuppliersTableAdaptermouse no e escolha Configurar no menu de contexto. Observe que a Suppliers_Select coluna agora inclui a FullContactName coluna em sua coleção Colunas de Dados.

Execute o Assistente de Configuração do TableAdapter s para atualizar as colunas da DataTable

Figura 6: Executar o Assistente de Configuração do TableAdapter para atualizar as colunas de DataTable s (clique para exibir a imagem em tamanho real)

Clique em Concluir para concluir o assistente. Isso adicionará automaticamente uma coluna correspondente ao SuppliersDataTable. O assistente TableAdapter é inteligente o suficiente para detectar que a FullContactName coluna é uma coluna computada e, portanto, somente leitura. Consequentemente, ele define a propriedade trueda coluna como ReadOnly . Para verificar isso, selecione a coluna do SuppliersDataTable e vá para a janela Propriedades (consulte a Figura 7). Observe que as propriedades e MaxLength colunas FullContactNameDataType também são definidas adequadamente.

A coluna FullContactName está marcada como somente leitura

Figura 7: A FullContactName coluna está marcada como Read-Only (clique para exibir a imagem em tamanho real)

Etapa 5: Adicionar umGetSupplierBySupplierIDmétodo ao TableAdapter

Para este tutorial, criaremos uma página ASP.NET que exibe os fornecedores em uma grade atualizável. Em tutoriais anteriores, atualizamos um único registro da Camada lógica de negócios recuperando esse registro específico do DAL como um DataTable fortemente tipado, atualizando suas propriedades e, em seguida, enviando o DataTable atualizado de volta para o DAL para propagar as alterações para o banco de dados. Para realizar essa primeira etapa – recuperar o registro que está sendo atualizado do DAL – precisamos primeiro adicionar um GetSupplierBySupplierID(supplierID) método ao DAL.

Clique com o SuppliersTableAdapter botão direito do mouse no no Design do Conjunto de Dados e escolha a opção Adicionar Consulta no menu de contexto. Como fizemos na Etapa 3, permita que o assistente gere um novo procedimento armazenado para nós selecionando a opção Criar procedimento armazenado (consulte a Figura 3 para obter uma captura de tela desta etapa do assistente). Como esse método retornará um registro com várias colunas, indique que queremos usar uma consulta SQL que seja uma SELECT que retorna linhas e clique em Avançar.

Escolha a opção SELECT que retorna linhas

Figura 8: Escolha a opção SELECT que retorna linhas (clique para exibir a imagem em tamanho real)

A etapa subsequente nos solicita que a consulta seja usada para esse método. Insira o seguinte, que retorna os mesmos campos de dados que o main consulta, mas para um fornecedor específico.

SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers
WHERE SupplierID = @SupplierID

A próxima tela nos pede para nomear o procedimento armazenado que será gerado automaticamente. Nomeie este procedimento Suppliers_SelectBySupplierID armazenado e clique em Avançar.

Nomeie o procedimento armazenado Suppliers_SelectBySupplierID

Figura 9: Nomear o procedimento Suppliers_SelectBySupplierID armazenado (clique para exibir a imagem em tamanho real)

Por fim, o assistente nos solicita os padrões de acesso a dados e os nomes de método a serem usados para o TableAdapter. Deixe as duas caixas de seleção marcadas, mas renomeie os FillBy métodos e GetDataBy como FillBySupplierID e GetSupplierBySupplierID, respectivamente.

Nomeie os métodos TableAdapter FillBySupplierID e GetSupplierBySupplierID

Figura 10: nomear os métodos FillBySupplierID TableAdapter e GetSupplierBySupplierID (clique para exibir a imagem em tamanho real)

Clique em Concluir para concluir o assistente.

Etapa 6: Criando a camada de lógica de negócios

Antes de criarmos uma página ASP.NET que usa a coluna computada criada na Etapa 1, primeiro precisamos adicionar os métodos correspondentes à BLL. Nossa página de ASP.NET, que criaremos na Etapa 7, permitirá que os usuários exibam e editem fornecedores. Portanto, precisamos de nossa BLL para fornecer, no mínimo, um método para obter todos os fornecedores e outro para atualizar um fornecedor específico.

Crie um novo arquivo de classe chamado SuppliersBLLWithSprocs na ~/App_Code/BLL pasta e adicione o seguinte código:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class SuppliersBLLWithSprocs
{
    private SuppliersTableAdapter _suppliersAdapter = null;
    protected SuppliersTableAdapter Adapter
    {
        get
        {
            if (_suppliersAdapter == null)
                _suppliersAdapter = new SuppliersTableAdapter();
            return _suppliersAdapter;
        }
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
    public NorthwindWithSprocs.SuppliersDataTable GetSuppliers()
    {
        return Adapter.GetSuppliers();
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Update, true)]
    public bool UpdateSupplier(string companyName, string contactName, 
        string contactTitle, int supplierID)
    {
        NorthwindWithSprocs.SuppliersDataTable suppliers = 
            Adapter.GetSupplierBySupplierID(supplierID);
        if (suppliers.Count == 0)
            // no matching record found, return false
            return false;
        NorthwindWithSprocs.SuppliersRow supplier = suppliers[0];
        supplier.CompanyName = companyName;
        if (contactName == null) 
            supplier.SetContactNameNull(); 
        else 
            supplier.ContactName = contactName;
        if (contactTitle == null) 
            supplier.SetContactTitleNull(); 
        else 
            supplier.ContactTitle = contactTitle;
        // Update the product record
        int rowsAffected = Adapter.Update(supplier);
        // Return true if precisely one row was updated, otherwise false
        return rowsAffected == 1;
    }
}

Assim como as outras classes BLL, SuppliersBLLWithSprocs tem umaAdapterprotectedpropriedade que retorna uma instância da SuppliersTableAdapter classe juntamente com dois public métodos: GetSuppliers e UpdateSupplier. O GetSuppliers método chama e retorna o SuppliersDataTable retornado pelo método correspondente GetSupplier na Camada de Acesso a Dados. O UpdateSupplier método recupera informações sobre o fornecedor específico que está sendo atualizado por meio de uma chamada para o método DAL s GetSupplierBySupplierID(supplierID) . Em seguida, ele atualiza as CategoryNamepropriedades , ContactNamee ContactTitle e confirma essas alterações no banco de dados chamando o método da Camada de Update Acesso a Dados, passando o objeto modificado SuppliersRow .

Observação

Exceto para SupplierID e CompanyName, todas as colunas na tabela Fornecedores permitem NULL valores. Portanto, se os parâmetros ou passados contactName foremnull, precisaremos definir as propriedades e ContactTitle correspondentes ContactName para um NULL valor de banco de dados usando os SetContactNameNull métodos e SetContactTitleNullcontactTitle , respectivamente.

Etapa 7: Trabalhando com a coluna computada da camada de apresentação

Com a coluna computada adicionada à Suppliers tabela e o DAL e a BLL atualizados adequadamente, estamos prontos para criar uma página ASP.NET que funciona com a FullContactName coluna computada. Comece abrindo a ComputedColumns.aspx página na AdvancedDAL pasta e arraste um GridView da Caixa de Ferramentas para o Designer. Defina a propriedade gridView como ID e, de sua marca inteligente, associe-a a um novo ObjectDataSource chamado SuppliersDataSource.Suppliers Configure o ObjectDataSource para usar a SuppliersBLLWithSprocs classe que adicionamos novamente na Etapa 6 e clique em Avançar.

Configurar o ObjectDataSource para usar a classe SuppliersBLLWithSprocs

Figura 11: Configurar o ObjectDataSource para usar a SuppliersBLLWithSprocs classe (clique para exibir a imagem em tamanho real)

Há apenas dois métodos definidos na SuppliersBLLWithSprocs classe : GetSuppliers e UpdateSupplier. Verifique se esses dois métodos estão especificados nas guias SELECT e UPDATE, respectivamente, e clique em Concluir para concluir a configuração do ObjectDataSource.

Após a conclusão do assistente de Configuração da Fonte de Dados, o Visual Studio adicionará um BoundField para cada um dos campos de dados retornados. Remova BoundField SupplierID e altere as HeaderText propriedades de CompanyName, ContactName, ContactTitlee FullContactName BoundFields para Company, Contact Name, Title e Full Contact Name, respectivamente. Na marca inteligente, marcar caixa de seleção Habilitar Edição para ativar os recursos de edição internos do GridView.

Além de adicionar BoundFields ao GridView, a conclusão do Assistente de Fonte de Dados também faz com que o Visual Studio defina a propriedade objectDataSource como OldValuesParameterFormatString original_{0}. Reverta essa configuração de volta para seu valor padrão, {0} .

Depois de fazer essas edições para GridView e ObjectDataSource, sua marcação declarativa deve ser semelhante à seguinte:

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="CompanyName" 
            HeaderText="Company" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="ContactName" 
            HeaderText="Contact Name" 
            SortExpression="ContactName" />
        <asp:BoundField DataField="ContactTitle" 
            HeaderText="Title" 
            SortExpression="ContactTitle" />
        <asp:BoundField DataField="FullContactName" 
            HeaderText="Full Contact Name"
            SortExpression="FullContactName" 
            ReadOnly="True" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLLWithSprocs" 
        UpdateMethod="UpdateSupplier">
    <UpdateParameters>
        <asp:Parameter Name="companyName" Type="String" />
        <asp:Parameter Name="contactName" Type="String" />
        <asp:Parameter Name="contactTitle" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Em seguida, visite esta página por meio de um navegador. Como mostra a Figura 12, cada fornecedor é listado em uma grade que inclui a FullContactName coluna , cujo valor é simplesmente a concatenação das outras três colunas formatadas como ContactName (ContactTitle, CompanyName) .

Cada fornecedor é listado na grade

Figura 12: Cada fornecedor está listado na grade (clique para exibir a imagem em tamanho real)

Clicar no botão Editar para um fornecedor específico causa um postback e tem essa linha renderizada em sua interface de edição (consulte a Figura 13). As três primeiras colunas são renderizadas em sua interface de edição padrão : um controle TextBox cuja Text propriedade é definida como o valor do campo de dados. A FullContactName coluna, no entanto, permanece como texto. Quando boundfields foram adicionados ao GridView na conclusão do assistente de Configuração da Fonte de Dados, a FullContactName propriedade BoundField s ReadOnly foi definida true como porque a coluna correspondente FullContactName no SuppliersDataTable tem sua ReadOnly propriedade definida truecomo . Conforme observado na Etapa 4, a FullContactName propriedade s ReadOnly foi definida true como porque o TableAdapter detectou que a coluna era uma coluna computada.

A coluna FullContactName não é editável

Figura 13: A FullContactName coluna não é editável (clique para exibir a imagem em tamanho real)

Vá em frente e atualize o valor de uma ou mais das colunas editáveis e clique em Atualizar. Observe como o FullContactName valor s é atualizado automaticamente para refletir a alteração.

Observação

Atualmente, o GridView usa BoundFields para os campos editáveis, resultando na interface de edição padrão. Como o CompanyName campo é necessário, ele deve ser convertido em um TemplateField que inclui um RequiredFieldValidator. Eu deixo isso como um exercício para o leitor interessado. Consulte o tutorial Adicionando controles de validação ao tutorial De edição e inserção de interfaces para obter instruções passo a passo sobre como converter um BoundField em um TemplateField e adicionar controles de validação.

Resumo

Ao definir o esquema de uma tabela, o Microsoft SQL Server permite a inclusão de colunas computadas. São colunas cujos valores são calculados de uma expressão que geralmente faz referência aos valores de outras colunas no mesmo registro. Como os valores das colunas computadas são baseados em uma expressão, eles são somente leitura e não podem ser atribuídos a um valor em uma instrução INSERT ou UPDATE . Isso introduz desafios ao usar uma coluna computada na consulta main de um TableAdapter que tenta gerar automaticamente instruções , UPDATEe DELETE correspondentesINSERT.

Neste tutorial, discutimos técnicas para contornar os desafios colocados pelas colunas computadas. Em particular, usamos procedimentos armazenados em nosso TableAdapter para superar a fragilidade inerente a TableAdapters que usam instruções SQL ad hoc. Ao fazer com que o assistente TableAdapter crie novos procedimentos armazenados, é importante que tenhamos a consulta main omitir inicialmente todas as colunas computadas porque sua presença impede que os procedimentos armazenados de modificação de dados sejam gerados. Depois que o TableAdapter tiver sido configurado inicialmente, seu SelectCommand procedimento armazenado poderá ser retoolizado para incluir todas as colunas computadas.

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 Hilton Geisenow e Teresa Murphy. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.