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 umSortableBindingList
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 DataBindingList
gené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 DataBindingList
genérica.
DataBindingList genérica
Esta classe herda de SortableBindingLIst
gené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:
SupportsSorting retorna
true
.ApplySort chama
entities.ApplySort()
e, em seguida,OnListChanged()
.As propriedades SortDirection e SortProperty expõem a definição de classificação atual, que é armazenada em membros locais.
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
etimestamp
mapeiam para matriz de bytes. ComoToString()
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.