我在Windows窗体应用程序上使用VS2008 C#Express和Northwind数据库。

我使用拖放操作为两个datagridviews设置主详细信息绑定(我使用了订单和订单详细信息)。此时,一切都按预期工作。为了不返回表中的每一行,我想基于Orders表的过滤器以及Orders Details表中的字段过滤Orders表。在TableAdapter配置向导中,我使用查询构建器添加了一个新的FillByMyFilter,它创建了以下查询:

SELECT订单。[订单ID],订单。[客户ID],订单。[员工ID],订单。[船名],订单。[船舶地址],订单。[船舶城市],订单。[发货]区域],                       订单。[船舶邮政编码],订单。[船舶国家],订单。[船舶通过],订单。[订单日期],订单。[所需日期],订单。[发货日期],                       Orders.Freight 来自订单INNER JOIN                       [订单详情] ON订单。[订单ID] = [订单详情]。[订单ID] 在哪里(订单。[船名]喜欢N'A%')和([订单明细] .Quantity <!> lt; 20)

我通过添加两个表来获得此功能,但未检查“订单详细信息”表中的任何字段框,以便它只返回原始“填充”查询中使用的列。我此时只尝试过滤主表中的DataSet,而不是返回不同数量的列。订单明细的子行仍应像默认的未过滤结果集一样工作。

现在出现问题:当我单击“执行查询”按钮时,它可以正常工作。我使用设计器创建的默认填充从上面的查询获得53行而不是1078行。它返回与原始填充查询相同的列。但是,当我尝试运行应用程序时,我得到以下约束错误:

<!>“;无法启用约束。一行或多行包含违反非null,唯一或外键约束的值。<!> quot;

我做错了什么?

更新:我认为由于向导创建的INNER JOIN,我得到了约束错误。如果我编辑查询以使用LEFT JOIN,则向导会将其更改回INNER JOIN。

我的问题仍然是如何根据父表和子表中的条件过滤父表(Orders)中的记录。我的下一个测试是尝试使用存储过程,但想知道只使用TableAdapter自定义FillBy方法。

问候,

调试

有帮助吗?

解决方案 3

感谢所有发布的答案。以下是我使用TableAdapter向导和Northwind类型数据集的方法。

1)右键单击xsd设计器中的Parent表以添加或配置查询。 2)单击<!>“;下一步<!>”;向导中的按钮,直到您看到<!>“查询生成器<!>”;按钮。单击“查询生成器”按钮以使您自己进入查询生成器模式。 3)右键单击并在设计窗格中添加子表。您应该有两个表和连接它们的默认约束。 4)单击要过滤的子表上的列(此复选标记将在以后删除),以便将其添加到条件窗格,以便您可以对其进行过滤。 5)为Parent和Child列添加过滤器。在这个例子中,我过滤了船名LIKE'A%'和订单数量<!> lt; 20。

请注意,此时您可以通过单击“执行查询”按钮来测试查询。使用Northwind DB for SQL 2008紧凑版我得到53行返回。如果您此时要保存它,它将在运行时失败,因为结果集中存在重复的主键。因此接下来的几个步骤将摆脱'em。

6)在条件窗格中,取消选中先前添加的子表列。过滤器将保留,现在也将在设计窗格中取消选中相同的列。如果运行查询,您仍将拥有53行但没有子表列。 7)右键单击设计窗格并添加<!> quot; Group By <!> quot;。此时,执行此查询时,订单ID中应该没有重复项。我收到了29行返回。 8)单击确定,然后单击<!>“;下一步<!>”;按钮,直到您保存新的FillBy查询。 9)更改源代码以使用新的FillBy。

当我运行应用程序时,我得到了过滤的父表,其中包含了执行查询按钮返回的相同的29行。子表按预期工作,并包含至少一个包含数量<!> lt;的子行。 20。

对于真实世界的应用程序,我认为使用存储过程或LINQ会更好。但这个问题让我摸不着头脑,所以我<!>“使它适合<!>”;只是因为这是一个挑战(至少对我而言)。

其他提示

本文包含一些疑难解答建议,以确定导致问题的确切行:

DataSet地狱 - <!>“无法启用约束。一行或多行包含值.... <!> quot;

如果您查看Orders.Designer.cs(猜测,因为我在VB中工作),您可能会看到在Orders上定义的唯一约束(对于主键)。

我怀疑问题是,当您运行查询时,您将获得一个或多个具有<!> gt;的订单。 1 OrderDetails.Quanity <!> gt; 20 ....所以,该订单将在结果集中返回两次,违反主键。

尝试: SELECT *来自订单,其中[Ship Name] LIKE'%any%AND OrderID in(从OrderDetails选择OrderID,其中Quantity <!> lt; 20)

这可能是一种非常低效的方法,在oracle中你会使用EXISTS()而不是IN()但是我不知道sql server等价。

希望你得到这个答案,但如果没有,请考虑一下。

在您的数据集中,如果Order和OrderDetail DataTables之间存在关系,那么它的工作方式有点像FK约束。因此,子表(OrderDetail)中没有记录没有相应的父(Order)记录。所以可能发生的情况是当您刷新Order DataTable时,使用上面提到的查询,OrderDetail表中仍然存在子行,这些子行将具有对刷新后不再存在的父(订单)记录的反映。也就是说,如果刷新Order DataTable,您还需要刷新OrderDetail数据表,或者删除两个DataTable之间的关系。

希望这会有所帮助......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top