Compartilhar via


Associação de dados

O LINQ to SQL dá suporte à associação a controles comuns, como controles de grade. Especificamente, o LINQ to SQL define os padrões básicos para associar a uma grade de dados e lidar com a associação mestre-detalhe, tanto no que diz respeito à exibição quanto à atualização.

Princípio subjacente

LINQ to SQL converte consultas LINQ para SQL para execução em um banco de dados. Os resultados são IEnumerable fortemente tipados. Como esses objetos são objetos CLR (Common Language Runtime), a associação de dados de objeto comum pode ser usada para exibir os resultados. Por outro lado, as operações de alteração (inserções, atualizações e exclusões) exigem etapas adicionais.

Operação

A associação implícita aos controles do Windows Forms é realizada implementando IListSource. Fontes de dados genéricas Table<TEntity> (Table<T> em C# ou Table(Of T) no Visual Basic) e genéricas DataQuery foram atualizadas para implementar IListSource. Os mecanismos de associação de dados da interface do usuário (Windows Forms e Windows Presentation Foundation) testam se a fonte de dados deles implementa IListSource. Portanto, escrever uma atribuição direta de uma consulta a uma fonte de dados de um controle invoca implicitamente a geração de coleção pelo LINQ to SQL, como no exemplo a seguir:

DataGrid dataGrid1 = new DataGrid();
DataGrid dataGrid2 = new DataGrid();
DataGrid dataGrid3 = new DataGrid();

var custQuery =
    from cust in db.Customers
    select cust;
dataGrid1.DataSource = custQuery;
dataGrid2.DataSource = custQuery;
dataGrid2.DataMember = "Orders";

BindingSource bs = new BindingSource();
bs.DataSource = custQuery;
dataGrid3.DataSource = bs;
Dim dataGrid1 As New DataGrid()
Dim dataGrid2 As New DataGrid()
Dim dataGrid3 As New DataGrid()

Dim custQuery = _
    From cust In db.Customers _
    Select cust

dataGrid1.DataSource = custQuery
dataGrid2.DataSource = custQuery
dataGrid2.DataMember = "Orders"

Dim bs = _
    New BindingSource()
bs.DataSource = custQuery
dataGrid3.DataSource = bs

O mesmo ocorre com o Windows Presentation Foundation:

ListView listView1 = new ListView();
var custQuery2 =
    from cust in db.Customers
    select cust;

ListViewItem ItemsSource = new ListViewItem();
ItemsSource = (ListViewItem)custQuery2;
Dim listView1 As New ListView()
Dim custQuery2 = _
From cust In db.Customers _
Select cust

Dim ItemsSource As New ListViewItem
ItemsSource = custQuery2

As gerações de coleção são implementadas por Table<TEntity> genérico e por DataQuery genérico em GetList.

Implementação de IListSource

O LINQ to SQL implementa IListSource em dois locais:

  • A fonte de dados é um Table<TEntity>: o LINQ to SQL navega a tabela para preencher uma coleção DataBindingList que mantém uma referência na tabela.

  • A fonte de dados é um IQueryable<T>. Há dois cenários:

    • Se LINQ to SQL encontrar o elemento subjacente Table<TEntity> proveniente de IQueryable<T>, a origem permite edição e a situação será a mesma mencionada no primeiro ponto.

    • Se LINQ to SQL não puder encontrar o subjacente Table<TEntity>, a origem não permitirá a edição (por exemplo, groupby). LINQ to SQL analisa a consulta para preencher um genérico SortableBindingList, que é uma estrutura simples BindingList<T> que implementa o recurso de classificação para entidades do tipo T, de acordo com uma propriedade específica.

Coleções especializadas

Para muitos recursos descritos anteriormente neste documento, BindingList<T> foi adaptado para diferentes classes específicas. Essas classes são genéricas SortableBindingList e genéricas DataBindingList. Ambos são declarados como internos.

SortableBindingList genérica

Essa classe herda de BindingList<T>, e é uma versão classificável de BindingList<T>. A classificação é uma solução na memória e nunca entra em contato com o próprio banco de dados. BindingList<T> implementa IBindingList, mas não oferece suporte à classificação por padrão. No entanto, BindingList<T> implementa IBindingList com métodos core virtuais. Você pode substituir facilmente esses métodos. Genérico SortableBindingList substitui SupportsSortingCore, SortPropertyCore, SortDirectionCore e ApplySortCore. ApplySortCore é chamado por ApplySort e classifica a lista de itens T para uma determinada propriedade.

Uma exceção será gerada se a propriedade não pertencer a T.

Para obter a classificação, o LINQ to SQL cria uma classe genérica SortableBindingList.PropertyComparer que herda de genérico IComparer.Compare e implementa um comparador padrão para um determinado tipo T, um PropertyDescriptore uma direção. Essa classe cria dinamicamente um Comparer de T, onde T é o PropertyType do PropertyDescriptor. Em seguida, o comparador padrão é recuperado do genérico Comparerestático. Uma instância padrão é obtida usando reflexão.

Genérico SortableBindingList também é a classe base para DataBindingList. A SortableBindingList genérica oferece dois métodos virtuais para suspender ou retomar o controle de itens adicionar/remover. Esses dois métodos podem ser usados para recursos básicos, como classificação, mas serão realmente implementados por classes superiores, como genéricos DataBindingList.

DataBindingList genérica

Esta classe herda de SortableBindingLIstgenérica. A DataBindingList genérica mantém uma referência na Table genérica subjacente da IQueryable genérica usada para o preenchimento inicial da coleção. A DatabindingList genérica adiciona o controle para adicionar/remover itens à coleção substituindo InsertItem() e RemoveItem(). Também implementa o recurso abstrato suspender/retomar para tornar o controle condicional. Esse recurso faz a DataBindingList genérica tirar proveito de todo o uso polimorfo do recurso de rastreamento das classes pai.

Vinculação a EntitySets

A associação ao EntitySet é um caso especial porque EntitySet já é uma coleção que implementa IBindingList. O LINQ to SQL adiciona suporte de classificação e cancelamento (ICancelAddNew). Uma EntitySet classe usa uma lista interna para armazenar entidades. Essa lista é uma coleção de baixo nível baseada em uma matriz genérica, a classe genérica ItemList .

Adicionando um recurso de classificação

Matrizes oferecem um método de classificação (Array.Sort()) que pode ser usado com um Comparer T. LINQ to SQL usa a classe genérica SortableBindingList.PropertyComparer descrita anteriormente neste tópico para obter isso Comparer para a propriedade e a direção a ser classificada. Um ApplySort método é adicionado ao genérico ItemList para chamar esse recurso.

No lado EntitySet, agora você precisa declarar suporte à ordenação:

Quando você usa um System.Windows.Forms.BindingSource e associa um EntitySet<TEntity> ao System.Windows.Forms.BindingSource.DataSource, você deve chamar EntitySet<TEntity>. GetNewBindingList para atualizar BindingSource.List.

Se você usar um System.Windows.Forms.BindingSource e definir a propriedade BindingSource.DataMember e configurar o BindingSource.DataSource para uma classe que tenha uma propriedade nomeada em BindingSource.DataMember que exponha o EntitySet<TEntity>, você não precisará chamar EntitySet<TEntity>.GetNewBindingList para atualizar o BindingSource.List, mas perderá a capacidade de ordenação.

Armazenamento em cache

Implementar consultas LINQ to SQL GetList. Quando a classe BindingSource do Windows Forms atende a essa interface, ela chama GetList() três vezes para uma única conexão. Para contornar essa situação, o LINQ to SQL implementa um cache por instância para armazenar e sempre retornar a mesma coleção gerada.

Cancelamento

IBindingList define um AddNew método usado pelos controles para criar um novo item de uma coleção associada. O DataGridView controle mostra esse recurso muito bem quando a última linha visível contém uma estrela em seu cabeçalho. A estrela mostra que você pode adicionar um novo item.

Além desse recurso, uma coleção também pode implementar ICancelAddNew. Esse recurso permite que os controles cancelem ou validem se o novo item editado foi validado ou não.

ICancelAddNew é implementado em todas as coleções genéricas LINQ to SQL vinculadas a dados (SortableBindingList e EntitySet). Em ambas as implementações, o código executa da seguinte maneira:

  • Permite que os itens sejam inseridos e removidos da coleção.

  • Não controla as alterações desde que a interface do usuário não confirme a edição.

  • Não rastreia as alterações desde que a edição seja cancelada (CancelNew).

  • Permite controlar quando a edição é confirmada (EndNew).

  • Permite que a coleção se comporte normalmente se o novo item não for proveniente de AddNew.

Resolução de problemas

Esta seção destaca vários itens que podem ajudar a solucionar problemas de seus aplicativos de vinculação de dados LINQ to SQL.

  • Você deve usar propriedades; usar apenas campos não é suficiente. Os Windows Forms exigem esse uso.

  • Por padrão, os tipos de banco de dados image, varbinary, e timestamp são mapeados para um array de bytes. Como ToString() não há suporte neste cenário, esses objetos não podem ser exibidos.

  • Um membro de classe mapeado para uma chave primária tem um setter, mas LINQ to SQL não dá suporte à alteração de identidade de objeto. Portanto, a chave primária/exclusiva usada no mapeamento não pode ser atualizada no banco de dados. Uma alteração na grade provoca uma exceção quando você chama SubmitChanges.

  • Se uma entidade estiver associada em duas grades separadas (por exemplo, um mestre e outro detalhe), uma Delete na grade mestra não será propagada para a grade de detalhes.

Consulte também