Привязка данных
LINQ to SQL поддерживает привязку к общим элементам управления, таким как элементы управления сеткой. В частности, LINQ to SQL определяет основные шаблоны привязки к сетке данных и обработке привязки основных сведений, как в отношении отображения, так и обновления.
Основной принцип
LINQ to SQL преобразует запросы LINQ в SQL для выполнения в базе данных. Результаты являются строго типизированной коллекцией IEnumerable
. Поскольку эти объекты являются обычными объектами среды CLR, то для отображения результатов можно использовать привязку к данным обычных объектов. С другой стороны, для выполнения операций изменения (вставки, обновления и удаления) требуются дополнительные действия.
Операция
Неявная привязка к элементам управления Windows Forms осуществляется посредством реализации интерфейса IListSource. Универсальные Table<TEntity> источники данных (Table<T>
в C# или Table(Of T)
Visual Basic) и универсальные DataQuery
были обновлены для реализации IListSource. Оба обработчика привязки данных пользовательского интерфейса (Windows Forms и Windows Presentation Foundation) проверяют, реализует ли их источник данных интерфейс IListSource. Поэтому написание прямого влияния запроса на источник данных элемента управления неявно вызывает создание коллекции LINQ to SQL, как показано в следующем примере:
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
То же происходит в 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
Создание коллекции реализуется с помощью универсального класса Table<TEntity> и универсального класса DataQuery
в методе GetList.
Реализация интерфейса "IListSource"
LINQ to SQL реализуется IListSource в двух расположениях:
Источник данных — это Table<TEntity>: LINQ to SQL просматривает таблицу, чтобы заполнить
DataBindingList
коллекцию, которая сохраняет ссылку на таблицу.Источником данных является интерфейс IQueryable<T>. Имеется два сценария.
Если LINQ to SQL находит базовые Table<TEntity> данные из источника IQueryable<T>, источник позволяет выпуску и ситуация совпадает с первой точкой маркера.
Если LINQ to SQL не удается найти базовый Table<TEntity>объект, источник не разрешает выпуск (например,
groupby
). LINQ to SQL просматривает запрос для заполнения универсального типа, который является простымSortableBindingList
BindingList<T>, который реализует функцию сортировки для сущностей T для заданного свойства.
Специализированные коллекции
Для реализации многих функций, описанных ранее в этом документе, класс BindingList<T> был специализирован для получения некоторых других классов. Этими классами являются универсальный класс SortableBindingList
и универсальный класс DataBindingList
. Оба класса объявляются как внутренние.
Универсальный класс «SortableBindingList»
Этот класс, который является производным от класса BindingList<T>, представляет собой сортируемую версию класса BindingList<T>. Сортировка выполняется в памяти и никогда не обращается к самой базе данных. Объект BindingList<T> реализует интерфейс IBindingList, но не поддерживает сортировку по умолчанию. BindingList<T> Однако реализуется IBindingList с помощью методов виртуального ядра. Эти методы легко переопределить. Общий объект SortableBindingList
переопределяет методы SupportsSortingCore, SortPropertyCore, SortDirectionCore и ApplySortCore. Метод ApplySortCore
вызывается методом ApplySort и сортирует список из T элементов по данному свойству.
Если свойство не принадлежит "T", возникает исключение.
Чтобы выполнить сортировку, LINQ to SQL создает универсальный SortableBindingList.PropertyComparer
класс, наследующий от универсального IComparer.Compare и реализующий средство сравнения по умолчанию для заданного типа T, a PropertyDescriptor
и направления. Этот класс динамически создает класс Comparer
для "T", где "T" является типом PropertyType
дескриптора PropertyDescriptor
. Затем из статического универсального класса Comparer
извлекается компаратор по умолчанию. Экземпляр по умолчанию получается с помощью отражения.
Универсальный класс SortableBindingList
также является базовым классом для DataBindingList
. Универсальный класс SortableBindingList
предлагает два виртуальных метода для приостановки или возобновления отслеживания добавления и удаления элементов. Эти два метода могут использоваться для базовых функций, таких как сортировка, но в действительности они реализуются классами верхнего уровня, например универсальным классом DataBindingList
.
Универсальный класс «DataBindingList»
Этот класс наследует от класса SortableBindingLIst
. Универсальный класс DataBindingList
сохраняет ссылку на базовый универсальный класс Table
универсального интерфейса IQueryable
, используемого для первоначального заполнения коллекции. Универсальный класс DatabindingList
обеспечивает отслеживание для добавления и удаления элементов в коллекции посредством переопределения методов InsertItem
() и RemoveItem
(). Он также реализует абстрактную возможность приостановки/возобновления, чтобы сделать отслеживание условным. Эта возможность позволяет универсальному классу DataBindingList
воспользоваться всеми преимуществами полиморфного использования возможности отслеживания родительских классов.
Привязка к коллекциям «EntitySet»
Привязка к классу EntitySet
является особым случаем, поскольку класс EntitySet
уже является коллекцией, реализующей интерфейс IBindingList. LINQ to SQL добавляет поддержку сортировки и отмены (ICancelAddNew). Для хранения сущностей класс EntitySet
использует внутренний список. Этот список представляет собой коллекцию нижнего уровня, основанную на универсальном массиве, универсальном классе ItemList
.
Добавление возможности сортировки
Массивы предлагают метод сортировки (Array.Sort()
), который можно использовать с Comparer
T. LINQ to SQL использует универсальный SortableBindingList.PropertyComparer
класс, описанный ранее в этом разделе, для получения этого Comparer
свойства и направления сортировки. Для вызова этой функции к универсальному интерфейсу ApplySort
добавляется метод ItemList
.
На стороне класса EntitySet
необходимо объявить поддержку сортировки.
SupportsSorting возвращает
true
.ApplySort вызывает метод
entities.ApplySort()
, а затем методOnListChanged()
.Свойства SortDirection и SortProperty предоставляют текущее определение сортировки, которое хранится в локальных членах.
При использовании System.Windows.Forms.BindingSource и привязке EntitySet TEntity к System.Windows.Forms.BindingSource.DataSource необходимо вызвать EntitySet<<TEntity>>. GetNewBindingList для обновления BindingSource.List.
Если вы используете System.Windows.Forms.BindingSource и задаете свойство BindingSource.DataMember и задаете BindingSource.DataSource классу с именем свойства BindingSource.DataMember, который предоставляет EntitySet<TEntity, вам не нужно вызывать EntitySet<TEntity>>. GetNewBindingList для обновления BindingSource.List, но вы теряете возможность сортировки.
Кэширование
Реализуйте GetListзапросы LINQ to SQL. Если класс Windows Forms BindingSource встречает этот интерфейс, он три раза вызывает метод GetList() для одного подключения. Чтобы обойти эту ситуацию, LINQ to SQL реализует кэш для каждого экземпляра для хранения и всегда возвращает ту же созданную коллекцию.
Отмена
Интерфейс IBindingList определяет метод AddNew, который используется элементами управления для создания нового элемента из связанной коллекции. Элемент управления DataGridView
прекрасно демонстрирует эту возможность, когда последняя отображаемая строка содержит звездочку в заголовке. Звездочка означает, что можно добавить новый элемент.
В дополнение к этой возможности коллекция может также реализовать интерфейс ICancelAddNew. Это позволяет элементам выполнять отмену и проверять, был ли проверен новый измененный элемент.
ICancelAddNew реализован во всех коллекциях входящих данных LINQ to SQL (универсальные SortableBindingList
и универсальные EntitySet
). В обоих реализациях код выполняет перечисленные ниже задачи.
Позволяет вставлять, а затем удалять элементы в коллекции.
Не отслеживает изменений, если пользовательский интерфейс не зафиксировал версию.
Не отслеживает изменений, если версия отменена (CancelNew).
Разрешает отслеживать фиксацию версий (EndNew).
Позволяет коллекции осуществлять нормальное поведение, если новый элемент добавлен не с помощью метода AddNew.
Устранение неполадок
В этом разделе приводятся несколько элементов, которые помогут устранить неполадки приложений привязки данных LINQ to SQL.
Необходимо использовать свойства - использования одних полей недостаточно. Это требование обусловлено Windows Forms.
По умолчанию ,
image
иvarbinary
timestamp
типы баз данных сопоставляют с массивом байтов. В данном сценарии не поддерживается методToString()
, поэтому эти объекты невозможно отобразить.Член класса, сопоставленный с первичным ключом, имеет метод задания, но LINQ to SQL не поддерживает изменение удостоверения объекта. Поэтому первичный/уникальный ключ, используемый в сопоставлении, не может быть обновлен в базе данных. Изменение в сетке вызывает исключение при вызове SubmitChanges.
Если сущность привязана в двух отдельных сетках (например, в основной сетке и в сетке подробных сведений), операция
Delete
в основной сетке не распространяется на сетку подробных сведений.