我在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%')和([订单明细]。数量< 20)
我通过添加两个表来获得此功能,但未检查“订单详细信息”表中的任何字段框,以便它只返回原始“填充”查询中使用的列。我此时只尝试过滤主表中的DataSet,而不是返回不同数量的列。订单明细的子行仍应像默认的未过滤结果集一样工作。
现在出现问题:当我单击“执行查询”按钮时,它可以正常工作。我使用设计器创建的默认填充从上面的查询获得53行而不是1078行。它返回与原始填充查询相同的列。但是,当我尝试运行应用程序时,我得到以下约束错误:
“无法启用约束。一行或多行包含违反非空,唯一或外键约束的值。”
我做错了什么?
更新:我认为由于向导创建的INNER JOIN,我得到了约束错误。如果我编辑查询以使用LEFT JOIN,则向导会将其更改回INNER JOIN。
我的问题仍然是如何根据父表和子表中的条件过滤父表(Orders)中的记录。我的下一个测试是尝试使用存储过程,但想知道只使用TableAdapter自定义FillBy方法。
问候,
调试
答案 0 :(得分:2)
本文包含一些疑难解答建议,以确定导致问题的确切行:
DataSet hell - "Failed to enable constraints. One or more rows contain values...."
答案 1 :(得分:1)
如果您查看Orders.Designer.cs(猜测,因为我在VB中工作),您可能会看到在Orders上定义的唯一约束(对于主键)。
我怀疑问题是,当您运行查询时,您将收到一个或多个具有>的订单。 1 OrderDetails.Quanity> 20 ....所以,该订单将在结果集中返回两次,违反主键。
尝试: SELECT *来自订单,其中[Ship Name] LIKE'%any%AND ANDIDID(从OrderDetails中选择OrderID,其中Quantity< 20)
这可能是一种非常低效的方法,在oracle中你会使用EXISTS()而不是IN()但我不知道sql server等价。
答案 2 :(得分:1)
感谢所有发布的答案。以下是我使用TableAdapter向导和Northwind类型数据集的方法。
1)右键单击xsd设计器中的Parent表以添加或配置查询。 2)单击向导中的“下一步”按钮,直到看到“查询生成器”按钮。单击“查询生成器”按钮以使您自己进入查询生成器模式。 3)右键单击并在设计窗格中添加子表。您应该有两个表和连接它们的默认约束。 4)单击要过滤的子表上的列(此复选标记将在以后删除),以便将其添加到条件窗格,以便您可以对其进行过滤。 5)为Parent和Child列添加过滤器。在这个例子中,我过滤了船名LIKE'A%'和订单数量< 20。
请注意,此时您可以通过单击“执行查询”按钮来测试查询。使用Northwind DB for SQL 2008紧凑版我得到53行返回。如果您此时要保存它,它将在运行时失败,因为结果集中存在重复的主键。因此接下来的几个步骤将摆脱'em。
6)在条件窗格中,取消选中先前添加的子表列。过滤器将保留,现在也将在设计窗格中取消选中相同的列。如果运行查询,您仍将拥有53行但没有子表列。 7)右键单击设计窗格并添加“分组依据”。此时,执行此查询时,订单ID中应该没有重复项。我收到了29行返回。 8)单击“确定”,然后单击“下一步”按钮,直到保存新的FillBy查询。 9)更改源代码以使用新的FillBy。
当我运行应用程序时,我得到了过滤的父表,其中包含了执行查询按钮返回的相同的29行。子表按预期工作,并且包含至少一个包含数量< 20。
对于真实世界的应用程序,我认为使用存储过程或LINQ会更好。但是这个问题让我摸不着头脑,所以我“让它变得合适”只是因为它是一个挑战(至少对我而言)。
答案 3 :(得分:0)
希望你得到这个答案,但如果没有,请考虑一下。
在您的数据集中,如果Order和OrderDetail DataTables之间存在关系,那么它的工作方式有点像FK约束。因此,子表(OrderDetail)中没有记录没有相应的父(Order)记录。所以可能发生的情况是当您刷新Order DataTable时,使用上面提到的查询,OrderDetail表中仍然存在子行,这些子行将具有对刷新后不再存在的父(订单)记录的反映。也就是说,如果刷新Order DataTable,您还需要刷新OrderDetail数据表,或者删除两个DataTable之间的关系。
希望这会有所帮助......