Compartilhar via


Associação de dados

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 a associação a uma grade de dados e para a manipulação da associação aos detalhes mestre, tanto em relação à exibição como à 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) comuns, a vinculação de dados de objetos comuns 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

Implicitamente, a associação aos controles do Windows Forms é realizada por meio da implementação de 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 (interface do usuário) (Windows Forms e Windows Presentation Foundation) testam se a fonte de dados deles implementaIListSource. Portanto, escrever uma simulação direta de uma consulta para uma fonte de dados de um controle chama implicitamente a geração de coleção do 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

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 o LINQ to SQL localizar o Table<TEntity> subjacente do IQueryable<T>, a fonte permitirá a edição e a situação será a mesma que no primeiro ponto de marcador.

    • Se LINQ to SQL não conseguir localizar o subjacenteTable<TEntity>, a origem não permitirá a edição (por exemplo, groupby). LINQ to SQL procura a consulta para preencher um SortableBindingList genérico, que é um BindingList<T> simples que implementa a função de classificação para entidades T para uma determinada propriedade.

Coleções especializadas

Para muitos recursos descritos anteriormente neste documento, BindingList<T> foi especializado para algumas classes diferentes. Essas classes são SortableBindingList genérica e DataBindingListgenérica. As duas são declaradas como internas.

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, por padrão, não dá suporte à classificação. No entanto, BindingList<T> implementa IBindingList com métodos core virtuais. Você pode substituir esses métodos facilmente. SortableBindingList genérica substitui SupportsSortingCore, SortPropertyCore, SortDirectionCore e ApplySortCore. ApplySortCore é chamada por ApplySort e classifica a lista de itens de 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 a genérica IComparer.Compare e implementa um comparador padrão para um determinado tipo T, um PropertyDescriptor e uma direção. Essa classe cria dinamicamente um Comparer de T onde T é PropertyType de PropertyDescriptor. Em seguida, o comparador padrão é recuperado do Comparer estático genérico. Uma instância padrão é obtida usando reflexão.

A SortableBindingList genérica 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 base como classificação, mas serão realmente implementados por classes superiores, como DataBindingListgenérica.

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.

Associando a EntitySets

A associação a EntitySet é um caso especial porque EntitySet já é uma coleção que implementa IBindingList. LINQ to SQL adiciona suporte de classificação e cancelamento (ICancelAddNew). Uma classe EntitySet 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 método ApplySort é adicionado ao ItemList genérico para chamar esse recurso.

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

Quando você usa um System.Windows.Forms.BindingSource e associa um EntitySet<TEntity> a 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 definir BindingSource.DataSource a uma classe que tem uma propriedade nomeada no BindingSource.DataMember que expõe o EntitySet<TEntity>, você não precisará chamar EntitySet<TEntity>.GetNewBindingList para atualizar BindingSource.List, mas você perde o recurso de classificação.

Cache

Implementar consultas LINQ to SQL GetList. Quando a classe BindingSource do Windows Forms encontra 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 retorna a mesma coleção gerada.

Cancelamento

O IBindingList define um método AddNew que é usado pelos controles para criar um novo item de uma coleção associada. O controle DataGridView 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 de LINQ to SQL de dados (genéricas SortableBindingList e genéricasEntitySet). Em ambas as implementações, o código executa da seguinte maneira:

  • Permite que 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 controla 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.

Solução de problemas

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

  • Você deve usar propriedades; usar somente campos não é suficiente. O Windows Forms requer esse uso.

  • Por padrão, os tipos de banco de dados image, varbinary e timestamp mapeiam para matriz de bytes. Como ToString() não é suportado nesse cenário, esses objetos não podem ser exibidos.

  • Um membro da classe mapeado para uma chave primária tem um setter, mas LINQ to SQL não dá suporte à alteração de identidade do objeto. Portanto, a chave primária/exclusiva que é 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, uma mestra e outra de detalhes), Delete na grade mestra não será propagado para a grade de detalhes.

Confira também