Я выберу типичного родителя / ребенка или мастера / детали клиентов: заказы. Если вы использовали сервер доступа или sql БД с отношением, определенным в БД, и вы создали новый набор данных, открыли его в конструкторе, щелкнули правой кнопкой мыши поверхность и выбрали «Добавить TableAdapter», поместили SELECT * FROM customers
и повторили процесс ( если щелкнуть правой кнопкой мыши ..) для заказов вы получите DataTable и TableAdapter клиентов, DataTable и TableAdapter заказов и DataRelation между двумя связывающими (скажем) orders.customerid с Customers.id
Сохранить набор , затем взгляните в окно источников данных и разверните каждый узел .
Существует узел верхнего уровня Customer и узел верхнего уровня Orders, и вы также заметите узел Orders, который является дочерним по отношению к Customer
Перетащите узел Customers из источников данных на новую форму. Появятся: сетевая информация о клиентах, набор данных, клиентская таблица адаптации, источник связи с клиентами и связующий клиент. Удалить навигатор (для наглядности прямо сейчас). Вы заметите, что представление данных о клиентах привязано к источнику связи клиентов, а источник связи связан с таблицей клиентов набора данных
Перетащите Заказы верхнего уровня из окна источников данных в форму. Вы заметите, что отображаются данные о датах заказов, источник заказов, таблица заказов и навигация. Удалить навигатор. Обратите внимание, что, как и прежде ,riddidgridvew привязывается к источнику ordersbindings, а источник ordersbindigsource связывается с Orders в наборе данных. Я думаю, это то, что вы сделали
Удалите все, что появилось, когда вы перетаскивали ордера (dgv / bs / ta для ордеров). Не удаляйте набор данных - он все еще используется связями с именами клиентов *
Теперь go обратно в окно источников данных, и на этот раз перетащите дочерние заказы, которые находятся ниже узла «Клиенты». Появляются те же компоненты (ordersdgv / bs / ta / nav). Удалить навигацию. На этот раз посмотрите на источник данных ordersbindingsource и свойства datamember. Вы заметите, что в отличие от прошлого раза, этот источник связывания заказов привязан не непосредственно к набору данных, а к источнику связи, в частности, к устройству данных, названному в честь того же имени, что и отношение данных в наборе
В этой настройке, когда текущая родительская строка изменяется в customerbindingsource, ordersbindingsource будет видеть только отфильтрованный набор строк заказов - фильтр пропускает только те строки, у которых orders.customerid равен текущему идентификатору в th Customersbindingsource
Note; важно, чтобы данные Orders были в наборе данных. Ничто здесь не может автоматически загружать данные базы данных. Если вы заполняете клиентов, но не заполняете данные заказов, то никакие данные не будут отображаться в заказах, независимо от того, как они связаны.
В упрощенном c подходе используются запросы по умолчанию в таблицах-адаптерах (* 1024). *) и загружает ВСЕ базы данных в набор данных. Это будет работать в демонстрационных целях, но вы действительно не хотите делать это в производственной программе.
Go вернуться к набору данных и изменить запросы по умолчанию в таблицах адаптеров, чтобы они были SELECT * FROM customers WHERE id = @id
и соответствовали заказам. Затем добавьте ДРУГОЙ запрос к ТА клиента (щелкните его правой кнопкой мыши и выберите добавить запрос):
SELECT * FROM customers WHERE lastname = @lastname
Назовите этот запрос FillByLastName (мастер попросит вас назвать его и предложить FillBy. Не принимать значение по умолчанию). ; дайте ему разумное имя)). Это может загрузить 10 клиентов.
Теперь go к табличному адаптеру ORDERS и добавьте к нему еще один запрос:
SELECT * FROM orders WHERE customerid = @customerid
Назовите его FillByCustomerId. Это можно использовать, как только мы загрузим 10 клиентов, чтобы получить заказы для этих 10 клиентов:
'fill the form dataset with customers named smith:
Me.someDataSet.Clear()
customersTableAdapter.FillByLastName(someDataSet, "Smith") 'it will fill the Customers table with Smiths
ordersTableAdapter.ClearBeforeFill = false 'turn this off or every call to fill will remove existing order from the datatable
For Each cro as CustomersRow in someDataSet.Customers 'for all our smiths
ordersTableAdapter.FillByCUstomerId(someDataSet, cro.Id) 'fill orders for customer with that id
Next cro
Так что теперь у вас есть 10 клиентов, и, возможно, более 50 заказов - у вас нет всего БД в вашем наборе данных, просто интересные данные. Привязка данных через отношение данных, предоставляемое в bindingsource клиентов, будет показывать только связанные строки. Щелкните по различным строкам в сетевом представлении данных клиентов и обратите внимание, что заказы, показанные в сетевом представлении ordersdatagrid, изменяются и отображают только соответствующие строки
. Предполагается, что вы добавляете столько запросов к табличному адаптеру, сколько вам нужно. Вместо того, чтобы зацикливать клиентов и заполнять их заказы по каждому идентификатору клиента, вы можете написать запрос, который возвращает их все в одно нажатие, в табличном адаптере ORDERS:
SELECT orders.*
FROM
orders INNER JOIN customers on orders.customerid = customers.id
WHERE
customers.lastname = @lastName
Запрос выбирает только данные из заказов, но присоединяется к клиентам и ищет их по фамилии, поэтому мы должны назвать это FillByCustomerLastName
Наш код может выглядеть следующим образом:
'fill the form dataset with customers named smith:
Me.someDataSet.Clear()
customersTableAdapter.FillByLastName(someDataSet, "Smith") 'it will fill the Customers table with Smiths
ordersTableAdapter.FillByCustomerLastName(someDataSet, "Smith") 'fill orders for all customers with a last name of smith
Лошади для выбранных вами курсов. Я склонен выбирать первый подход и l oop, потому что он более гибкий, но там, где важна прямая производительность, может быть быстрее использовать шаблон, подобный второму