如何在VB.NET中内连接两个已经填充的DataTables

时间:2014-05-14 16:21:42

标签: vb.net datatable merge inner-join

我认为Der Golem的答案是正确的,因为它是我说过的具体问题的正确答案。

不幸的是,我没有发现datatable2中的记录并不是唯一的事实,这显然不能很好地执行"内部连接"在两张桌子上我想要的结果。

如果是,则设置DataRelation将起作用。


我还是VB.NET的新手,所以请耐心等待。

  • 我有两个数据表,每个表都来自不同的数据库服务器。
  • 他们都有三列(为了便于测试,最终的程序将有50 +)。
  • 他们都有一个我希望内部加入的公共数据列(" OrderNum")。

这里有一个问题,但是"答案"对我不起作用,也不对它下面的LINQ选项起作用: Merging 2 data tables in vb.net

这是我的示例代码:

DB1 = New DatabaseConnectionSQL1
DB1.OpenConn()
DB2 = New DB_DatabaseConnectionSQL2
DB2.OpenConn()

Dim dtA As DataTable = New DataTable("DataTable1")
Dim dtB As DataTable = New DataTable("DataTable2")
Dim dtCombined As DataTable = New DataTable("CombinedDataTable")

dtA.Columns.Add("Order", System.Type.GetType("System.String"))
dtA.Columns.Add("Account_Number", System.Type.GetType("System.String"))
dtA.Columns.Add("Account_Name", System.Type.GetType("System.String"))

'"Order" = "Head_Order_Number"

dtB.Columns.Add("Head_Order_Number", System.Type.GetType("System.String"))
dtB.Columns.Add("Line_Number", System.Type.GetType("System.Int32"))
dtB.Columns.Add("Model", System.Type.GetType("System.String"))

dtA = DB1.GetDataTable(sQuery1)
dtB = DB2.GetDataTable(sQuery2)

'This doesn't work as it just appends the table
'dtA.Merge(dtB, True)
'I tried creating a DataSet and setting a Relation, but that kept failing
'I've tried at least 10 different things here. I'm at my wit's end.

dgvDataGrid.DataSource = dtCombined 
dgvDataGrid.Refresh()

DB1.CloseConn()
DB2.CloseConn()

我注意到其他地方的人建议使用Linq。即使我不熟悉它,我也尽力而为,但仍然失败。

表A(dtA):

Order | Account_Number | Account_Name
10000 | 10000000000001 | BlahA
20000 | 10000000000002 | BlahB
30000 | 10000000000003 | BlahC

表B(dtB):

Head_Order_Number| Line_Number | Model
10000            | 00000000034 | MD35Z
15000            | 00000000530 | MX25A
25000            | 00000024535 | P231Y
20000            | 00000027735 | A511L
30000            | 00000000910 | M232C

决赛桌我希望将两者结合起来(dtCombined):

Order | Account_Number | Account_Name | Line_Number | Model
10000 | 10000000000001 | BlahA        | 00000000034 | MD35Z
20000 | 10000000000002 | BlahB        | 00000027735 | A511L
30000 | 10000000000003 | BlahC        | 00000000910 | M232C

非常感谢任何帮助。


我之前尝试添加DataRelation并且一直出现错误,但我没有正确设置。现在我已经解决了这个问题,我又收到了另一个错误:

" System.ArgumentException:无法启用此约束,因为并非所有值都具有相应的父值。"

dt1 = New DataTable("DataTable1")
dt1.Columns.Add("order_number", System.Type.GetType("System.String"))
dt1.Columns.Add("account_name", System.Type.GetType("System.String"))

dt2 = New DataTable("DataTable2")
dt2.Columns.Add("head_order_number", System.Type.GetType("System.String"))
dt2.Columns.Add("model", System.Type.GetType("System.String"))

Conn1.ConnectionString = sConnString1
Dim da1 As SqlDataAdapter = New SqlDataAdapter(sQuery1, Conn1)
Conn1.Open()

Conn2.ConnectionString = sConnString2
Dim da2 As SqlDataAdapter = New SqlDataAdapter(sQuery2, Conn2)
Conn2.Open()

ds = New DataSet
da1.Fill(ds, "DataTable1")
da2.Fill(ds, "DataTable2")

Dim dr As DataRelation = New DataRelation("Combined", _
    ds.Tables("DataTable1").Columns("OrderNo"), _
    ds.Tables("DataTable2").Columns("OrderNo"))
ds.Relations.Add(dr)

dgvDataGrid.DataSource = ds
dgvDataGrid.Refresh()

Conn1.Close()
Conn2.Close()

这个错误似乎有意义,因为DataTable1总共有1950行,而DataTable2有超过4000,但这不是DataRelation的重点吗?它有效地内连接两个表,所以最终结果应该是1950行?

1 个答案:

答案 0 :(得分:4)

您要执行的查询如下所示:

Dim sql As String = "SELECT dta.*, dtB.* FROM dtA INNER JOIN dtB ON dtA.Order = dtB.Order"

请注意,Order = 25000的记录 JOIN

<强> [编辑]

根据你的评论,我发现你缺乏一些知识......

所以 - 假设你已经准备好了你的数据库连接(conn):

Dim cmd As OleDbCommand = New OleDbCommand(sql, conn)
Dim da As OleDbDataAdapter = New OleDbDataAdapter
da.SelectCommand = cmd
conn.Open()
Dim ds As DataSet = New DataSet
da.Fill(ds, "Result")
conn.Close()

dgvDataGrid.datasource = ds
ds.DataBind()

我假设是OleDb连接 - 但是SQL连接真的是一样的(用Sql替换OleDb)

[编辑2] 你决定让我出汗!

最后,针对您的具体问题提供了解决方案:

如下所示:http://msdn.microsoft.com/en-us/library/cc188919.aspx

DataRelation对象就是您所需要的。

创建DataRelation对象

' Create the DataRelation and
' relate the customers to their orders
DataRelation oDr_Customer2Order = new DataRelation("Customer2Order",
    oDs.Tables["Customer"].Columns["CustomerID"],
    oDs.Tables["Order"].Columns["CustomerID"]);
oDs.Relations.Add(oDr_Customer2Order);

通过创建DataRelation对象然后将它们添加到DataSet的Relations集合,三个DataTable对象的行集通过定义的字段相互关联。与大多数ADO.NET对象一样,DataRelation对象有几个不同的构造函数。我使用了接受关系名称,父表列和子表列的构造函数。如果有多个列定义了关系,我可以传入父表的列数组和子表列的数组。另一种选择是使用我在图3中使用的相同的前三个参数,然后传入第四个参数来表示是否应该自动创建约束(传入布尔值)。但更多的是关于时刻的限制。 一旦DataSet填充了三个行集并建立了连接DataTable对象的关系,DataSet就可以通过设置DataSource属性轻松地显示在Web窗体的DataGrid中:

dataGrid1.DataSource = oDs;

DataGrid足够聪明,可以确定需要显示多个DataTable对象,并且应该允许按照DataRelation对象规定的顺序导航行集。