Как использовать TableAdapterManager и связанные таблицы данных в сочетании с запросами SQL
У меня есть вопрос о том, как правильно работать со связанными таблицами данных и как правильно их реализовать в исходной базе данных бэкэнда.
ситуация следующая:
У меня есть база данных SQL (SQL Server), которая является основным источником данных. Здесь таблицы могут иметь отношение друг к другу через внешние ключи.
эту базу данных SQL я использую, чтобы заполнить таблицы данных с помощью запросов SQL. Полученные таблицы данных я использую, чтобы визуализировать информацию в формуле
var query = new SqlCommand(_sqlquery, connection); var sqlAdapter = new SqlDataAdapter(query); sqlAdapter.Fill(dataTable);
...
Здесь я использую sql запросы, чтобы получить необходимую информацию в моих таблицах данных, например:
ВЫБЕРИТЕ * ИЗ [ЗАКАЗАТЬ] ВНУТРЕННЕЕ ПРИСОЕДИНЯЙТЕСЬ к клиенту ПО [заказ].
Пока все хорошо, визуализация в сетке данных работает хорошо.
НО проблемы возникают при попытке сохранить изменения визуализированных данных в сетке данных обратно в исходную базу данных sql.
Я много искал в интернете, и решение, похоже, заключается в использовании TableAdapterManager. Проблема в том, что я не очень понимаю, как связать мой код, который я уже имею, чтобы визуализировать данные с помощью TableAdapterManager, который может актуализировать данные в базе данных sql.
2 ответа
Позвольте мне добавить еще один ответ - это будет легко объяснить шаг за шагом. Я буду редактировать / добавлять больше деталей, когда это необходимо.
1. Начните с создания нового набора данных и добавьте необходимые вам таблицы данных. Добавьте новый табличный адаптер - он также создаст данные на основе вашего запроса или запроса по умолчанию. У Tableadapter может быть много запросов - они используются для заполнения таблицы данных из базы данных.
Начните с простого запроса:
select * from customers
или же
select *, computedField1 = 'abc', computedField2 = 123
from customers
where 1=0
Этот "первый" запрос - "поддельный" ("где 1=0" говорит о том, что он никогда не будет использоваться) и декларативный, из одной таблицы, без параметров. Обычно вы никогда не получаете ВСЕ данные без параметров или соединений. Этот запрос "позволяет" конструктору создавать структуру и обновлять операторы, распознавать первичные ключи.
Затем добавьте еще один запрос:
FillById
select *
from customers
where custId = @custId
FillByName
select *
from customers
where custname like (@ss + '%')
FillByRecent
select cc.*
from customers cc
inner join orders oo on cc.custId = oo.custId // get only customers with orders
where oo.orderdate > @dtFrom
Вы позвоните им в коде:
taCustomer.FillByName(ds.customers, "AAA"); // all started from "AAA"
Сделать то же самое для заказов
2. Создать отношения
Нажмите на серое пространство перед столбцом custId в Customer - он выберет столбец. Перетащите выделенный и сбросьте на custId в Заказах
3. Добавить форму
После компиляции ваш набор данных будет добавлен в окно "Источники данных". Выберите форму, перетащите клиента из окна "Источники данных" на форму - она создаст григ и добавит в форму компоненты: набор данных, источник привязки, табличный адаптер.
Добавить заказы тоже.
Посмотрите на свойства "источник данных" и "дата-столбец" в сетках и источники привязки:
- bsCustomer будет ссылаться на DS - клиента
- bsOrders будет ссылаться на клиента - customer_orders_relation
4. Загрузка / обновление
в form_load()
вызов
taOrders.FillBySomething(ds.orders, ...)
taCustomer.FillByAnotherSomething(ds.customers, ...);
под кнопкой Сохранить
taOrders.Update(ds.orders); // will update only modified content
taCustomer.Update(ds.customers);
Вы используете присоединиться. Это объединяет результат из 2 таблиц, что хорошо для просмотра, но сбивает с толку для обновления (но это все еще возможно). Ваш результат будет следующим. Что вы ожидаете, если пользователь сделает такую модификацию:
ord1 cust1 --> cust1a
ord2 cust1 --> cust1b
ord3 cust2
ord4 cust2
обычно, если нужны обновления, создают 2 таблицы dtOrders и dtCustomers и устанавливают отношения между ними в C# (мне нравится использовать конструктор: добавить набор данных, добавить tableAdapters для заказов и клиентов, перетащить customerId из одной таблицы в другую, чтобы установить отношение). Оставьте на форме набор данных, табличные адаптеры, bindingSources и настройте orderDatasource, чтобы получить данные из customerDatasource->yourRelation. получить данные для каждой таблицы.
Заметка. Использование набора данных и табличных адаптеров более предпочтительно для приложений winform. Для веб-сайтов обычно используются более легкие конструкции, позволяющие избежать восстанавливающих объектов по каждому запросу.
customerTableAdapter.Fill(ds.dtCustomers);
ordersTableAdapter.Fill(ds.dtOrders);
Затем вы можете отобразить 2 сетки (мастер-детали) или одну сетку с использованием отношения. В ваших таблицах данных у вас не будет дублированных клиентов, обновления не будут сбивать с толку.
TableAdapterManager может использоваться, если вам нужно обновить таблицы в одной транзакции. Если это не важно, вы можете делать обновления без TableAdapterManager.
иначе вы можете использовать адаптер с одной таблицей для соединения и создавать свои собственные состояния обновлений столько, сколько вам нужно:
ta.updateOrderMethod1(row1) // Update orders set ... where ordId = @ordId
ta.updateOrderMethod2(row1) // spUpdateOrder(ordId = @ordId)
ta.updateCustomer(row1) // Update customer set ... where customerId = @customerId
ta.updateCustomerNameOnly(row1) // Update customer set customerName=@customerName where customerId = @customerId