|
Программирование >> Привязка данных
Извлечение данных Сгенерированный табличный адаптер содержит команды для 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); Это единственное выражение применяется для фильтрации всех методов текущего объекта и возврата только тех из них, которые отвечают следующим критериям:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |