Vincular objetos como fontes de dados em aplicativos do .NET Framework usando o Visual Studio
Observação
Os conjuntos de dados e as classes relacionadas são tecnologias herdadas do .NET Framework do início dos anos 2000 que permitem que os aplicativos trabalhem com dados na memória enquanto os aplicativos estão desconectados do banco de dados. As tecnologias são bastante úteis em aplicativos que permitem que os usuários modifiquem dados e persistam as alterações no banco de dados. Embora os conjuntos de dados tenham se mostrado uma tecnologia muito bem-sucedida, é recomendado que os novos aplicativos .NET usem o Entity Framework Core. O Entity Framework proporciona uma forma mais natural de trabalhar com dados tabulares como modelos de objeto e conta com uma interface de programação mais simples.
O Visual Studio fornece ferramentas de tempo de design para trabalhar com objetos personalizados como a fonte de dados em seu aplicativo. Quando você deseja armazenar dados de um banco de dados em um objeto que você associa a controles de interface do usuário, a abordagem recomendada é usar o Entity Framework para gerar a classe ou classes. O Entity Framework gera automaticamente todo o código de controle de alterações clichê, o que significa que todas as alterações nos objetos locais são mantidas automaticamente no banco de dados quando você chama AcceptChanges no objeto DbSet. Para obter mais informações, confira Documentação do Entity Framework.
Dica
As abordagens de associação de objeto neste artigo só devem ser consideradas se o aplicativo já for baseado em conjuntos de dados. Você também poderá usar essas abordagens se já estiver familiarizado com conjuntos de dados e os dados que você for processar forem tabulares e não muito complexos nem muito grandes. Para obter um exemplo ainda mais simples, envolvendo o carregamento de dados diretamente em objetos usando um DataReader e atualizando manualmente a interface do usuário sem vinculação de dados, confira Criar um aplicativo de dados simples usando ADO.NET.
Requisitos de objeto
O único requisito para que objetos personalizados funcionem com as ferramentas de design de dados no Visual Studio é que o objeto precise de pelo menos uma propriedade pública.
Geralmente, objetos personalizados não exigem interfaces, construtores ou atributos específicos para atuar como uma fonte de dados para um aplicativo. No entanto, se você quiser arrastar o objeto da janela Fontes de Dados para uma superfície de design para criar um controle associado a dados e, se o objeto implementar a interface ITypedList ou IListSource, o objeto precisará ter um construtor padrão. Caso contrário, o Visual Studio não poderá instanciar o objeto de fonte de dados e ele exibirá um erro quando você arrastar o item para a superfície de design.
Exemplos de uso de objetos personalizados como fontes de dados
Embora existam inúmeras maneiras de implementar a lógica do aplicativo ao trabalhar com objetos como uma fonte de dados, para bancos de dados SQL, há algumas operações padrão que podem ser simplificadas usando os objetos TableAdapter gerados pelo Visual Studio. Esta página explica como implementar esses processos padrão usando TableAdapters. Ela não se destina a ser um guia para criar seus objetos personalizados. Por exemplo, você normalmente executará as seguintes operações padrão, independentemente da implementação específica de seus objetos ou da lógica do aplicativo:
Carregar dados em objetos (normalmente de um banco de dados).
Criar uma coleção tipada de objetos.
Adicionar objetos a uma coleção e remover objetos dela.
Exibir os dados do objeto para os usuários em um formulário.
Alterar/editar os dados em um objeto.
Salvar dados de objetos de volta para o banco de dados.
Carregar dados em objetos
Para este exemplo, você carrega dados em seus objetos usando TableAdapters. Por padrão, TableAdapters são criados com dois tipos de métodos que buscam dados de um banco de dados e preenchem tabelas de dados.
O método
TableAdapter.Fill
preenche uma tabela de dados existente com os dados retornados.O método
TableAdapter.GetData
retorna uma nova tabela de dados preenchida com os dados.
A maneira mais fácil de carregar seus objetos personalizados com os dados é chamar o método TableAdapter.GetData
, percorrer a coleção de linhas na tabela de dados retornada e preencher cada objeto com os valores em cada linha. Você pode criar um método GetData
que retorna uma tabela de dados populada para qualquer consulta adicionada a um TableAdapter.
Observação
O Visual Studio nomeia as consultas de TableAdapter Fill
e GetData
por padrão, mas você pode alterar esses nomes para qualquer nome de método válido.
O seguinte exemplo mostra como percorrer as linhas em uma tabela de dados e preencher um objeto com os dados:
private void LoadCustomers()
{
NorthwindDataSet.CustomersDataTable customerData =
customersTableAdapter1.GetTop5Customers();
foreach (NorthwindDataSet.CustomersRow customerRow in customerData)
{
Customer currentCustomer = new Customer();
currentCustomer.CustomerID = customerRow.CustomerID;
currentCustomer.CompanyName = customerRow.CompanyName;
if (customerRow.IsAddressNull() == false)
{
currentCustomer.Address = customerRow.Address;
}
if (customerRow.IsCityNull() == false)
{
currentCustomer.City = customerRow.City;
}
if (customerRow.IsContactNameNull() == false)
{
currentCustomer.ContactName = customerRow.ContactName;
}
if (customerRow.IsContactTitleNull() == false)
{
currentCustomer.ContactTitle = customerRow.ContactTitle;
}
if (customerRow.IsCountryNull() == false)
{
currentCustomer.Country = customerRow.Country;
}
if (customerRow.IsFaxNull() == false)
{
currentCustomer.Fax = customerRow.Fax;
}
if (customerRow.IsPhoneNull() == false)
{
currentCustomer.Phone = customerRow.Phone;
}
if (customerRow.IsPostalCodeNull() == false)
{
currentCustomer.PostalCode = customerRow.PostalCode;
}
if (customerRow.IsRegionNull() == false)
{
currentCustomer.Region = customerRow.Region;
}
LoadOrders(currentCustomer);
customerBindingSource.Add(currentCustomer);
}
}
Criar uma coleção tipada de objetos
Você pode criar classes de coleção para seus objetos ou usar as coleções tipadas fornecidas automaticamente pelo componente BindingSource.
Ao criar uma classe de coleção personalizada para objetos, sugerimos que você herde de BindingList<T>. Essa classe genérica fornece funcionalidade para administrar sua coleção, bem como a capacidade de gerar eventos que enviam notificações para a infraestrutura de associação de dados no Windows Forms.
A coleção gerada automaticamente em BindingSource usa um BindingList<T> para a respectiva coleção tipada. Se o aplicativo não exigir funcionalidade adicional, você poderá manter sua coleção dentro do BindingSource. Para obter mais informações, confira a propriedade List da classe BindingSource.
Observação
Se sua coleção exigir funcionalidade não fornecida pela implementação base do BindingList<T>, você deverá criar uma coleção personalizada para que possa adicionar à classe conforme necessário.
O seguinte código mostra como criar a classe para uma coleção fortemente tipada de objetos Order
:
/// <summary>
/// A collection of Orders
/// </summary>
public class Orders: System.ComponentModel.BindingList<Order>
{
// Add any additional functionality required by your collection.
}
Adicionar objetos a uma coleção
Você adiciona objetos a uma coleção chamando o método Add
da classe de coleção personalizada ou do BindingSource.
Observação
O método Add
é fornecido automaticamente para sua coleção personalizada quando você herda de BindingList<T>.
O seguinte código mostra como adicionar objetos à coleção tipada em um BindingSource:
O seguinte código mostra como adicionar objetos a uma coleção tipada que herda de BindingList<T>:
Observação
Neste exemplo, a coleção Orders
é uma propriedade de um objeto Customer
.
Remover objetos de uma coleção
Você remove objetos de uma coleção chamando o método Remove
ou RemoveAt
de sua classe de coleção personalizada ou de BindingSource.
Observação
Os métodos Remove
e RemoveAt
são fornecidos automaticamente para sua coleção personalizada quando você herda de BindingList<T>.
O seguinte código mostra como localizar e remover objetos da coleção tipada em um BindingSource com o método RemoveAt:
int customerIndex = customerBindingSource.Find("CustomerID", "ALFKI");
customerBindingSource.RemoveAt(customerIndex);
Exibir dados de objeto para usuários
Para exibir os dados em objetos para os usuários, crie uma fonte de dados de objeto usando o assistente de Configuração da Fonte de Dados e arraste todo o objeto ou as propriedades individuais para o formulário da janela Fontes de Dados.
Modificar os dados em objetos
Para editar dados em objetos personalizados associados a controles do Windows Forms, basta editar os dados no controle associado (ou diretamente nas propriedades do objeto). A arquitetura de associação de dados atualiza os dados no objeto.
Se o aplicativo exigir o acompanhamento das alterações e a reversão das alterações propostas em seus valores originais, você precisará implementar essa funcionalidade em seu modelo de objeto. Para obter exemplos de como as tabelas de dados acompanham as alterações propostas, confira DataRowState, HasChanges e GetChanges.
Salvar dados em objetos de volta para o banco de dados
Salve os dados de volta no banco de dados passando os valores do objeto para os métodos DBDirect do TableAdapter.
O Visual Studio cria métodos DBDirect que podem ser executados diretamente no banco de dados. Esses métodos não exigem objetos DataSet ou DataTable.
Métodos DBDirect TableAdapter | Descrição |
---|---|
TableAdapter.Insert |
Adiciona novos registros a um banco de dados, permitindo que você passe valores de coluna individuais como parâmetros de método. |
TableAdapter.Update |
Atualiza registros existentes em um banco de dados. O método Update usa valores de coluna originais e novos como parâmetros de método. Os valores originais são usados para localizar o registro original e os novos valores são usados para atualizar esse registro. O método TableAdapter.Update também é usado para reconciliar alterações em um conjunto de dados de volta ao banco de dados, usando uma matriz DataSet, DataTable, DataRow de DataRows como parâmetros de método. |
TableAdapter.Delete |
Exclui registros existentes do banco de dados com base nos valores de coluna originais passados como parâmetros de método. |
Para salvar dados de uma coleção de objetos, faça loop pela coleção de objetos (por exemplo, usando um loop for-next). Envie os valores de cada objeto para o banco de dados usando os métodos DBDirect do TableAdapter.
O seguinte exemplo mostra como usar o método DBDirect TableAdapter.Insert
para adicionar um novo cliente diretamente ao banco de dados:
private void AddNewCustomers(Customer currentCustomer)
{
customersTableAdapter.Insert(
currentCustomer.CustomerID,
currentCustomer.CompanyName,
currentCustomer.ContactName,
currentCustomer.ContactTitle,
currentCustomer.Address,
currentCustomer.City,
currentCustomer.Region,
currentCustomer.PostalCode,
currentCustomer.Country,
currentCustomer.Phone,
currentCustomer.Fax);
}