2

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

我使用拖放设置两个数据网格视图的主详细信息绑定(我使用了订单和订单详细信息)。在这一点上,一切都按预期工作。为了不返回表中的每一行,我想根据 Orders 表的过滤器和 Orders Details 表中的字段过滤 Orders 表。在 TableAdapter 配置向导中,我使用查询生成器添加了一个新的 FillByMyFilter,它创建了以下查询:

SELECT Orders.[Order ID]、Orders.[Customer ID]、Orders.[Employee ID]、Orders.[Ship Name]、Orders.[Ship Address]、Orders.[Ship City]、Orders.[Ship Region]、 Orders.[Ship Postal Code]、Orders.[Ship Country]、Orders.[Ship Via]、Orders.[Order Date]、Orders.[Required Date]、Orders.[Shipped Date]、Orders.Freight FROM Orders INNER JOIN [Order Details] ON Orders.[Order ID] = [Order Details].[Order ID] WHERE (Orders.[Ship Name] LIKE N'A%') AND ([Order Details].Quantity < 20)

我通过添加两个表得到了这个,但没有检查 Order Details 表中的任何字段框,因此它只会返回原始 Fill 查询中使用的列。我现在只是试图过滤主表中的数据集,而不是返回不同数量的列。订单详细信息的子行仍应像默认的未过滤结果集一样工作。

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

“未能启用约束。一行或多行包含违反非空、唯一或外键约束的值。”

我究竟做错了什么?

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

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

问候,

调试

4

4 回答 4

2

本文包含一些故障排除建议,以查明导致问题的确切行:

数据集地狱 - “无法启用约束。一行或多行包含值......”

于 2009-01-04T00:54:59.457 回答
1

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

我怀疑问题是,当您运行查询时,您将获得一个或多个具有> 1 OrderDetails.Quantity > 20 ....的单个订单。因此,该订单将在您的结果集中返回两次,这违反了主键。

尝试: SELECT * from orders where [Ship Name] LIKE '%whatever% AND OrderID in(从 OrderDetails 中选择 OrderID,其中 Quantity < 20)

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

于 2009-01-05T22:15:01.573 回答
1

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

1)右键单击xsd设计器中的父表添加或配置查询。2) 单击向导中的“下一步”按钮,直到看到“查询生成器”按钮。单击查询构建器按钮以进入查询构建器模式。3)右键单击并在设计窗格中添加子表。您应该有两个表和连接它们的默认约束。4) 单击要过滤的子表上的列(此复选标记稍后将被删除),以便将其添加到条件窗格中,以便您可以过滤它。5) 为父列和子列添加过滤器。在此示例中,我过滤了 Ship Name LIKE 'A%' 和 Order Quantity < 20。

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

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

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

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

于 2009-01-06T03:12:47.727 回答
0

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

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

希望这可以帮助...

于 2009-01-05T14:43:11.423 回答