3. Общее представление о привязке данных в Windows Forms

Объект SqlCommand

объекту команды можно передать либо

Как только у вас есть соединение, с которым можно работать, вы создаете объект SqlCommand, Передавая конструктору текст запроса SQL для исполнения и соединение, которое следует использовать. Объекту команды можно передать либо операторы SQL, либо имя сохраняемой процедуры. В реальных уровнях данных я рекомендую инкапсулировать доступ к данным на уровне базы данных в сохраняемых процедурах, и в своем уровне данных лишь потреблять эти процедуры. Это развяжет код вашего приложения от специфической схемы ваших таблиц, благодаря чему небольшие изменения в нижележащей схеме не будут влиять на код приложения. Сохраняемые процедуры позволят вам также использовать встроенные механизмы безопасности SQL Server для предотвращения прямого доступа к таблицам, и сохраняемые процедуры обеспечивают иногда лучшую производительность, чем динамические операторы SQL, исполняемые из кода в листинге Г. З. Во многих примерах кода в этой книге я нарушал эту рекомендацию, чтобы можно было использовать базу данных Northwind с минимальными модификациями, и чтобы вы ясно могли видеть, что именно извлекается запросами При выполнении текстовых запросов SQL Вы должны точно специфицировать столбцы, которые должны возвращаться вашим запросом. Спецификация * для столбцов может возвратить гораздо больше информации, чем вам нужно, влияя на производительность приложения. При этом объекту команды требуется проделать больше работы для определения точной схемы результирующего набора, который будет возвращен запросом Создает объект SqlDataAdapter, Являющийся мостом между нейтральным в смысле источника набором данных и специфическим источником данных, с которым он будет работать. В данном слу-чае я конструирую его, передавая объект команды.

События набора данных и адаптера данных

однако иногда вам нужно быть

До сих пор я обсуждал только программирование с методами и свойствами наборов данных и адаптеров данных, а также обработку исключений, когда что-то идет не так. Однако иногда вам нужно быть поближе к тому, что происходит в процессе обработки. Имеется ряд событий из классов DataSet, DataTable И SqlDataAdapter, К Которым вы можете подключиться, чтобы ваш код мог получать уведомления при изменениях в данных. Класс DataSet Имеет два события: MergeFailed, Которое запускается, если вы выполняете операцию Merge и имеет место конфликт первичного ключа между целевой и исходной таблицами. Initialized, Которое запускается, когда DataSet Завершит инициализацию содержащихся в нем объектов и состояния. Наиболее полезные события имеет DataTable; Они описаны в таблице Г.4.

События ColumnChanging/ColumnChanged Передают вашему обработчику события параметр типа DataColumnChangeEventArgs. Этот параметр содержит несколько значений, полезных для контроля над обновлением столбца. Свойство для чтения/записи с именем ProposedValue Содержит значение, которое будет иметь изменяемый столбец после того, как обработчик события завершится. Вы можете инспектировать это значение в своем обработчике ColumnChanging, И в комбинации со свойствами row и Column Параметра аргументов события верифицировать его и принять решение об изменении этого значения. Если предполагаемое значение не отвечает вашим ограничениям верификации, у вас есть две возможности. Во-первых, вы можете изменить его на некоторое приемлемое значение, присвоив другое значение соответствующего типа свойству ProposedValue Параметра аргументов события. Если вы делаете это, любое значение, которое вы присвоите свойству, станет тем, что будет действительно установлено для столбца, когда изменение будет сделано. Поэтому вы могли бы также изменить предполагаемое значение на первоначальное, которое можно извлечь через свойства Row И Column, Как показано здесь, чтобы фактически предотвратить изменение:

Класс XPathNodelterator

исходно он позиционируется непосредственно перед

Класс XPathNodelterator Следует модели других итераторов в. NET Framework. Исходно он позиционируется непосредственно перед элементом коллекции, которую он содержит. Вы последовательно вызываете метод MoveNext, Обычно в цикле While, И проверяете возвращаемое булево значение. Если оно равно True, То был еще один узел, куда можно было перейти, и итератор будет позиционирован на этом узле. Если возвращается False, То больше нет узлов, которые можно итерировать. Следующий код демонстрирует процесс загрузки документа, выполнения запроса и итерации по результатам. Свойство Current Итератора возвращает ссылку на XPathNavigator, Позиционированный на текущем узле, который вы можете затем использовать для доступа к содержимому узла, либо для выполнения навигации или дальнейших запросов, относящихся к этому узлу. Этот пример обращается к свойству Value Текущего узла, которое в случае элемента или атрибута является просто его текстовым содержанием. Имеется также свойство Name, Которое возвращает имя узла. Сложность возвращаемых результатов зависит от сложности запроса, который вы выдаете. Для чего-то простого вроде показанного запроса, который просто возвращает набор элементов, содержащих текстовые узлы со значениями, которые вас интересуют, код довольно прямолинеен. Однако результаты XPath-запросов могли бы возвращать любой тип узла, поэтому вам часто требуется некоторая условная логика, которая проверяет тип каждого узла по мере их итерации и модифицирует свои действия в зависимости от типа узла. Тип узла экспонируется свойством NodeType Объекта XPathNavigator, Которое возвращает перечисление типа XPathNodeType.

Конструирование адаптера данных для извлечения данных

чтобы при помощи адаптера данных

До сих пор, при конструировании адаптера данных для извлечения данных, мы устанавливали его свойство SelectCommand На экземпляр SqlCommand, Который инкапсулирует текстовый запрос SQL или сохраняемую процедуру, возвращающую строки, используемые для первоначального заполнения таблицы. Чтобы при помощи адаптера данных производить обновления, вам необходимо также предусмотреть объекты команд для свойств InsertCommand, DeleteCommand И UpdateCommand, В зависимости от того, какие обновления вы собираетесь производить. Как вы и могли бы ожидать, InsertCommand Будет использоваться для любых строк, помеченных как Added, DeleteCommand — для любых строк, помеченных как Deleted, И UpdateCommand — для любых строк, помеченных как Modified. Если набор данных не содержит строк с каким-то состоянием, то нет необходимости предоставлять соответствующую команду, поскольку она использована не будет. Но вообще говоря, вам нужно предусмотреть все три, так как нельзя заранее быть уверенным, что на момент выполнения обновления у вас не будет строк в модифицированном, добавленном или удаленном состоянии. Точно так же, как и команда выбора, используемая для заполнения набора данных, команды, используемые для обновления базы данных набором данных, могут применять либо текстовые запросы SQL, либо сохраняемые процедуры, передавая столбцы обновляемых строк в качестве параметров. Для простых приложений, которым требуется непосредственно работать в каждый момент времени с единственной таблицей в базе данных, вы можете использовать параметризованные текстовые запросы SQL. Для более масштабных приложений вы, возможно, захотите использовать сохраняемые процедуры.

Обработка событий элементов управления

все элементы управления наследуют большой

Как уже упоминалось, основная часть периода жизни приложения Windows Forms определяется обработкой событий элементов управления. Все элементы управления наследуют большой набор событий от базового класса Control. Эти события соответствуют общим сообщениям Windows, которые могут передаваться операционной системой любому окну. Сюда относятся такие события, как щелчки мыши, события клавиатуры, события таймера Windows и события перерисовки. Многие из этих событий имеют один и тот же тип делегата — EventHandler, Представленный выше. Если вам нужно побольше узнать о делегатах и событиях, я порекомендовал бы вам обратиться к какой-нибудь хорошей книге по общему программированию. NET. Некоторые события определяются с использованием более специализированных типов делегатов, которые включают специализированные аргументы события. Эти аргументы несут дополнительную информацию о событии, которая может использоваться подписчиками для обработки события в своих обработчиках. Например, класс Control Определяет события для мыши, среди которых назовем хотя бы MouseUp, MouseDown, MouseMove И MouseWheel. Эти события объявляются как принадлежащие к типу MouseEventHandler. Тип делегата MouseEventHandler В качестве второго параметра в своей сигнатуре принимает объект MouseEventArgs. Класс MouseEventArgs Определяет несколько свойств, которые могут быть использованы для условной обработки в зависимости от специфики события. В число этих свойств входят позиции X и Y в экранных координатах, где произошло событие мыши, какая кнопка была нажата и сколько раз, если событие было щелчком мыши, и на сколько щелчков было прокручено колесико мыши, если событие было вызвано движением колесика.