Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
por Scott Mitchell
Ao trabalhar com um banco de dados, é comum solicitar dados espalhados por várias tabelas. Para recuperar dados de duas tabelas diferentes, podemos usar uma subconsulta correlacionada ou uma operação JOIN. Neste tutorial, comparamos subconsultas correlacionadas e a sintaxe JOIN antes de ver como criar um TableAdapter que inclui um JOIN em sua consulta principal.
Introdução
Com bancos de dados relacionais, os dados com os quais estamos interessados em trabalhar geralmente estão espalhados por várias tabelas. Por exemplo, ao exibir informações sobre o produto, provavelmente queremos listar a categoria correspondente de cada produto e os nomes dos fornecedores. A Products tabela tem CategoryID e SupplierID valores, mas a categoria real e os nomes dos fornecedores estão na Categories e na Suppliers, respectivamente.
Para recuperar informações de outra tabela relacionada, podemos usar subconsultas correlacionadas ou JOINs. Uma subconsulta correlacionada é uma consulta aninhada SELECT que faz referência a colunas na consulta externa. Por exemplo, no tutorial Criando uma camada de acesso a dados , usamos duas subconsultas correlacionadas na ProductsTableAdapter consulta principal para retornar os nomes de categoria e fornecedor para cada produto. A JOIN é uma construção SQL que mescla linhas relacionadas de duas tabelas diferentes. Usamos um JOIN no tutorial Consultando dados com o controle SqlDataSource para exibir informações de categoria ao lado de cada produto.
A razão pela qual nos abstivemos de usar JOINs com os TableAdapters é por limitações no assistente de TableAdapters para gerar automaticamente as instruções correspondentes INSERT, UPDATE e DELETE. Mais especificamente, se a consulta principal do TableAdapter contiver algum JOINs, o TableAdapter não poderá criar automaticamente as instruções SQL ad-hoc ou os procedimentos armazenados para as suas propriedades InsertCommand, UpdateCommand ou DeleteCommand.
Neste tutorial, vamos comparar brevemente e contrastar subconsultas correlacionadas e JOIN s antes de explorar como criar um TableAdapter que inclui JOIN s em sua consulta principal.
Comparando e contrastando subconsultas correlacionadas eJOIN
Lembre-se de que o ProductsTableAdapter criado no primeiro tutorial no Northwind DataSet usa subconsultas correlacionadas para trazer de volta a categoria correspondente de cada produto e o nome do fornecedor. A ProductsTableAdapter consulta principal é mostrada abaixo.
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
(SELECT CategoryName FROM Categories WHERE Categories.CategoryID =
Products.CategoryID) as CategoryName,
(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID =
Products.SupplierID) as SupplierName
FROM Products
As duas subconsultas correlacionadas - (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) e (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) - são consultas SELECT que retornam um único valor por produto como uma coluna adicional na lista de colunas da instrução externa SELECT.
Alternativamente, um JOIN pode ser usado para devolver o fornecedor de cada produto e o nome da categoria. A consulta a seguir retorna a mesma saída que a anterior, mas usa JOIN s no lugar de subconsultas:
SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
Categories.CategoryName,
Suppliers.CompanyName as SupplierName
FROM Products
LEFT JOIN Categories ON
Categories.CategoryID = Products.CategoryID
LEFT JOIN Suppliers ON
Suppliers.SupplierID = Products.SupplierID
A JOIN mescla os registros de uma tabela com os registros de outra tabela com base em alguns critérios. Na consulta acima, por exemplo, o LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID instrui o SQL Server a mesclar cada registro de produto com o registro da categoria cujo valor de CategoryID corresponde ao valor de CategoryID do produto. O resultado mesclado nos permite trabalhar com os campos de categoria correspondentes para cada produto (como CategoryName).
Observação
JOIN s são comumente usados ao consultar dados de bancos de dados relacionais. Se você é novo na JOIN sintaxe ou precisa melhorar um pouco seu uso, eu recomendaria o tutorial SQL Join na W3 Schools. Também vale a pena ler as JOIN seções Fundamentos e Fundamentos de Subconsulta dos Manuais Online do SQL.
Como JOIN s e subconsultas correlacionadas podem ser usadas para recuperar dados relacionados de outras tabelas, muitos desenvolvedores ficam coçando a cabeça e se perguntando qual abordagem usar. Todos os gurus do SQL com quem conversei disseram aproximadamente a mesma coisa, que isso realmente não importa em termos de desempenho, pois o SQL Server produzirá planos de execução aproximadamente idênticos. O conselho deles, então, é usar a técnica com a qual você e sua equipe estão mais confortáveis. Vale a pena notar que, depois de darem este conselho, estes peritos expressam imediatamente a sua preferência por JOIN s em vez de subconsultas correlacionadas.
Ao criar uma camada de acesso a dados usando conjuntos de dados tipados, as ferramentas funcionam melhor ao usar subconsultas. Em particular, o assistente de TableAdapter não gerará automaticamente as instruções INSERT, UPDATE e DELETE correspondentes se a consulta principal contiver alguém JOINes, mas gerará automaticamente essas instruções quando subconsultas correlacionadas forem usadas.
Para explorar essa lacuna, crie um DataSet Tipado temporário na pasta ~/App_Code/DAL. Durante o assistente de Configuração do TableAdapter, escolha usar instruções SQL ad-hoc e insira a seguinte SELECT consulta (consulte a Figura 1):
SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
Categories.CategoryName,
Suppliers.CompanyName as SupplierName
FROM Products
LEFT JOIN Categories ON
Categories.CategoryID = Products.CategoryID
LEFT JOIN Suppliers ON
Suppliers.SupplierID = Products.SupplierID
Figura 1: Insira uma consulta principal que contenha JOIN s (Clique para visualizar a imagem em tamanho real)
Por padrão, o TableAdapter criará automaticamente INSERT, UPDATE e DELETE instruções com base na consulta principal. Se clicar no botão Avançadas, poderá ver que esta funcionalidade está ativada. Apesar desta configuração, o TableAdapter não poderá criar as instruções INSERT, UPDATE e DELETE porque a consulta principal contém uma JOIN.
Figura 2: Insira uma consulta principal que contenha JOIN s
Clique em Concluir para finalizar o assistente. Neste ponto, o Designer do DataSet incluirá um único TableAdapter com uma DataTable com colunas para cada um dos campos retornados na lista de colunas da consulta SELECT. Isso inclui o CategoryName e o SupplierName, como mostra a Figura 3.
Figura 3: A DataTable inclui uma coluna para cada campo retornado na lista de colunas
Enquanto o DataTable tem as colunas apropriadas, o TableAdapter não tem valores para suas InsertCommandpropriedades , UpdateCommande DeleteCommand . Para confirmar isso, clique no TableAdapter no Designer e, em seguida, vá para a janela Propriedades. Lá você verá que as InsertCommandpropriedades , UpdateCommand, e DeleteCommand estão definidas como (Nenhuma) .
Figura 4: As propriedades InsertCommand, UpdateCommand e DeleteCommand estão definidas como (Nenhum) (Clique para visualizar a imagem em tamanho normal)
Para contornar essa falha, podemos fornecer manualmente as instruções SQL e os parâmetros para o InsertCommand, UpdateCommande DeleteCommand propriedades através da janela Propriedades. Como alternativa, poderíamos começar configurando a consulta principal do TableAdapter para não incluir nenhum JOIN s. Isso permitirá que as instruções INSERT, UPDATE e DELETE sejam geradas automaticamente para nós. Depois de concluir o assistente, podemos então atualizar manualmente o TableAdapter's SelectCommand a partir da janela de Propriedades para que inclua a sintaxe JOIN.
Embora esta abordagem funcione, é muito frágil ao usar consultas SQL ad-hoc, porque, sempre que a consulta principal do TableAdapter é reconfigurada por meio do assistente, as instruções INSERT, UPDATE e DELETE geradas automaticamente são recriadas. Isso significa que todas as personalizações que fizemos mais tarde seriam perdidas se clicássemos com o botão direito do mouse no TableAdapter, escolhêssemos Configurar no menu de contexto e concluíssemos o assistente novamente.
A fragilidade das instruções INSERT, UPDATE e DELETE, geradas automaticamente pelo TableAdapter, é, felizmente, limitada às instruções SQL ad hoc. Se o seu TableAdapter usa procedimentos armazenados, você pode personalizar o SelectCommand, InsertCommand, UpdateCommandou DeleteCommand procedimentos armazenados e executar novamente o assistente de configuração do TableAdapter sem ter que temer que os procedimentos armazenados serão modificados.
Ao longo das próximas etapas, criaremos um TableAdapter que, inicialmente, usa uma consulta principal que omite qualquer JOIN s para que os procedimentos armazenados de inserção, atualização e exclusão correspondentes sejam gerados automaticamente. Em seguida, atualizaremos o SelectCommand para que use um JOIN que retorna colunas adicionais de tabelas relacionadas. Finalmente, criaremos uma classe Business Logic Layer correspondente e demonstraremos o uso do TableAdapter em uma página da Web ASP.NET.
Etapa 1: Criando o TableAdapter usando uma consulta principal simplificada
Para este tutorial, adicionaremos um TableAdapter e um DataTable fortemente tipado para a tabela Employees no DataSet NorthwindWithSprocs. A Employees tabela contém um ReportsTo campo que especifica o EmployeeID do gestor do colaborador. Por exemplo, a funcionária Anne Dodsworth tem um ReportTo valor de 5, que é o EmployeeID de Steven Buchanan. Consequentemente, Anne se reporta a Steven, seu empresário. Além de relatar o ReportsTo valor de cada funcionário, também poderemos querer obter o nome do seu gerente. Isso pode ser feito usando um JOIN. Mas usar um JOIN ao criar inicialmente o TableAdapter impede que o assistente gere automaticamente os recursos de inserção, atualização e exclusão correspondentes. Portanto, começaremos criando um TableAdapter cuja consulta principal não contém nenhum JOIN s. Em seguida, na Etapa 2, atualizaremos o procedimento armazenado da consulta principal para recuperar o nome do gerente por meio de um JOIN.
Comece abrindo o NorthwindWithSprocs DataSet na ~/App_Code/DAL pasta. Clique com o botão direito do mouse no Designer, selecione a opção Adicionar no menu de contexto e escolha o item de menu TableAdapter. Isso iniciará o assistente de configuração do TableAdapter. Como mostra a Figura 5, peça ao assistente para criar novos procedimentos armazenados e clique em Avançar. Para uma revisão sobre a criação de novos procedimentos armazenados a partir do assistente de TableAdapter, consulte o tutorial Criando novos procedimentos armazenados para os TableAdapters do conjunto de dados tipados.
Figura 5: Selecione a opção Create new stored procedures (Clique para visualizar a imagem em tamanho real)
Use a seguinte SELECT instrução para a consulta principal do TableAdapter:
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Como esta consulta não inclui nenhum JOIN, o assistente TableAdapter criará automaticamente procedimentos armazenados com instruções correspondentes a INSERT, UPDATE e DELETE, bem como um procedimento armazenado para executar a consulta principal.
A etapa a seguir nos permite nomear os procedimentos armazenados do TableAdapter. Use os nomes Employees_Select, Employees_Insert, Employees_Update, e Employees_Delete, como mostra a Figura 6.
Figura 6: Nomeie os procedimentos armazenados do TableAdapter (Clique para visualizar a imagem em tamanho real)
A etapa final solicita-nos que nomeemos os métodos do TableAdapter. Use Fill e GetEmployees como os nomes do método. Certifique-se também de deixar a caixa de seleção Criar métodos para enviar atualizações diretamente para o banco de dados (GenerateDBDirectMethods) marcada.
Figura 7: Nomeie os métodos Fill de TableAdapter e GetEmployees (Clique para visualizar a imagem em tamanho real)
Depois de concluir o assistente, reserve um momento para examinar as rotinas armazenadas no banco de dados. Você deve ver quatro novos: Employees_Select, Employees_Insert, Employees_Update, e Employees_Delete. Em seguida, inspecione o EmployeesDataTable e o EmployeesTableAdapter que acabou de ser criado. O DataTable contém uma coluna para cada campo retornado pela consulta principal. Clique no TableAdapter e, em seguida, vá para a janela Propriedades. Lá, verá que as propriedades InsertCommand, UpdateCommand e DeleteCommand estão configuradas corretamente para chamar os procedimentos armazenados correspondentes.
Figura 8: O TableAdapter inclui recursos de inserção, atualização e exclusão (Clique para visualizar a imagem em tamanho real)
Com as inserções, atualizações e exclusões de procedures armazenadas criadas automaticamente e as InsertCommand, UpdateCommand e DeleteCommand propriedades corretamente configuradas, estamos prontos para personalizar o procedimento armazenado SelectCommand para retornar informações adicionais sobre o gerente de cada funcionário. Especificamente, precisamos atualizar o Employees_Select procedimento armazenado para usar um JOIN e retornar os valores de FirstName e LastName do gerente. Depois que o procedimento armazenado tiver sido atualizado, precisaremos atualizar a DataTable para que ela inclua essas colunas adicionais. Abordaremos essas duas tarefas nas etapas 2 e 3.
Etapa 2: Personalizando o procedimento armazenado para incluir umJOIN
Comece por ir ao Explorador de Servidores, detalhando a pasta de Procedimentos Armazenados do banco de dados Northwind e abrindo o procedimento armazenado Employees_Select. Se você não vir esse procedimento armazenado, clique com o botão direito do mouse na pasta Stored Procedures e escolha Atualizar. Atualize o procedimento armazenado para que ele use um LEFT JOIN para retornar o nome e o sobrenome do gerente:
SELECT Employees.EmployeeID, Employees.LastName,
Employees.FirstName, Employees.Title,
Employees.HireDate, Employees.ReportsTo,
Employees.Country,
Manager.FirstName as ManagerFirstName,
Manager.LastName as ManagerLastName
FROM Employees
LEFT JOIN Employees AS Manager ON
Employees.ReportsTo = Manager.EmployeeID
Depois de atualizar a SELECT instrução, salve as alterações indo para o menu Arquivo e escolhendo Salvar Employees_Select. Como alternativa, você pode clicar no ícone Salvar na barra de ferramentas ou pressionar Ctrl+S. Depois de salvar as alterações, clique com o botão direito do Employees_Select mouse no procedimento armazenado no Gerenciador de Servidores e escolha Executar. Isso executará o procedimento armazenado e mostrará seus resultados na janela Saída (veja a Figura 9).
Figura 9: Os resultados dos procedimentos armazenados são exibidos na janela de saída (Clique para visualizar a imagem em tamanho real)
Etapa 3: Atualizando as colunas da DataTable
Neste ponto, o Employees_Select procedimento armazenado retorna os valores ManagerFirstName e ManagerLastName, mas o EmployeesDataTable não tem essas colunas. Essas colunas ausentes podem ser adicionadas à DataTable de duas maneiras:
- Manualmente - clique com o botão direito do mouse na DataTable no DataSet Designer e, no menu Adicionar, escolha Coluna. Em seguida, você pode nomear a coluna e definir suas propriedades de acordo.
-
Automaticamente - o assistente de Configuração de TableAdapter atualizará as colunas de DataTable para refletir os campos retornados pelo
SelectCommandprocedimento armazenado. Ao usar instruções SQL ad-hoc, o assistente também removerá asInsertCommand,UpdateCommandeDeleteCommandpropriedades, dado que oSelectCommandagora contém umJOIN. Mas ao usar procedimentos armazenados, essas propriedades de comando permanecem intactas.
Exploramos manualmente a adição de colunas DataTable em tutoriais anteriores, incluindo Master/Detail Using a Bulleted List of Master Records with a Details DataList e Uploading Files, e analisaremos esse processo novamente com mais detalhes no nosso próximo tutorial. Para este tutorial, no entanto, vamos usar a abordagem automática por meio do assistente de configuração do TableAdapter.
Comece clicando com o botão direito do rato em EmployeesTableAdapter e selecionando Configurar no menu de contexto. Isso abre o assistente de Configuração do TableAdapter, que lista os procedimentos armazenados usados para selecionar, inserir, atualizar e excluir, juntamente com seus valores de retorno e parâmetros (se houver). A Figura 10 mostra esse assistente. Aqui podemos ver que o Employees_Select procedimento armazenado agora retorna os campos ManagerFirstName e ManagerLastName.
Figura 10: O assistente mostra a lista de colunas atualizada para o procedimento armazenado (Clique para visualizar a Employees_Selectimagem em tamanho real)
Conclua o assistente clicando em Concluir. Ao retornar ao DataSet Designer, o EmployeesDataTable inclui duas colunas adicionais: ManagerFirstName e ManagerLastName.
Figura 11: A EmployeesDataTable contém duas novas colunas (Clique para visualizar a imagem em tamanho real)
Para ilustrar que o procedimento armazenado atualizado Employees_Select está em vigor e que os recursos de inserção, atualização e exclusão do TableAdapter ainda estão funcionais, vamos criar um site que permita aos usuários visualizar e excluir funcionários. Antes de criarmos essa página, no entanto, precisamos primeiro criar uma nova classe na Camada de Lógica de Negócios para trabalhar com funcionários do NorthwindWithSprocs DataSet. Na Etapa 4, criaremos uma EmployeesBLLWithSprocs classe. Na etapa 5, usaremos essa classe de uma página ASP.NET.
Etapa 4: Implementando a camada de lógica de negócios
Crie um novo arquivo de classe na ~/App_Code/BLL pasta chamada EmployeesBLLWithSprocs.cs. Essa classe imita a semântica da classe existente EmployeesBLL , apenas esta nova fornece menos métodos e usa o NorthwindWithSprocs DataSet (em vez do Northwind DataSet). Adicione o seguinte código à EmployeesBLLWithSprocs classe.
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 EmployeesBLLWithSprocs
{
private EmployeesTableAdapter _employeesAdapter = null;
protected EmployeesTableAdapter Adapter
{
get
{
if (_employeesAdapter == null)
_employeesAdapter = new EmployeesTableAdapter();
return _employeesAdapter;
}
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, true)]
public NorthwindWithSprocs.EmployeesDataTable GetEmployees()
{
return Adapter.GetEmployees();
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Delete, true)]
public bool DeleteEmployee(int employeeID)
{
int rowsAffected = Adapter.Delete(employeeID);
// Return true if precisely one row was deleted, otherwise false
return rowsAffected == 1;
}
}
A EmployeesBLLWithSprocs propriedade class s Adapter retorna uma instância do NorthwindWithSprocs DataSet s EmployeesTableAdapter. Isso é usado pelas classes s GetEmployees e DeleteEmployee métodos. O método GetEmployees chama o método correspondente EmployeesTableAdapterGetEmployees, que invoca o procedimento armazenado Employees_Select e insere os seus resultados num EmployeeDataTable. O DeleteEmployee método chama similarmente o EmployeesTableAdapter método s Delete , que invoca o Employees_Delete procedimento armazenado.
Etapa 5: Trabalhando com os dados na camada de apresentação
Com a EmployeesBLLWithSprocs aula concluída, estamos prontos para trabalhar com os dados dos funcionários através de uma página de ASP.NET. Abra a página JOINs.aspx na pasta AdvancedDAL e arraste um GridView da Caixa de Ferramentas para o Designer, definindo a sua propriedade ID como Employees. Em seguida, na etiqueta inteligente de GridView, ligue a grelha a um novo controlo ObjectDataSource chamado EmployeesDataSource.
Configure o ObjectDataSource para usar a classe EmployeesBLLWithSprocs e, nas abas SELECT e DELETE, verifique se os métodos GetEmployees e DeleteEmployee estão selecionados nas listas suspensas. Clique em Concluir para concluir a configuração de ObjectDataSource.
Figura 12: Configurar o ObjectDataSource para usar a classe (EmployeesBLLWithSprocs imagem em tamanho real)
Figura 13: Fazer com que o ObjectDataSource use os métodos GetEmployees e DeleteEmployee (Clique para visualizar a imagem em tamanho real)
O Visual Studio adicionará um BoundField ao GridView para cada uma das EmployeesDataTable colunas s. Remova todos esses BoundFields, exceto Title, LastName, FirstName, ManagerFirstNamee ManagerLastName renomeie as HeaderText propriedades dos últimos quatro BoundFields para Sobrenome, Nome, Nome do Gerente e Sobrenome do Gerente, respectivamente.
Para permitir que os usuários excluam funcionários desta página, precisamos fazer duas coisas. Primeiro, instrua o GridView a fornecer funcionalidades de eliminação marcando a opção Ativar eliminação na sua etiqueta inteligente. Em segundo lugar, altere a propriedade ObjectDataSource s OldValuesParameterFormatString do valor definido pelo assistente ObjectDataSource (original_{0}) para seu valor padrão ({0}). Depois de fazer essas alterações, sua marcação declarativa de GridView e ObjectDataSource deve ser semelhante à seguinte:
<asp:GridView ID="Employees" runat="server" AutoGenerateColumns="False"
DataKeyNames="EmployeeID" DataSourceID="EmployeesDataSource">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
<asp:BoundField DataField="Title"
HeaderText="Title"
SortExpression="Title" />
<asp:BoundField DataField="LastName"
HeaderText="Last Name"
SortExpression="LastName" />
<asp:BoundField DataField="FirstName"
HeaderText="First Name"
SortExpression="FirstName" />
<asp:BoundField DataField="ManagerFirstName"
HeaderText="Manager's First Name"
SortExpression="ManagerFirstName" />
<asp:BoundField DataField="ManagerLastName"
HeaderText="Manager's Last Name"
SortExpression="ManagerLastName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="EmployeesDataSource" runat="server"
DeleteMethod="DeleteEmployee" OldValuesParameterFormatString="{0}"
SelectMethod="GetEmployees" TypeName="EmployeesBLLWithSprocs">
<DeleteParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
Teste a página visitando-a através de um navegador. Como mostra a Figura 14, a página listará cada funcionário e o nome de seu gerente (supondo que eles tenham um).
Figura 14: O JOIN no Employees_Select procedimento de armazenamento retorna o nome do gerente (Clique para visualizar a imagem em tamanho real)
Clicar no botão Excluir inicia o fluxo de trabalho de exclusão, que culmina na execução do Employees_Delete procedimento armazenado. No entanto, a instrução DELETE tentada no procedimento armazenado falha devido a uma violação de restrição de chave estrangeira (consulte a Figura 15). Especificamente, cada funcionário tem um ou mais registros na Orders tabela, fazendo com que a exclusão falhe.
Figura 15: A exclusão de um funcionário que tem pedidos correspondentes resulta em uma violação de restrição de chave estrangeira (Clique para visualizar a imagem em tamanho real)
Para permitir que um funcionário seja excluído, você pode:
- Atualize a restrição de chave estrangeira para exclusões em cascata,
- Exclua manualmente os
Ordersregistros da tabela do(s) funcionário(s) que você deseja excluir, ou - Atualize o
Employees_Deleteprocedimento armazenado para primeiro excluir os registros relacionados daOrderstabela antes de excluir oEmployeesregistro. Discutimos essa técnica no tutorial Usando procedimentos armazenados existentes para o conjunto de dados tipado s TableAdapters .
Deixo isto como um exercício para o leitor.
Resumo
Ao trabalhar com bancos de dados relacionais, é comum que as consultas extraiam seus dados de várias tabelas relacionadas. Subconsultas correlacionadas e JOIN s fornecem duas técnicas diferentes para acessar dados de tabelas relacionadas em uma consulta. Em tutoriais anteriores, utilizámos mais frequentemente subconsultas correlacionadas porque o TableAdapter não pode gerar automaticamente as instruções INSERT, UPDATE e DELETE para consultas que envolvem JOINs. Embora esses valores possam ser fornecidos manualmente, ao usar instruções SQL ad-hoc, todas as personalizações serão sobrepostas quando o Assistente de Configuração do TableAdapter for concluído.
Felizmente, TableAdapters criados usando procedimentos armazenados não sofrem da mesma fragilidade que aqueles criados usando instruções SQL ad-hoc. Portanto, é viável criar um TableAdapter cuja consulta principal usa um JOIN ao usar procedimentos armazenados. Neste tutorial, vimos como criar um TableAdapter. Começámos por usar uma consulta JOIN sem SELECT para a consulta principal do TableAdapter, de modo a que os procedimentos armazenados de inserção, atualização e eliminação correspondentes fossem criados automaticamente. Com a configuração inicial do TableAdapter concluída, modificámos o procedimento armazenado SelectCommand para usar um JOIN e executámos novamente o assistente de Configuração do TableAdapter para atualizar as colunas EmployeesDataTable.
A nova execução do assistente de Configuração do TableAdapter atualizou automaticamente as EmployeesDataTable colunas para refletir os campos de dados retornados Employees_Select pelo procedimento armazenado. Como alternativa, poderíamos ter adicionado essas colunas manualmente à DataTable. Exploraremos manualmente a adição de colunas à DataTable no próximo tutorial.
Feliz Programação!
Sobre o Autor
Scott Mitchell, autor de sete livros sobre ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias Web da Microsoft desde 1998. Scott trabalha como consultor, formador e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Ele pode ser contatado em mitchell@4GuysFromRolla.com.
Um agradecimento especial a
Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Hilton Geisenow, David Suru e Teresa Murphy. Interessado em rever meus próximos artigos do MSDN? Se for o caso, envie-me uma mensagem para mitchell@4GuysFromRolla.com.