you can only do it in sqlin dataset, you cannot join query two datatables like what you can do in t-sql

解决方案 »

  1.   

    // C#
    private void lbOrders_SelectedIndexChanged
    (object sender, System.EventArgs e)
    {
       // 选择新订单时,清除 RTF 文本框。
       rtbDetails.Clear();   // 声明一个用来保存选定的订单 ID 的整数。
       int SelectedOrderID;
       // 将选定的项目设置为整数。
       SelectedOrderID = (int)lbOrders.SelectedItem;   // 声明一个用来保存选定订单的记录的数据行。
       DataRow drSelectedOrder;
       drSelectedOrder = 
          dsNorthwind1.Orders.FindByOrderID(SelectedOrderID);   // 声明一个用来保存相关记录的数据行数组。
       DataRow[] draOrderDetails;
       draOrderDetails = 
          drSelectedOrder.GetChildRows("OrdersOrderDetails");   string details = "";
       foreach(DataRow drDetails in draOrderDetails)
       {
          foreach(DataColumn dcDetails in drDetails.Table.Columns)
          {
             details += dcDetails.ColumnName + ": ";
             details += drDetails[dcDetails].ToString() + "\n";
          }
          details += "\n";
       }
       rtbDetails.Text = details;
    }
    保存项目。 
    运行应用程序。 
    在列表框中选择一个订单,其订单明细将显示在 RTF 文本框中。 
    在列表框中选择另一个订单。RTF 文本框中的订单明细将被更新。 
    浏览多对多关系
    构成多对多关系的表通常通过保证数据完整性的第三方表进行连接。在罗斯文数据库中,订单表和产品表就是这样相关的。因为有些订单可能包含很多产品,而有些产品又在很多订单中销售。这两个表是通过订单明细表连接的,订单明细表利用这两个表中的列建立自己特定的列,并使这些数据相关。浏览构成多对多关系的三个表与处理一对多关系的表并没有太大区别。要浏览多对多关系,您可以基于订单明细表中的单个记录来访问产品,这将返回产品名称并显示在订单明细中。您可以使用 GetParentRow 方法从产品表中访问产品名称。调用 GetParentRow 方法将返回单个数据行,而调用 GetChildRows 方法将返回数据行数组(如上例所示)。从订单明细记录中获取产品名称 
      

  2.   

    在 Solution Explorer(解决方案资源管理器)中,右键单击 Form1 并从快捷菜单中选择 View Code(查看代码)。 
    在列表框 (lbOrders) 的 SelectedIndexChanged 事件处理程序中,将以下代码添加到 For Each 行之间:
    ' Visual Basic
    details &= "产品名称: " & _
       CType(drDetails.GetParentRow("ProductsOrderDetails") _
       ("ProductName"), String) & ControlChars.CrLf// C#
    details += "产品名称: " + 
       drDetails.GetParentRow("ProductsOrderDetails")["ProductName"] 
       + "\n";
    保存项目。 
    运行应用程序。 
    在列表框中选择一个订单, 
    RTF 文本框中将显示产品名称和详细信息。现在窗体中显示来自所有四个表的相关数据。  图 2:显示产品名称和订单明细的窗体 在列表框中选择另一个订单。RTF 文本框中的订单明细将被更新。 
    关闭窗体。 
    表达式列
    除了包含静态数据外,还可以基于表达式的结果为 DataColumn 分配值。表达式是一个分配给 DataColumn.Expression 属性的字符串。当表达式与相关数据一同使用时,数据列可以包含: 相关数据列的计算所得值。 
    相关数据列的合计信息。 
    相关数据的逻辑比较结果。 
    为说明处理相关数据时的值表达式列,我们将针对每种使用情况介绍一个示例,并添加到 DataRelationExample 应用程序中。添加包含计算值的表达式列
    计算的列包含数学运算结果。可以从现有的列中取值进行计算。订单明细表中将添加一个名为 Total 的新列,它将包含由表达式 UnitPrice * Quantity 返回的值(订单的总计美元值)。添加表达式列 在 Solution Explorer(解决方案资源管理器)中,右键单击 Form1 并从快捷菜单中选择 View Code(查看代码)。 
    将以下代码添加到 Form1_Load 事件处理程序中已有代码之上:
    ' Visual Basic
    ' 在订单明细表中创建名为 Total 的表达式列。
    Dim dcTotal as DataColumn = new DataColumn("Total")
    dcTotal.DataType = System.Type.GetType("System.Decimal")
    dcTotal.Expression = "UnitPrice * Quantity"
    DsNorthwind1.Order_Details.Columns.Add(dcTotal)// C#
    // 在订单明细表中创建名为 Total 的表达式列。
    DataColumn dcTotal = new DataColumn("Total");
    dcTotal.DataType = System.Type.GetType("System.Decimal");
    dcTotal.Expression = "UnitPrice * Quantity";
    dsNorthwind1.Order_Details.Columns.Add(dcTotal);
    运行应用程序。 
    在列表框中选择一个订单, 
    检查 RTF 文本框中的订单明细,并注意每个记录都有一个新的 Total 列,显示 UnitPrice 和 Quantity 字段的乘积。 关闭窗体。 
    添加包含合计信息的表达式列
    Expression 属性支持几个合计功能(Sum、Avg、Count 等)。有关详细信息,请参阅 DataColumn.Expression 属性。为演示如何生成合计信息,需要在订单表中添加一个名为 OrderTotal 的新列。此列将使用 Sum 功能,根据在列表框 (lbOrders) 中选定的订单返回所有子订单明细记录的总计美元值。然后,该值将显示在 RTF 文本框中每个订单明细的上方。创建 OrderTotal 列 在 Solution Explorer(解决方案资源管理器)中,右键单击 Form1 并从快捷菜单中选择 View Code(查看代码)。 
    在 Form1_Load 事件处理程序中,将以下代码添加到在订单明细表中创建 Total 列的代码的下方:
    ' Visual Basic
    ' 在订单表中创建名为 OrderTotal 的表达式列。
    Dim dcOrderTotal as DataColumn = new DataColumn("OrderTotal")
    dcOrderTotal.DataType = System.Type.GetType("System.Decimal")
    dcOrderTotal.Expression = "Sum(Child.Total)"
    DsNorthwind1.Orders.Columns.Add(dcOrderTotal)
      

  3.   

    // C#
    // 在订单表中创建名为 OrderTotal 的表达式列。
    DataColumn dcTotal2 = new DataColumn("OrderTotal");
    dcTotal2.DataType = System.Type.GetType("System.Decimal");
    dcTotal2.Expression = "Sum(Child.Total)";
    dsNorthwind1.Orders.Columns.Add(dcTotal2);
    将合计信息显示在所有订单明细的上方 在 lbOrders_SelectedIndexChanged 事件处理程序中,将以下代码添加到 Dim details As String = "" 或 string details = "" 行之下:
    ' Visual Basic
    details = "订单总计: " & String.Format("{0:c}",  _
    DsNorthwind1.Orders.FindByOrderID(CType(lbOrders.SelectedItem, _
    Integer))("OrderTotal")) & ControlChars.CrLf// C#
    details = "订单总计: " + 
    String.Format("{0:c}",dsNorthwind1.Orders.FindByOrderID
    ((int)lbOrders.SelectedItem)["OrderTotal"]) + "\n"; 
    运行应用程序。 
    在列表框中选择一个订单, 
    请注意,选定订单的所有订单明细的总计金额将显示在 RTF 文本框中的第一行。 在列表框中选择另一个订单,将更新显示以反映新选择的订单。 
    关闭窗体。 
    添加包含逻辑求值的表达式列
    Expression 属性可以基于其他列中的计算值来填充某个数据列。例如,订单表中的 OrderSize 列可以包含值“Big”(如果订单总额大于 1000)或者“Small”(如果订单总额小于 1000)。为演示这类表达式,需要在 DataRelationExample 应用程序中添加代码以执行以下操作: 在订单表中添加名为 OrderSize 的数据列。 
    根据相关订单明细的值来填充 OrderSize 列。 
    在 RTF 文本框的顶部同时显示 OrderSize 列的值和 OrderTotal 的值。 
    添加创建 OrderSize 列的代码 在 Solution Explorer(解决方案资源管理器)中,右键单击 Form1 并从快捷菜单中选择 View Code(查看代码)。 
    在 Form1_Load 事件处理程序中,将以下代码添加到在订单表中创建 OrderTotal 列的代码的下方:
    ' Visual Basic
    ' 在订单表中创建名为 OrderSize 的表达式列。
    Dim dcOrderSize as DataColumn = new DataColumn("OrderSize")
    dcOrderSize.DataType = System.Type.GetType("System.String")
    dcOrderSize.Expression = "IIF(Sum(Child.Total)<1000,'Small','Big')"
    DsNorthwind1.Orders.Columns.Add(dcOrderSize)// C#
    // 在订单表中创建名为 OrderSize 的表达式列。
    DataColumn dcOrderSize = new DataColumn("OrderSize");
    dcOrderSize.DataType = System.Type.GetType("System.String");
    dcOrderSize.Expression = "IIF(Sum(Child.Total)<1000,'Small','Big')";
    dsNorthwind1.Orders.Columns.Add(dcOrderSize);
    显示 OrderSize 的值 在 lbOrders_SelectedIndexChanged 事件处理程序中,将以下代码添加到第一个 For Each 行的上方:
    ' Visual Basic
    details &= " (" & CType(DsNorthwind1.Orders.FindByOrderID _
    (CType(lbOrders.SelectedItem, Integer))("OrderSize"), String) & ")" _
    & ControlChars.CrLf// C#
    details += " (" + dsNorthwind1.Orders.FindByOrderID
    ((int)lbOrders.SelectedItem)["OrderSize"] + ")\n";
    运行应用程序。 
    在列表框中选择一个订单。 
    检查 RTF 文本框中的第一行。选定订单的 OrderSize 将显示在 OrderTotal 的右侧。 
    在列表框中选择另一个订单,将更新显示以反映新选择的订单。 
    从 Debug(调试)菜单中,选择 Stop Debugging(停止调试)。 
    有关相关表的其他信息
    这里有必要提及一些其他信息以丰富本文的内容。填充相关数据表的顺序非常重要
    相关数据表的填充顺序对数据的输出有很大影响,因此必须在设计应用程序时予以考虑。例如,请注意最后一个填充的客户表的情况。当填充客户表时,组合框将填充客户名称值。填充组合框时,会引发 SelectedIndexChanged 事件。这将执行事件处理程序中的代码。由于尚未填充订单表,GetChildRows 方法将返回零 (0) 个记录,窗体的标题将显示错误信息。试一试:更改代码以首先填充客户表,并运行应用程序。窗体的标题显示 ALFKI 的零 (0) 个订单,这是不正确的。返回相关记录的特定版本
    通过将所需的 DataRowVersion 作为第二个(可选的)参数传递给 GetChildRows 或 GetParentRow 方法,可以返回数据行的特定版本。以该应用程序为例,如果只想查看特定客户的原始订单,可以将组合框的 SelectedIndexChanged 事件中的代码更改为类似如下的代码。由于此应用程序中的数据并未更改,以下代码不会产生明显的效果,这里只是作为一个说明。' Visual Basic
    ' 只用选定客户的原始子行
    ' 填充数组。
    Dim draOrders As DataRow() = DsNorthwind1.Customers.FindByCustomerID _
    (cbCustomers.SelectedValue.ToString()).GetChildRows _
    ("CustomersOrders", DataRowVersion.Original)// C#
    // 只用选定客户的原始子行
    // 填充数组。
    DataRow draOrders = dsNorthwind1.Customers.FindByCustomerID
    (cbCustomers.SelectedValue.ToString()).GetChildRows
    ("CustomerOrders", DataRowVersion.Original);
    总结
    要访问特定数据行的相关记录,可以调用该行的 GetChildRows 或 GetParentRow 方法,以传递连接该数据行及其相关记录的数据关系。然后,便可以通过检查由该方法调用返回的数据行(或数据行数组)来访问相关的记录。通过为 DataColumn.Expression 属性分配一个有效的表达式字符串并将数据列添加到相应的 DataTable.Columns 集合中,可以对相关记录中的值进行计算,合计和逻辑求值。
      

  4.   

    you can set up many-to-many relationship in DataSet, see
    http://msdn.microsoft.com/library/en-us/dv_vstechart/html/vbtchnavigatingmultiplerelatedtablesinadonetdataset.asp?frame=true#vbtchnavigatingmultiplerelatedtablesinadonetdatasetanchor9
      

  5.   

    DataRelation 可以使多对多的
    看看它的构造函数吧
      

  6.   

    to:小跑
    你举的例子似乎必须先在xml designer里定义表的关系后才可以的。
    你试过用编码方式加入两个表之间的关系,然后再实现你举的那些例子吗?我是说SqlConnection开始的一切都用手工编码?
    在dataSet.Relations.Add(new DataRelation("relName",colPK,colFK));
    后我根本无法类似FindXX()或GetChildRows()等方法。
    难道非得有个弄出个.xsd文件才能实现吗?