Как вы фильтруете заполнение TableAdapter на основе двух таблиц?

StackOverflow https://stackoverflow.com/questions/410148

Вопрос

Я использую VS2008 C # Express и базу данных Northwind в приложении Windows Form.

Я использовал перетаскивание, чтобы настроить привязку основных сведений (я использовал Orders и Order Details) для двух datagridviews.На данный момент все работает так, как ожидалось.Чтобы не возвращать каждую строку в таблице, я хочу отфильтровать таблицу Заказов на основе фильтра для таблицы Заказов, а также по полю в таблице Сведений о заказах.В мастере настройки TableAdapter я использовал конструктор запросов, чтобы добавить новый FillByMyFilter, который создал следующий запрос:

ВЫБЕРИТЕ Заказы.[Идентификатор заказа], Заказы.[Идентификатор клиента], Заказы.[Идентификатор сотрудника], Заказы.[Название отгрузки], Заказы.[Адрес отгрузки], заказы.[Город отгрузки], Заказы.[Регион отгрузки], Заказы.[Почтовый индекс отгрузки], заказы.[Страна отгрузки], заказы.[Отправитель через], заказы.[Дата заказа], заказы.[Требуемая дата], Заказы.[Дата отгрузки], Заказы.Перевозка ИЗ ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ заказов [Детали заказа] В заказах.[Идентификатор заказа] = [Детали заказа].[Идентификатор заказа] ГДЕ (Заказы.[Название отгрузки] КАК N'A%') И ([Детали заказа].Количество < 20)

Я получил это, добавив обе таблицы, но не установил ни одно из полей в таблице Сведений о заказе, чтобы возвращать только те столбцы, которые были использованы в исходном запросе на заполнение.На данный момент я только пытаюсь отфильтровать набор данных в главной таблице и не возвращать другое количество столбцов.Дочерние строки сведений о заказе по-прежнему должны работать как нефильтрованный результирующий набор по умолчанию.

Теперь о проблеме:Когда я нажимаю кнопку Выполнить запрос, он работает нормально.Я получаю 53 строки из приведенного выше запроса, а не 1078, используя заливку по умолчанию, созданную дизайнером.Он возвращает те же столбцы, что и исходный запрос на заполнение.Однако, когда я пытаюсь запустить приложение, я получаю следующую ошибку ограничения:

"Не удалось включить ограничения.Одна или несколько строк содержат значения, нарушающие ненулевые, уникальные или внешние ключевые ограничения ".

Что я делаю не так?

Обновить:Я думаю, что я получаю ошибку ограничения из-за ВНУТРЕННЕГО СОЕДИНЕНИЯ, созданного Мастером.Если я отредактирую запрос, чтобы использовать ЛЕВОЕ СОЕДИНЕНИЕ, то Мастер изменит его обратно на ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Мой вопрос по-прежнему заключается в том, как фильтровать записи в родительской таблице (Orders) на основе критериев как из Родительской, так и из дочерней таблицы.Мой следующий тест - попытаться использовать сохраненную процедуру, но я хотел бы знать, используя только пользовательский метод TableAdapter FillBy.

С уважением,

Отлаживать

Это было полезно?

Решение 3

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

1) Щелкните правой кнопкой мыши родительскую таблицу в xsd designer, чтобы добавить или настроить запрос.2) Нажимайте кнопку "Далее" в Мастере, пока не увидите кнопку "Конструктор запросов".Нажмите кнопку Query Builder, чтобы перейти в режим Query Builder.3) Щелкните правой кнопкой мыши и добавьте дочернюю таблицу на панели дизайна.У вас должны быть обе таблицы и ограничение по умолчанию, которое их соединяет.4) Щелкните столбец в дочерней таблице, который вы хотите отфильтровать (этот флажок будет снят позже), чтобы добавить его в панель критериев, чтобы вы могли отфильтровать его.5) Добавьте фильтр для Родительского и Дочернего столбцов.В этом примере я отфильтровал название отгрузки КАК "A%" и Количество заказа < 20.

Обратите внимание, что на этом этапе вы можете протестировать свой запрос, нажав кнопку Выполнить запрос.Используя Northwind DB для SQL 2008 compact edition, я получаю 53 возвращенные строки.Если бы вы сохранили его на этом этапе, он потерпел бы неудачу во время выполнения из-за дублирующихся первичных ключей в результирующем наборе.Таким образом, следующие несколько шагов помогут избавиться от них.

6) На панели критериев снимите флажок с дочернего столбца таблицы, который вы добавили ранее.Фильтр останется, и тот же столбец теперь также будет снят с флажка на панели дизайна.Если вы запустите запрос, у вас по-прежнему будет 53 строки, но без дочернего столбца таблицы.7) Щелкните правой кнопкой мыши на панели дизайна и добавьте "Сгруппировать по".На данный момент, когда вы выполняете этот запрос, у вас не должно быть дубликатов в идентификаторе заказа.Я получил ровно 29 возвращенных строк.8) Нажмите "ОК", а затем кнопку "Далее", пока не сохраните свой новый запрос FillBy.9) Измените свой исходный код, чтобы использовать ваш новый FillBy.

Когда я запустил приложение, я получил отфильтрованную родительскую таблицу с теми же 29 строками, которые возвращала кнопка Выполнить запрос.Дочерняя таблица работала как ожидалось и содержала по крайней мере одну дочернюю строку, которая содержала < 20.

Для реального приложения, я думаю, было бы лучше использовать сохраненный proc или LINQ.Но эта проблема заставила меня почесать в затылке, и поэтому я "привел ее в порядок" просто потому, что это был вызов (по крайней мере, для меня).

Другие советы

В этой статье содержится несколько рекомендаций по устранению неполадок, позволяющих точно определить строку, вызывающую проблему:

DataSet hell - "Не удалось включить ограничения.Одна или несколько строк содержат значения ...."

Если вы посмотрите в Orders.Designer.cs (предполагаю, поскольку я работаю в VB), вы, вероятно, увидите уникальное ограничение, определенное для Orders (для первичного ключа).

Я подозреваю, что проблема в том, что когда вы запускаете свой запрос, вы получаете один или несколько отдельных заказов, у которых > 1 OrderDetails.Количество> 20....so, этот Порядок будет возвращен дважды в вашем результирующем наборе, нарушая первичный ключ.

Попробуй:ВЫБЕРИТЕ * из заказов, где [Название отгрузки] ПОХОЖЕ на '%whatever% И введите OrderID (выберите OrderID из OrderDetails, где Количество < 20)

Вероятно, это очень неэффективный способ сделать это, в oracle вы бы использовали EXISTS() вместо IN(), но я не знаю эквивалента sql server.

Надеюсь, вы получили ответ на этот вопрос, но если нет, подумайте об этом.

В вашем наборе данных, если таблицы данных Order и OrderDetail имеют связь между собой, то это работает в некотором роде как ограничение FK.Таким образом, в дочерней таблице (OrderDetail) не может быть записей, у которых нет соответствующей родительской записи (Order).Итак, что может происходить, когда вы обновляете таблицу данных Order с помощью запроса, о котором вы упомянули выше, в таблице OrderDetail все еще остаются дочерние строки, которые будут ссылаться на родительские записи (Order), которых больше не будет после обновления.Тем не менее, если вы обновите таблицу данных Order, вам также необходимо обновить таблицу данных OrderDetail или удалить связь между двумя таблицами данных.

Надеюсь, это поможет...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top