Compartir por


Enlace de datos

LINQ to SQL admite el enlace a controles comunes, como controles de cuadrícula. En concreto, LINQ to SQL define los patrones básicos para enlazar a una cuadrícula de datos y controlar el enlace de detalles maestros, tanto con respecto a la visualización como a la actualización.

Principio subyacente

LINQ to SQL traduce consultas LINQ a SQL para su ejecución en una base de datos. Los resultados son IEnumerable fuertemente tipados. Dado que estos objetos son objetos de Common Language Runtime (CLR) normales, se puede usar el enlace de datos de objetos ordinarios para mostrar los resultados. Por otro lado, las operaciones de cambio (inserciones, actualizaciones y eliminaciones) requieren pasos adicionales.

Operación

El enlace implícito a controles de Windows Forms se realiza mediante la implementación de IListSource. Los orígenes de datos genéricos Table<TEntity> (Table<T> en C# o Table(Of T) en Visual Basic) y genéricos DataQuery se han actualizado para implementar IListSource. Los motores de enlace de datos de la interfaz de usuario (Windows Forms y Windows Presentation Foundation) prueban si su origen de datos implementa IListSource. Por consiguiente, al escribir una modificación directa de una consulta en un origen de datos de un control, se llama implícitamente a la generación de colecciones de LINQ to SQL, como en el ejemplo siguiente:

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

Lo mismo ocurre con 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

Las generaciones de colecciones se implementan de manera genérica mediante Table<TEntity> y DataQuery en GetList.

Implementación de IListSource

LINQ to SQL implementa IListSource en dos ubicaciones:

  • El origen de datos es Table<TEntity>:LINQ to SQL examina la tabla para rellenar una colección DataBindingList que mantiene una referencia en la tabla.

  • El origen de datos es IQueryable<T>. Hay dos escenarios:

    • Si LINQ to SQL encuentra el objeto Table<TEntity> subyacente de IQueryable<T>, el origen permite la edición y la situación es la misma que en el primer punto de la lista.

    • Si LINQ to SQL no encuentra el subyacente Table<TEntity>, el origen no permite la edición (por ejemplo, groupby). LINQ to SQL examina la consulta para rellenar un genérico SortableBindingList, que es un sencillo BindingList<T> que implementa la característica de ordenación para las entidades T para una propiedad determinada.

Colecciones especializadas

Para muchas características descritas anteriormente en este documento, BindingList<T> se ha especializado en algunas clases diferentes. Estas clases son genéricas SortableBindingList y genéricas DataBindingList. Ambas se declaran como internas.

SortableBindingList genérica

Esta clase hereda de BindingList<T>y es una versión clasificable de BindingList<T>. La ordenación es una solución en memoria y nunca se pone en contacto con la propia base de datos. BindingList<T> implementa IBindingList pero no admite la ordenación de forma predeterminada. Sin embargo, BindingList<T> implementa IBindingList con métodos virtuales centrales. Puede invalidar fácilmente estos métodos. La clase SortableBindingList genérica invalida SupportsSortingCore, SortPropertyCore, SortDirectionCore y ApplySortCore. ApplySortCore se llama por ApplySort y ordena la lista de elementos T para una propiedad determinada.

Se produce una excepción si la propiedad no pertenece a T.

Para lograr la ordenación, LINQ to SQL crea una clase genérica SortableBindingList.PropertyComparer que hereda de genérico IComparer.Compare e implementa un comparador predeterminado para un tipo determinado T, un PropertyDescriptory una dirección. Esta clase crea dinámicamente un Comparer de T donde T es el PropertyType del PropertyDescriptor. A continuación, el comparador predeterminado se recupera del genérico estático Comparer. Se obtiene una instancia predeterminada mediante la reflexión.

Generic SortableBindingList es también la clase base para DataBindingList. La clase SortableBindingList genérica proporciona dos métodos virtuales para suspender o reanudar el seguimiento de las operaciones de agregar o quitar elementos. Estos dos métodos se pueden usar para características base como la ordenación, pero realmente se implementarán mediante clases superiores como genéricas DataBindingList.

Clase DataBindingList genérica

Esta clase se hereda de la clase SortableBindingLIst genérica. La clase DataBindingList genérica mantiene una referencia en el elemento Table genérico subyacente de la interfaz genérica IQueryable que se utilizó para el llenado inicial de la colección. Genérico DatabindingList agrega seguimiento para agregar o quitar elementos a la colección reemplazando InsertItem() y RemoveItem(). También implementa la característica de seguimiento de suspensión/reanudación abstracta para que el seguimiento sea condicional. Esta característica permite que la clase DataBindingList genérica se pueda aprovechar del uso polimórfico completo de la característica de seguimiento de las clases primarias.

Enlace a EntitySets

El enlace a EntitySet es un caso especial porque EntitySet ya es una colección que implementa IBindingList. LINQ to SQL agrega compatibilidad con la ordenación y la cancelación (ICancelAddNew). Una EntitySet clase usa una lista interna para almacenar entidades. Esta lista es una colección de bajo nivel basada en una matriz genérica, la clase genérica ItemList .

Agregar una característica de ordenación

Las matrices ofrecen un método de ordenación (Array.Sort()) que se puede usar con un Comparer de T. LINQ to SQL usa la clase genérica SortableBindingList.PropertyComparer descrita anteriormente en este tema para obtener este Comparer para la propiedad y la dirección con la que se va a ordenar. Para llamar a esta característica, se agrega un método ApplySort a la clase ItemList genérica.

En el lado EntitySet, ahora tiene que declarar la compatibilidad con la ordenación:

Cuando use una clase System.Windows.Forms.BindingSource y enlace un tipo EntitySet<TEntity> a la propiedad System.Windows.Forms.BindingSource.DataSource, debe llamar al método EntitySet<TEntity>.GetNewBindingList para actualizar la clase BindingSource.List.

Si usa una clase System.Windows.Forms.BindingSource y establece las propiedades BindingSource.DataMember y BindingSource.DataSource en una clase con una propiedad citada en la propiedad BindingSource.DataMember que expone EntitySet<TEntity>, no tiene que llamar al método EntitySet<TEntity>.GetNewBindingList con el fin de actualizar la clase BindingSource.List, pero pierde capacidad de ordenación.

Almacenamiento en caché

Implementación GetList de consultas de LINQ to SQL. Cuando la clase BindingSource de Windows Forms cumple esta interfaz, llama a GetList() tres veces para una sola conexión. Para solucionar esta situación, LINQ to SQL implementa una caché por instancia para almacenar y siempre devolver la misma colección generada.

Cancelación

IBindingList define un AddNew método que usan los controles para crear un nuevo elemento a partir de una colección enlazada. El DataGridView control muestra esta característica muy bien cuando la última fila visible contiene una estrella en su encabezado. La estrella te muestra que puedes agregar un nuevo elemento.

Además de esta característica, una colección también puede implementar ICancelAddNew. Esta característica permite que los controles cancelen o validen que el nuevo elemento editado se haya validado o no.

ICancelAddNew se implementa en todas las colecciones LINQ to SQL vinculadas a datos (genéricas SortableBindingList y genéricas EntitySet). En ambas implementaciones, el código realiza lo siguiente:

  • Permite insertar y quitar elementos de la colección.

  • No realiza un seguimiento de los cambios siempre que la interfaz de usuario no confirme la edición.

  • No realiza un seguimiento de los cambios siempre que se cancele la edición (CancelNew).

  • Permite el seguimiento de los cambios cuando se confirma la edición (EndNew).

  • Permite que la colección se comporte normalmente si el nuevo elemento no procede de AddNew.

Solución de problemas

En esta sección se describen varios elementos que pueden ayudar a solucionar problemas de las aplicaciones de enlace de datos LINQ to SQL.

  • Debe utilizar propiedades; utilizar solo campos no es suficiente. Windows Forms requiere este uso.

  • De forma predeterminada, los tipos de base de datos image, varbinary y timestamp se asignan a la matriz de bytes. Dado que ToString() no se admite en este escenario, estos objetos no se pueden mostrar.

  • Un miembro de clase asignado a una clave principal tiene un establecedor, pero LINQ to SQL no admite el cambio de identidad de objeto. Por consiguiente, la clave principal/única que se usa en la asignación no se puede actualizar en la base de datos. Un cambio en la cuadrícula produce una excepción al llamar a SubmitChanges.

  • Si una entidad está enlazada en dos cuadrículas independientes (por ejemplo, una principal y otra de detalle), un Delete en la cuadrícula principal no se propaga a la cuadrícula de detalle.

Consulte también