Программирование >>  Привязка данных 

1 ... 5 6 7 [ 8 ] 9 10


Извлечение данных

Сгенерированный табличный адаптер содержит команды для SELECT, INSERT, UPDATE и DELETE. Излишне говорить, что они могут (и, возможно, должны) вызывать хранимые процедуры вместо прямого применения операторов SQL. Однако сгенерированный мастером код пока так и делает. Visual Studio .NET добавляет следующий код в файл .Designer:

private System.Data.SqlClient.SqlCommand m DeleteCommand; private System.Data.SqlClient.SqlCommand m InsertCommand; private System.Data.SqlClient.SqlCommand m UpdateCommand; private System.Data.SqlClient.SqlDataAdapter m adapter;

Объекты определены для всех команд SQL за исключением SELECT, а также SqlDataAdapter. Ниже в файле, в методе InitializeComponent() , мастер генерирует код создания каждой из этих команд, наряду с адаптером данных.

В предыдущих версиях Visual Studio .NET команды, сгенерированные для вставки и обновления, также включали конструкцию SELECT - это было сделано для повторной синхронизации данных с сервером на случай, если какие-то поля внутри базы данных были вычисляемыми (такие как identity и computed).

Сгенерированный мастером код работает, однако, он не оптимален. В промышленных системах весь сгенерированный код SQL должен быть заменен вызовами хранимых процедур. Если операторы INSERT и UPDATE не должны повторно синхронизировать данные, удаление излишних конструкций SQL повысит производительность приложения.

Обновление источника данных

До сих пор наши приложения только извлекали данные из базы. В этом разделе мы поговорим о том, как сохранять в базе измененные данные. Если следовать шагам, описанным в предыдущем разделе, мы получим приложение, которое содержит все необходимое, что должно быть в простейшем приложении. Для включения кнопки Save (Сохранить) потребуется внести лишь одно изменение в сгенерированную панель инструментов и написать обработчик событий, который обновит базу данных.

В среде IDE выберем кнопку Save (Сохранить) в навигационном элементе управления и изменим ее свойство Enabled на true. Затем, выполнив двойной щелчок на этой кнопке, сгенерируем обработчик события. Внутри него сохраним изменения данных, выполненные на экране, в базе данных:

private void dataNavigatorSaveItem Click(object sender, EventArgs e)

employeesTableAdapter.Update(employeesDataset.Employees);

Поскольку Visual Studio выполнит за нас всю тяжелую работу, все, что мы должны сделать - использовать метод Update табличного адаптера; в этом примере используется перегрузка, принимающая в качестве параметра DataTable.

Другие общие требования

Общим требованием при отображении данных является показ контекстного меню для данной записи. Его можно реализовать разными способами. Пример, приведенный в этом разделе, сосредоточен на одном подходе, который может упростить необходимый код, особенно если контекст отображения - DataGrid, когда отображается DataSet с некоторыми отношениями. Проблема здесь состоит в том, что контекстное меню зависит от выбранной записи, а эта запись может быть частью любого источника DataTable в пределах DataSet.



Поскольку функциональность контекстного меню с высокой вероятностью по природе своей имеет общее назначение, здесь реализация использует базовый класс ( ContextDataRow), поддерживающий код построения меню, и каждый класс строки данных (записи), поддерживающий всплывающее меню, наследуется от этого базового класса.

Когда пользователь щелкает правой кнопкой мыши на любой части строки в DataGrid, выполняется проверка, унаследована ли она от ContextDataRow, и если да, то может быть вызван метод PopupMenu(). Это можно было бы реализовать через интерфейс, однако в данном случае базовый класс обеспечивает более простое решение.

Настоящий пример демонстрирует, как генерировать классы DataRow и DataTable, которые можно использовать для обеспечения доступа, безопасного в отношении типов, к данным, почти таким же образом, как и в предыдущем примере с XSD. Однако на этот раз мы пишем код самостоятельно, чтобы показать, как в данном контексте использовать настраиваемые атрибуты и рефлексию.

На рис. 32.24 показана иерархия классов для этого примера.


Рис. 32.24. Иерархия классов для примера с контекстным меню

Ниже приведен код этого примера.

using System;

using System.Windows.Forms; using System.Data; using System.Data.SqlClient; using System.Reflection; public class ContextDataRow : DataRow

public ContextDataRow(DataRowBuilder builder) : base(builder)

public void PopupMenu(System.Windows.Forms.Control parent, int x, int y)

Использовать рефлексию, чтобы получить список команд для вспхвающего меню

MemberInfo[] members = this.GetType().FindMembers (MemberTypes.Method, BindingFlags.Public BindingFlags.Instance , new System.Reflection.MemberFilter(Filter), null);



if (members.Length > 0)

Создать контекстное меню ContextMenu menu = new ContextMenu();

Теперь пройти по членам и сгенерировать всплывающее меню. Обратите внимание на приведение к MethodInfo в цикле foreach foreach (MethodInfo meth in members)

Получить заголовок операции из ContextMenuAttribute

ContextMenuAttribute[] ctx = (ContextMenuAttribute[])

meth.GetCustomAttributes(typeof(ContextMenuAttribute), true); MenuCommand callback = new MenuCommand(this, meth); MenuItem item = new MenuItem(ctx[0].Caption,

new EventHandler(callback.Execute)); item.DefaultItem = ctx[0].Default;

menu.MenuItems.Add(item);

System.Drawing.Point pt = new System.Drawing.Point(x,y); menu.Show(parent, pt);

private bool Filter(MemberInfo member, object criteria)

bool bInclude = false; Привести MemberInfo к MethodInfo MethodInfo meth = member as MethodInfo; if (meth != null)

if (meth.ReturnType == typeof(void))

ParameterInfo[] parms = meth.GetParameters(); if (parms.Length == 0)

Проверить, есть ли в методе ContextMenuAttribute у метода object[] atts = meth.GetCustomAttributes

(typeof(ContextMenuAttribute), true); bInclude = (atts.Length == 1);

return bInclude;

Класс ContextDataRow унаследован от DataRow и содержит две функции-члена: PopupMenu() и Filter() . Метод PopupMenu() использует рефлексию для поиска методов, соответствующих определенной сигнатуре, и отображает пользователю всплывающее меню этих опций. Метод Filter() применяется как делегат в PopupMenu() при перечислении методов. Он просто возвращает true, если функция-член соответствует соглашениям вызова:

MemberInfo[] members = this.GetType().FindMembers(MemberTypes.Method, BindingFlags.Public BindingFlags.Instance, new System.Reflection.MemberFilter(Filter),

null);

Это единственное выражение применяется для фильтрации всех методов текущего объекта и возврата только тех из них, которые отвечают следующим критериям:



1 ... 5 6 7 [ 8 ] 9 10

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика