Atualizar o TableAdapter para usar JOINs (VB)
por Scott Mitchell
Ao trabalhar com um banco de dados, é comum solicitar dados distribuídos em 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 examinar como criar um TableAdapter que inclui um JOIN em sua consulta main.
Introdução
Com bancos de dados relacionais, os dados com os quais estamos interessados em trabalhar geralmente são distribuídos em várias tabelas. Por exemplo, ao exibir informações do produto, provavelmente queremos listar os nomes de cada categoria e fornecedor correspondentes de cada produto. A Products
tabela tem CategoryID
valores e SupplierID
, mas os nomes reais da categoria e do Categories
fornecedor estão nas tabelas e Suppliers
, respectivamente.
Para recuperar informações de outra tabela relacionada, podemos usar subconsultas correlacionadas ou JOIN
s. 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 s main para retornar os nomes de categoria e fornecedor para cada produto. Um JOIN
é um constructo SQL que mescla linhas relacionadas de duas tabelas diferentes. Usamos um JOIN
no tutorial Consultando Dados com o SqlDataSource Control para exibir informações de categoria ao lado de cada produto.
O motivo pelo qual nos abstivemos de usar JOIN
s com o TableAdapters é devido a limitações no assistente do TableAdapter para gerar automaticamente instruções correspondentes INSERT
, UPDATE
e DELETE
. Mais especificamente, se a consulta main tableAdapter contiver qualquer JOIN
s, o TableAdapter não poderá criar automaticamente as instruções SQL ad hoc ou procedimentos armazenados para suas InsertCommand
propriedades , UpdateCommand
e DeleteCommand
.
Neste tutorial, compararemos e compararemos brevemente subconsultas correlacionadas e JOIN
s antes de explorar como criar um TableAdapter que inclua JOIN
s em sua consulta main.
Comparando e contrastando subconsultas correlacionadas eJOIN
s
Lembre-se de que o ProductsTableAdapter
criado no primeiro tutorial no Northwind
DataSet usa subconsultas correlacionadas para trazer de volta cada categoria correspondente do produto e o nome do fornecedor. A ProductsTableAdapter
consulta s main é 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 – são SELECT
consultas que retornam um único valor por produto como uma coluna adicional na lista de colunas da instrução externa SELECT
(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID)
.
Como alternativa, um JOIN
pode ser usado para retornar o fornecedor e o nome da categoria de cada produto. A consulta a seguir retorna a mesma saída que a acima, 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
Um JOIN
mescla os registros de uma tabela com registros de outra tabela com base em alguns critérios. Na consulta acima, por exemplo, o instrui SQL Server LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID
a mesclar cada registro de produto com o registro de categoria cujo CategoryID
valor corresponde ao valor do CategoryID
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ê for novo na JOIN
sintaxe ou precisar melhorar um pouco seu uso, recomendo o tutorial ingressar no SQL nas Escolas W3. Também vale a pena ler as JOIN
seções Conceitos Básicos e Conceitos Básicos de Subconsulta dos Manuais Online do SQL.
Como JOIN
as subconsultas s e 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 realmente não importa o desempenho, pois SQL Server produzirão 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. Merece notar que, depois de dar este conselho, esses especialistas imediatamente expressam sua preferência de s em vez de JOIN
subconsultas correlacionadas.
Ao criar uma Camada de Acesso a Dados usando Conjuntos de Dados Tipado, as ferramentas funcionam melhor ao usar subconsultas. Em particular, o assistente tableAdapter s não gerará automaticamente instruções correspondentes INSERT
, UPDATE
e DELETE
se a consulta main contiver qualquer JOIN
s, mas gerará automaticamente essas instruções quando subconsultas correlacionadas forem usadas.
Para explorar essa deficiência, crie um Conjunto de Dados Digitado temporário na ~/App_Code/DAL
pasta . Durante o assistente de Configuração 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 exibir a imagem em tamanho real)
Por padrão, o TableAdapter criará INSERT
automaticamente instruções , UPDATE
e DELETE
com base na consulta main. Se você clicar no botão Avançado, poderá ver que esse recurso está habilitado. Apesar dessa configuração, o TableAdapter não poderá criar as INSERT
instruções , UPDATE
e DELETE
porque a consulta main contém um JOIN
.
Figura 2: insira uma consulta principal que contenha JOIN
s
Clique em Concluir para concluir o assistente. Neste ponto, o Designer do DataSet incluirá um único TableAdapter com um DataTable com colunas para cada um dos campos retornados na SELECT
lista de colunas da consulta. Isso inclui e CategoryName
SupplierName
, como mostra a Figura 3.
Figura 3: a DataTable inclui uma coluna para cada campo retornado na lista de colunas
Embora o DataTable tenha as colunas apropriadas, o TableAdapter não tem valores para suas InsertCommand
propriedades , UpdateCommand
e DeleteCommand
. Para confirmar isso, clique no TableAdapter no Designer e vá para o janela Propriedades. Lá, você verá que as InsertCommand
propriedades , UpdateCommand
e DeleteCommand
estão definidas como (Nenhum) .
Figura 4: As InsertCommand
propriedades , UpdateCommand
e DeleteCommand
são definidas como (Nenhum) (Clique para exibir a imagem em tamanho real)
Para contornar essa deficiência, podemos fornecer manualmente as instruções SQL e os parâmetros para as InsertCommand
propriedades , UpdateCommand
e DeleteCommand
por meio do janela Propriedades. Como alternativa, poderíamos começar configurando a consulta main tableAdapter para não incluir nenhum JOIN
s. Isso permitirá que as INSERT
instruções , UPDATE
e DELETE
sejam geradas automaticamente para nós. Depois de concluir o assistente, podemos atualizar manualmente o TableAdapter s SelectCommand
do janela Propriedades para que ele inclua a JOIN
sintaxe.
Embora essa abordagem funcione, ela é muito frágil ao usar consultas SQL ad hoc porque sempre que a consulta main do TableAdapter é configurada novamente por meio do assistente, as instruções , UPDATE
e DELETE
geradas INSERT
automaticamente são recriadas. Isso significa que todas as personalizações que fizemos mais tarde seriam perdidas se clicamos com o botão direito do mouse no TableAdapter, escolhemos Configurar no menu de contexto e concluímos o assistente novamente.
A fragilidade das instruções , UPDATE
e DELETE
geradas INSERT
automaticamente pelo TableAdapter é, felizmente, limitada a instruções SQL ad hoc. Se o TableAdapter usar procedimentos armazenados, você poderá personalizar os SelectCommand
procedimentos armazenados , InsertCommand
, UpdateCommand
ou DeleteCommand
e executar novamente o assistente de Configuração tableAdapter sem ter que temer que os procedimentos armazenados sejam modificados.
Nas próximas etapas, criaremos um TableAdapter que, inicialmente, usa uma consulta main 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. Por fim, criaremos uma classe de Camada de Lógica De Negócios 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 Employees
tabela no NorthwindWithSprocs
DataSet. A Employees
tabela contém um ReportsTo
campo que especificou o EmployeeID
do gerente do funcionário. 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 valor de ReportsTo
cada funcionário, talvez também queiramos recuperar o nome do 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 correspondentes de inserção, atualização e exclusão. Portanto, começaremos criando um TableAdapter cuja consulta main não contém nenhum JOIN
s. Em seguida, na Etapa 2, atualizaremos o procedimento armazenado de consulta main 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 de TableAdapter. Como a Figura 5 descreve, fazer com que o assistente crie novos procedimentos armazenados e clique em Avançar. Para obter uma atualização sobre como criar novos procedimentos armazenados do assistente TableAdapter s, consulte o tutorial Criando novos procedimentos armazenados para o TableAdapters do Conjunto de Dados Tipado .
Figura 5: selecione a opção Criar novos procedimentos armazenados (Clique para exibir a imagem em tamanho real)
Use a seguinte SELECT
instrução para a consulta main do TableAdapter:
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Como essa consulta não inclui nenhum JOIN
s, o assistente TableAdapter criará automaticamente procedimentos armazenados com instruções , UPDATE
e DELETE
correspondentesINSERT
, bem como um procedimento armazenado para executar a consulta main.
A etapa a seguir nos permite nomear os procedimentos armazenados do TableAdapter. Use os nomes Employees_Select
, Employees_Insert
, Employees_Update
e Employees_Delete
, conforme mostrado na Figura 6.
Figura 6: Nomeie os Procedimentos Armazenados do TableAdapter (clique para exibir a imagem em tamanho real)
A etapa final nos solicita o nome dos métodos tableAdapter. Use Fill
e GetEmployees
como os nomes dos métodos. Também deixe 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
TableAdapter e GetEmployees
(Clique para exibir a imagem em tamanho real)
Depois de concluir o assistente, reserve um momento para examinar os procedimentos armazenados no banco de dados. Você deverá ver quatro novos: Employees_Select
, Employees_Insert
, Employees_Update
e Employees_Delete
. Em seguida, inspecione o EmployeesDataTable
e EmployeesTableAdapter
o acabou de criar. A DataTable contém uma coluna para cada campo retornado pela consulta main. Clique no TableAdapter e vá para o janela Propriedades. Lá, você verá que as InsertCommand
propriedades , 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 exibir a imagem em tamanho real)
Com os procedimentos armazenados de inserção, atualização e exclusão criados automaticamente e as InsertCommand
propriedades , UpdateCommand
e DeleteCommand
configuradas corretamente, estamos prontos para personalizar o SelectCommand
procedimento armazenado s para retornar informações adicionais sobre cada gerente de funcionário. Especificamente, precisamos atualizar o Employees_Select
procedimento armazenado para usar um JOIN
e retornar os valores e LastName
s do FirstName
gerente. Depois que o procedimento armazenado for atualizado, precisaremos atualizar o DataTable para que ele inclua essas colunas adicionais. Abordaremos essas duas tarefas nas Etapas 2 e 3.
Etapa 2: Personalizando o procedimento armazenado para incluir umJOIN
Comece acessando o servidor Explorer, fazendo uma busca detalhada na pasta Procedimentos Armazenados do banco de dados Northwind e abrindo o Employees_Select
procedimento armazenado. Se você não vir esse procedimento armazenado, clique com o botão direito do mouse na pasta Procedimentos Armazenados 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 acessando o menu Arquivo e escolhendo Salvar Employees_Select
. Como alternativa, você pode clicar no ícone Salvar na barra de ferramentas ou clicar em Ctrl+S. Depois de salvar as alterações, clique com o botão direito do Employees_Select
mouse no procedimento armazenado na Explorer servidor e escolha Executar. Isso executará o procedimento armazenado e mostrará seus resultados na janela Saída (consulte a Figura 9).
Figura 9: Os resultados dos procedimentos armazenados são exibidos na janela saída (clique para exibir a imagem em tamanho real)
Etapa 3: Atualizando as colunas da DataTable s
Neste ponto, o Employees_Select
procedimento armazenado retorna ManagerFirstName
valores e ManagerLastName
, mas o EmployeesDataTable
está faltando essas colunas. Essas colunas ausentes podem ser adicionadas à DataTable de duas maneiras:
- Manualmente – clique com o botão direito do mouse na DataTable no Designer DataSet e, no menu Adicionar, escolha Coluna. Em seguida, você pode nomear a coluna e definir suas propriedades adequadamente.
- Automaticamente – o assistente de Configuração de TableAdapter atualizará as colunas de DataTable para refletir os campos retornados pelo
SelectCommand
procedimento armazenado. Ao usar instruções SQL ad hoc, o assistente também removerá asInsertCommand
propriedades ,UpdateCommand
eDeleteCommand
, já que oSelectCommand
agora contém umJOIN
. No entanto, ao usar procedimentos armazenados, essas propriedades de comando permanecem intactas.
Exploramos a adição manual de colunas DataTable em tutoriais anteriores, incluindo Mestre/Detalhe usando uma lista com marcadores de registros mestres com uma DataList de Detalhes e Carregando Arquivos, e examinaremos esse processo novamente com mais detalhes em nosso próximo tutorial. Para este tutorial, no entanto, vamos usar a abordagem automática por meio do assistente de Configuração de TableAdapter.
Comece clicando com o botão direito do EmployeesTableAdapter
mouse no 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 e parâmetros retornados (se houver). A Figura 10 mostra esse assistente. Aqui podemos ver que o Employees_Select
procedimento armazenado agora retorna os ManagerFirstName
campos e ManagerLastName
.
Figura 10: o assistente mostra a lista de colunas atualizada para o Employees_Select
procedimento armazenado (clique para exibir a imagem 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: o EmployeesDataTable
contém duas novas colunas (clique para exibir 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 uma página da Web que permita que os usuários exibam e excluam funcionários. No entanto, antes de criarmos essa página, 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.vb
. Essa classe imita a semântica da classe existente EmployeesBLL
, apenas essa nova fornece menos métodos e usa o NorthwindWithSprocs
DataSet (em vez do Northwind
DataSet). Adicione o código a seguir à classe EmployeesBLLWithSprocs
.
Imports NorthwindWithSprocsTableAdapters
<System.ComponentModel.DataObject()> _
Public Class EmployeesBLLWithSprocs
Private _employeesAdapter As EmployeesTableAdapter = Nothing
Protected ReadOnly Property Adapter() As EmployeesTableAdapter
Get
If _employeesAdapter Is Nothing Then
_employeesAdapter = New EmployeesTableAdapter()
End If
Return _employeesAdapter
End Get
End Property
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Select, True)> _
Public Function GetEmployees() As NorthwindWithSprocs.EmployeesDataTable
Return Adapter.GetEmployees()
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Delete, True)> _
Public Function DeleteEmployee(ByVal employeeID As Integer) As Boolean
Dim rowsAffected = Adapter.Delete(employeeID)
'Return true if precisely one row was deleted, otherwise false
Return rowsAffected = 1
End Function
End Class
A EmployeesBLLWithSprocs
propriedade da classe s Adapter
retorna uma instância do NorthwindWithSprocs
DataSet s EmployeesTableAdapter
. Isso é usado pelos métodos e DeleteEmployee
da classe sGetEmployees
. O GetEmployees
método chama o EmployeesTableAdapter
método correspondente GetEmployees
s, que invoca o Employees_Select
procedimento armazenado e preenche seus resultados em um EmployeeDataTable
. O DeleteEmployee
método também chama 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
classe concluída, estamos prontos para trabalhar com os dados dos funcionários por meio de uma página ASP.NET. Abra a JOINs.aspx
página na AdvancedDAL
pasta e arraste um GridView da Caixa de Ferramentas para o Designer, definindo sua ID
propriedade Employees
como . Em seguida, na marca inteligente GridView, associe a grade a um novo controle ObjectDataSource chamado EmployeesDataSource
.
Configure o ObjectDataSource para usar a EmployeesBLLWithSprocs
classe e, nas guias SELECT e DELETE, verifique se os GetEmployees
métodos e DeleteEmployee
estão selecionados nas listas suspensas. Clique em Concluir para concluir a configuração do ObjectDataSource.
Figura 12: Configurar o ObjectDataSource para usar a EmployeesBLLWithSprocs
classe (clique para exibir a imagem em tamanho real)
Figura 13: Fazer com que o ObjectDataSource use os GetEmployees
métodos e DeleteEmployee
(clique para exibir 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
ManagerFirstName
, e ManagerLastName
renomeie as HeaderText
propriedades dos últimos quatro BoundFields como 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 recursos de exclusão verificando a opção Habilitar Exclusão de sua marca inteligente. Em segundo lugar, altere a propriedade objectDataSource do OldValuesParameterFormatString
valor definido pelo assistente ObjectDataSource (original_{0}
) para seu valor padrão ({0}
). Depois de fazer essas alterações, a 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 por meio de um navegador. Como mostra a Figura 14, a página listará cada funcionário e o nome do gerente (supondo que eles tenham um).
Figura 14: o JOIN
no Employees_Select
procedimento armazenado retorna o nome do gerente (clique para exibir 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 tentativa DELETE
de instrução 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: Excluir um funcionário que tenha pedidos correspondentes resulta em uma violação de restrição de chave estrangeira (clique para exibir 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 registros da
Orders
tabela para os funcionários que você deseja excluir ou - Atualize o
Employees_Delete
procedimento armazenado para primeiro excluir os registros relacionados da tabela antes deOrders
excluir oEmployees
registro. Discutimos essa técnica no tutorial Usando procedimentos armazenados existentes para tableAdapters do Conjunto de Dados Tipado .
Eu deixo isso como um exercício para o leitor.
Resumo
Ao trabalhar com bancos de dados relacionais, é comum que as consultas efetuem pull dos 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. Nos tutoriais anteriores, geralmente usamos subconsultas correlacionadas porque o TableAdapter não pode gerar INSERT
automaticamente as instruções , UPDATE
e DELETE
para consultas que envolvem JOIN
s. Embora esses valores possam ser fornecidos manualmente, ao usar instruções SQL ad hoc, todas as personalizações serão substituídas quando o assistente de Configuração do TableAdapter for concluído.
Felizmente, os 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 main usa um JOIN
ao usar procedimentos armazenados. Neste tutorial, vimos como criar um TableAdapter desse tipo. Começamos usando uma JOIN
consulta -less SELECT
para a consulta main tableAdapter para que os procedimentos armazenados de inserção, atualização e exclusão correspondentes fossem criados automaticamente. Com a configuração inicial do TableAdapter concluída, aumentamos o SelectCommand
procedimento armazenado para usar um JOIN
e executar novamente o assistente de Configuração de TableAdapter para atualizar as EmployeesDataTable
colunas s.
Executar novamente o assistente de Configuração do TableAdapter atualizou automaticamente as EmployeesDataTable
colunas para refletir os campos de dados retornados pelo Employees_Select
procedimento armazenado. Como alternativa, poderíamos ter adicionado essas colunas manualmente à DataTable. Exploraremos a adição manual de colunas à DataTable no próximo 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 Hilton Geisenow, David Suru e Teresa Murphy. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.