- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
Вы должны согласиться с тем, что для работы с адаптерами данных может потребоваться ввод довольно большого объема программного кода, а также создание всех четырех объектов команд и соответствующей строки соединения (или DbConnection-объекта). Чтобы упростить дело, в .NET 2.0 каждый из поставщиков данных ADO.NET предлагает тип построителя команд. Используя этот тип, вы можете автоматически получать объекты команд, содержащие правильные типы команд Insert, Delete и Update на базе исходного оператора Select.
Тип SqlCommandBuilder автоматически генерирует значения для свойств InsertCommand, UpdateCommand и DeleteCommand объекта SqlDataAdapter на основе значения SelectCommand. Очевидным преимуществом здесь является то, что исключается необходимость строить все типы SqlCommand и SqlParameter вручную.
Здесь возникает вопрос о том, как построитель команд может строить указанные объекты SQL-команд "на лету". Оказывается, все дело в метаданных. В среде выполнения, когда вы вызываете метод Update() адаптера данных, соответствующий построитель команд читает данные структуры базы данных для автоматического генерирования объектов соответствующих команд вставки, удаления и обновления данных.
Рассмотрите следующий пример, в котором строка из DataSet удаляется с помощью автоматически сгенерированных SQL-операторов. Кроме того, для каждого объекта команды соответствующая команда выводится на печать.
static void Main(string[] args) {
DataSet theCarsInventory = new DataSet();
// Создание соединения.
SqlConnection cn = new SqlConnection("server=(local);User ID=sa;Pwd=;database=Cars");
// Автоматическое генерирование команд Insert, Update и Delete
// на основе существующей команды Select.
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Inventory", cn);
SqlCommandBuilder invBuilder = new SqlCommandBuilder(da);
// Заполнение DataSet.
da.Fill(theCarsInventory, "Inventory");
PrintDataSet(theCarsInventory);
// Удаление строки на основании пользовательского ввода
// и обновление базы данных.
try {
Console.Write("Номер строки для удаления: ");
int rowToDelete = int.Parse(Console.ReadLine());
theCarsInventory.Tables["Inventory"].Rows[rowToDelete].Delete();
da.Update(theCarsInventory, "Inventory");
} catch (Exception e) {
Console.WriteLine(e.Message);
}
// Новое заполнение и печать таблицы Inventory.
theCarsInventory = new DataSet();
da.Fill(theCarsInventory, "Inventory");
PrintDataSet(theCarsInventory);
}
В этим фрагменте программного кода обратите внимание на то, что здесь объект построителя команд (в данном случае это SqlCommandBuilder) передается объекту адаптера данных в виде параметра конструктора и больше никак не используется. Как бы странно это ни выглядело, но это все, что вам требуется сделать (в минимальных условиях). Указанный тип в фоновом режиме сконфигурирует для адаптера данных остальные объекты команд.
Хотя идея получить кое-что, не предлагая ничего взамен, понравится многим, важно понять, что построители команд имеют некоторые (весьма важные) ограничения. В частности, построитель команд может автоматически генерировать SQL-команды для адаптера данных только в том случае, когда выполнены все следующие условия.
• Соответствующая команда Select взаимодействует только с одной таблицей (так что, например, соединения таблиц не допускаются).
• Для этой единственной таблицы назначен первичный ключ.
• Столбцы, представляющие первичный ключ, присутствуют в данном SQL-операторе Select.
Так или иначе, рис. 22.19 демонстрирует, что указанная строка удаляется из физической базы данных (при анализе программного кода этого примера следует различать значение CarID и порядковый номер строки).
Рис. 22.19. Использование автоматически генерируемых команд SQL
Исходный код. Проект MySqlCommandBuilder размещен в подкаталоге, соответствующем главе 22.
Объекты DataSet с множеством таблиц и объекты DataRelation
До этого момента во всех примерах данной главы объекты DataSet содержали по одному объекту DataTable. Однако вся мощь несвязного уровня ADO.NET проявляется тогда, когда DataSet содержит множество объектов DataTable. В этом случае вы можете добавить в коллекцию DataRelation объекта DataSet любое число объектов DataRelation, чтобы указать взаимные связи таблиц. Используя эти объекты, клиентское звено приложения сможет осуществлять переходы между таблицами без пересылки данных по сети.
Для демонстрации возможностей использования объектов DataRelation создайте новый проект Windows Forms с именем MultitabledDataSet. Графический интерфейс пользователя этого приложения достаточно прост. На рис. 22.20 вы можете видеть три элемента управления DataGridView, содержащие данные из таблиц Inventory, Orders и Customers базы данных Cars. Кроме того, там присутствует одна кнопка, с помощью которой информация обо всех изменениях направляется в хранилище данных.
Рис. 22.20. Просмотр связанных объектов DataTable
Чтобы упростить ситуацию, тип MainForm будет использовать построители команд (по одному для каждой таблицы) для автоматического генерирования SQL-команд каждого из трех объектов SqlDataAdapter. Вот исходная модификация соответствующего экземпляра типа Form:
public partial class MainForm: Form {
// Объект DataSet для формы.
private DataSet carsDS = new DataSet("CarsDataSet");
// Применение построителей команд для упрощения
// настройки адаптеров данных.
private SqlCommandBuilder sqlCBInventory;
private SqlCommandBuilder sqlCBCustomers;
private SqlCommandBuilder sqlCBOrders;
// Адаптеры данных (для каждой из таблиц).
private SqlDataAdapter intTableAdapter;
private SqlDataAdapter custTableAdapter;
private SqlDataAdapter ordersTableAdapter;
// Объект соединения для формы.
private SqlConnection cn = new SqlConnection("server= (local);uid=sa;pwd=;database=Cars");
…
}
Конструктор формы выполняет основную работу по созданию членов-переменных для данных и заполнению DataSet. Обратите также внимание на вызов приватной вспомогательной функции ВuildTableRelationship().
public MainForm() {
InitializeComponent();
// Создание адаптеров.
invTableAdapter = new SqlDataAdapter("Select * from Inventory", cn);
custTableAdapter = new SqlDataAdapter("Select * from Customers", cn);
ordersTableAdapter = new SqlDataAdapter("Select * from Orders", cn);
// Автогенерирование команд.
sqlCBInventory = new SqlCommandBuilder(invTableAdapter);
sqlCBOrders = new SqlCommandBuilder(ordersTableAdapter);
sqlCBCustomers = new SqlCommandBuilder(custTableAdapter);
// Добавление таблиц в DataSet.
invTableAdapter.Fill(carsDS, " Inventory");
custTableAdapter.Fill(carsDS, "Customers");
ordersTableAdapter.Fill(carsDS, "Orders");
// Создание отношений между таблицами.
BuildTableRalationship();
// Привязка к элементам управления.
dataGridViewInventory.DataSource = carsDS.Tables["Inventory"];
dataGridViewCustomers.DataSourсе = carsDS.Tables["Customers"];
dataGridViewOrders.DataSource = carsDS.Tables["Orders"];
}
Вспомогательная функция BuildTableRelationship() делает в точности то, что от нее ожидается. Напомним, что база данных Cars имеет ряд отношений "родитель-потомок", что учитывается в следующем фрагменте программного кода:
private void BuildTableRelationship() {
// Создание объекта отношения CustomerOrder.
DataRelation dr = new DataRelation("CustomerOrder", carsDS.Tables["Customers"].Columns["CustID"], carsDS.Tables["Orders"].Columns["CustID"]);
carsDS.Relations.Add(dr);
// Создание объекта отношения InventoryOrder.
dr = new DataRelation("InventoryOrder", carsDS.Tables["Inventory"].Columns["CarID"], carsDS.Tables["Orders"].Columns["CarID"]);
carsDS.Relations.Add(dr);
}
Теперь, когда объект DataSet заполнен и отсоединен от источника данных, вы можете работать со всеми таблицами локально. Можно вставлять, обновлять или удалять значения любого из трех DataGridView. Как только вы будете готовы отправить измененные данные обратно в хранилище данных для обработки, щелкните на кнопке обновления формы. Программный код соответствующего обработчика события Click должен быть вам понятен.
private void btnOpdate_Cliсk(object sender, EventArgs e) {
try {
invTableAdapter.Update(carsDS, "Inventory");
custTableAdapter.Update(carsDS, "Customers");
ordersTableAdapter.Update(carsDS, "Orders");
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
После щелчка на кнопке обновления вы обнаружите, что каждая из таблиц в базе данных Cars соответствующим образом изменена.
Навигационные возможности для связанных таблиц
Чтобы продемонстрировать возможности DataRelation при программной реализации доступа к данным связанных таблиц, добавьте в форму новый тип Button и соответствующий ему TextBox. В результате конечный пользователь должен получить возможность ввести идентификационный номер заказчика и увидеть информацию о заказе соответствующего клиента, которая выводится в простом окне сообщения. Обработчик события Click этой кнопки реализован так.