Как использовать TableAdapterManager и связанные таблицы данных в сочетании с запросами SQL

У меня есть вопрос о том, как правильно работать со связанными таблицами данных и как правильно их реализовать в исходной базе данных бэкэнда.

ситуация следующая:

  1. У меня есть база данных SQL (SQL Server), которая является основным источником данных. Здесь таблицы могут иметь отношение друг к другу через внешние ключи.

  2. эту базу данных 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
Другие вопросы по тегам