Join two queries from different data sources using VB.NET - sql

I have two queries. One is an Oracle query, and one is a SQL Server query.
Oracle Columns: ID, Subject, Course
SQL Server Columns: ID, Recommended Subject, Recommended Course
I would like to join the two queries on ID. I need to find out which IDs have a subject that is not equal to the recommended subject or a course that is not equal to the recommended course. Then, display the results in a GridView.
Here's what I have tried to do so far. I have removed my SQL commands and connection strings.
Dim sConnectionString As String = ConfigurationManager.ConnectionStrings("sqlserver").ConnectionString
Dim sCN As New SqlConnection(sConnectionString)
Dim sCommandWrapper As SqlCommand = New SqlCommand("SQL", sCN)
Dim sDataAdapter As SqlDataAdapter = New SqlDataAdapter
sDataAdapter.SelectCommand = sCommandWrapper
Dim pConnectionString As String = ConfigurationManager.ConnectionStrings("oracle").ConnectionString
Dim pCN As New OleDbConnection(pConnectionString)
Dim pCommandWrapper As OleDbCommand = New OleDbCommand("SQL", pCN)
Dim pDataAdapter As OleDbDataAdapter = New OleDbDataAdapter
pDataAdapter.SelectCommand = pCommandWrapper
Dim stopDS As DataSet = New DataSet()
sDataAdapter.Fill(stopDS, "Recommendations")
pDataAdapter.Fill(stopDS, "Registrations")

Since you have your two results in a DataSet, you can define a relationship between the two tables using the DataSet.Relations property:
stopDS.Relations.Add(
"ID2ID",
stopDS.Tables("Recommendations").Columns("ID"),
stopDS.Tables("Registrations").Columns("ID")
)
You can then get the matching rows from either end of the relationship (apologies if I got the relationship the wrong way around!):
Dim rows() As DataRow = stopDS.Tables("Recommendations").Rows(0).GetChildRows("ID2ID")
Dim row As DataRow = stopDS.Tables("Registrations").Rows(0).GetParentRow("ID2ID")
' Can also use .GetParentRows(...) for an array.
Here is a complete example console app:
Module Module1
Sub Main()
Dim t1 = New DataTable()
t1.TableName = "Names"
t1.Columns.Add("ID", GetType(Integer))
t1.Columns.Add("Name", GetType(String))
Dim t2 = New DataTable()
t2.TableName = "Addresses"
t2.Columns.Add("ID", GetType(Integer))
t2.Columns.Add("Address", GetType(String))
Dim r As DataRow = Nothing
r = t1.NewRow()
r("ID") = 1
r("Name") = "Bob"
t1.Rows.Add(r)
r = t1.NewRow()
r("ID") = 2
r("Name") = "Joe"
t1.Rows.Add(r)
r = t1.NewRow()
r("ID") = 3
r("Name") = "Sue"
t1.Rows.Add(r)
r = t2.NewRow()
r("ID") = 1
r("Address") = "1 Main St"
t2.Rows.Add(r)
r = t2.NewRow()
r("ID") = 3
r("Address") = "2 Any St"
t2.Rows.Add(r)
Dim ds = New DataSet()
ds.Tables.Add(t1)
ds.Tables.Add(t2)
' Define relationship between the ID columns
ds.Relations.Add(
"NameToAddress",
ds.Tables("Names").Columns("ID"),
ds.Tables("Addresses").Columns("ID"))
For Each nameRow In t1.AsEnumerable()
Console.WriteLine("Name: {0}", nameRow.Field(Of String)("Name"))
For Each addrRow In nameRow.GetChildRows("NameToAddress")
Console.WriteLine("--Addr: {0}", addrRow.Field(Of String)("Address"))
Next
Next
Console.WriteLine("==========")
For Each addrRow In t2.AsEnumerable()
Console.WriteLine("Addr: {0}", addrRow.Field(Of String)("Address"))
Dim pr = addrRow.GetParentRow("NameToAddress")
If pr IsNot Nothing Then
Console.WriteLine("++Name: {0}", pr.Field(Of String)("Name"))
End If
For Each nameRow In addrRow.GetParentRows("NameToAddress")
Console.WriteLine("--Name: {0}", nameRow.Field(Of String)("Name"))
Next
Next
Console.ReadLine()
End Sub
End Module
The results are:
Name: Bob
--Addr: 1 Main St
Name: Joe
Name: Sue
--Addr: 2 Any St
==========
Addr: 1 Main St
++Name: Bob
--Name: Bob
Addr: 2 Any St
++Name: Sue
--Name: Sue

I really like Mike's approach, but let me suggest another one and you can choose whichever more suitable for you.
You can set up a linked server to your Oracle database. It is described in this answer. Alternatively you can follow this article.
Then simply join the two tables and get the results:
SELECT * FROM SqlTable s
INNER JOIN OracleServer.OracleDB..OracleTable o ON o.ID = s.ID
AND (s.Course != o.[Recommended Course] OR s.Subject != o.[Recommended Subject])
Unfortunately I don't have oracle installed to completely test this myself, but I hope you get in the direction.

Related

Temp table has no information but original table does

I have a datatable that has all the data in it but when my VB.net program runs it and I make a temptable, the temptable has no info. WHat am I doing wrong?
Public Sub HTSCode()
Dim TempTable As New DataTable
Dim DV As DataView
TempTable = RatesDataSet.HTS
DV = TempTable.DefaultView
DV.Sort = "HTS Code NA"
TempTable = DV.ToTable
For Each Row As DataRow In TempTable.Rows
'doesnt get to this point cause there are no rows.
Next
End Sub
I am attaching pictures 1 of my datatable before I run it so there is info there and the second is when running it shows it empty. I am now even getting the data directly from the table and not a copy of it or temptable anymore.
The answer is your problem lies elsewhere. Using this sample to simulate your code, I can't ever get an object with no rows
Public Class ds
Public ReadOnly Property HTS As DataTable
Get
Dim dt As New DataTable()
dt.Columns.AddRange(
{
New DataColumn("HTS Code", GetType(Integer)),
New DataColumn("HTS Code NA", GetType(Integer))
})
For i = 0 To 4
Dim row = dt.NewRow()
row("HTS Code") = i
row("HTS Code NA") = 10 - i
dt.Rows.Add(row)
Next
Return dt
End Get
End Property
End Class
Dim RatesDataSet = New ds
Dim TempTable As DataTable
Dim DV As DataView
TempTable = RatesDataSet.HTS
Console.WriteLine(TempTable.Rows.Count)
DV = TempTable.DefaultView
Console.WriteLine(DV.Count)
DV.Sort = "HTS Code NA"
Console.WriteLine(DV.Count)
TempTable = DV.ToTable
Console.WriteLine(TempTable.Rows.Count)
Console.WriteLine("HTS Code NA:")
For Each Row As DataRow In TempTable.Rows
Console.WriteLine(Row("HTS Code NA"))
Next
Output
5
5
5
5
HTS Code NA:
6
7
8
9
10
I think it was my dumbness I never linked the table to that form. As soon as I did that the table was filled and works. Sorry and thanks

Logon fails if two tables are in the dataSet

My report fills two tables. It works on the local server, but when published to another server it gives the following error:
Unable to connect. Login failed.
When I take off the second table and only use the first table, the report works. How can I resolve this?
objDataTable = New Data.DataTable
objDataTable.TableName = "Table"
objDataTable.Columns.Add("pes_nom", GetType(String))
objRow = objDataTable.NewRow
objRow("pes_nom") = objProposta.clsPessoa.pesNom
objDataTable.Rows.Add(objRow)
objDataSet = New Data.DataSet
objDataSet.Tables.Add(objDataTable)
If objProposta.clsDependente.DtDependentes IsNot Nothing Then
Dim dtCloned As New Data.DataTable
dtCloned = objProposta.clsDependente.DtDependentes.Clone()
dtCloned.Columns(3).DataType = System.Type.GetType("System.String")
For Each row As Data.DataRow In objProposta.clsDependente.DtDependentes.Rows
dtCloned.ImportRow(row)
Next
dtCloned.TableName = "Dependentes"
objDataSet.Tables.Add(dtCloned)
End If
Bmgviewer1.PathReport = "RptTermoAdesaoHAP.rpt"
Bmgviewer1.DataSet = objDataSet
Bmgviewer1.DataBind()
The solution was insert all data in just one table with multiple rows.
I added the following code:
If objProposta.clsDependente.DtDependentes IsNot Nothing Then
For Each row As Data.DataRow In objProposta.clsDependente.DtDependentes.Rows
objRow("dep_nom") = row.Item("dep_nom").ToString()
objRow("dep_cpf_cgc") = row.Item("dep_cpf_cgc").ToString()
objDataTable.Rows.Add(objRow)
objRow = objDataTable.NewRow
Next
Else
objDataTable.Rows.Add(objRow)
End If
And it worked.

Populating a treeview with two tables using vb.net

Hello I have this two tables:
Then I want this result using treeview:
id department category
1 MIS System
1 MIS Networking
1 MIS Programmer
2 Audit Operations
2 Audit DS
3 HRD PA
3 HRD PayBen
3
HRD PS
3 HRD PLD
4 Acounting Sup
4 Acounting FMCG
5 Procurement NULL
or like this
MIS
-System
-Networking
-Programmer
AUDIT
-Operations
-DS
HRD
-PA
-PayBen
-PS
-PLD
Acounting
-Sup
-FMCG
Can someone please guide me, thank you. I'm having trouble finding any solution on the internet and I'm new to the vb.net language.
In my code below, i give you the logic. You just need to query your tables now.
Tell me if you need explanations.
TreeView1.Nodes.Clear()
'Create a first node and select it
Dim root As TreeNode = TreeView1.Nodes.Add("Test")
TreeView1.SelectedNode = root
'Create two types of node
Dim department As New TreeNode()
Dim category As New TreeNode()
'Daos (if you create a Department class and subDepartment class)
Dim _daoD As New Departments(_cnx)
Dim _daoSD As New subDepartments(_cnx)
'Lists (depending on classes too)
Dim listD As List(Of Department)
Dim listSD As List(Of subDepatment)
For Each dep As Department In listD
'Add a Tree node for a new department
department = New TreeNode(dep.department)
department.Tag = dep.id
root.Nodes.Add(department)
TreeView1.SelectedNode = departement
For Each subDep As subDepartment In listSubDep
'Add a TreeNode for new categories
categ = New TreeNode(subDep.category)
categ.Tag = subDep.id
Nodes.Add(categ)
Next
Next
Then, you can create 4 classes (the first one with properties, and the second one to query in the table)
Public Class Department
'properties
Public Property id As Integer
Get
Return _ID
End Get
Set(ByVal Value As Integer)
_ID = Value
End Set
End Property
'etc
End Class
Public Class Departments
Dim _cnx As OracleConnection (if you use Oracle)
Public Sub New(ByVal pcnx As OracleConnection)
_cnx = pcnx
End Sub
'Your queries
End Class
Here is my solutio. i hope this will help someone who have this kind of problem.
Dim myConnString As String = "Data Source=name;Initial Catalog=database;Integrated Security=True"
Dim daMyName As New SqlDataAdapter
Dim dsMyName As New DataSet
Dim recCount As Integer
Dim mySelectQuery As String = "SELECT DEPARTMENT.department, subDept.category from subdept right join department on .department.id = subDept.parent"
Dim myConnection As New SqlConnection(myConnString)
Dim myCommand As New SqlCommand(mySelectQuery, myConnection)
myConnection.Open()
daMyName.SelectCommand = myCommand
daMyName.Fill(dsMyName)
Dim tbl As DataTable = dsMyName.Tables(0)
recCount = dsMyName.Tables(0).Rows.Count
tvw1.Nodes.Clear() 'Clear any nodes so we don't load a tree into a tree
Dim nd As TreeNode
nd = tvw1.Nodes.Add("DEPARTMENT")
Dim parentRow As DataRow
Dim rowNdx As Integer
rowNdx = 0
daMyName.Fill(tbl)
Dim Jan As String
For Each parentRow In tbl.Rows
If rowNdx = recCount Then
Exit For
End If
Jan = dsMyName.Tables(0).Rows(rowNdx)("Department").ToString() 'set the next name
Dim Dnode As TreeNode
Dnode = tvw1.Nodes.Add(dsMyName.Tables(0).Rows(rowNdx)("department").ToString())
Dim cnode As TreeNode
cnode = New TreeNode
Do While dsMyName.Tables(0).Rows(rowNdx)("department").ToString() = Jan And rowNdx < recCount
'if it changes we need to kick out of Do While
cnode = Dnode.Nodes.Add(dsMyName.Tables(0).Rows(rowNdx)("category").ToString())
rowNdx = rowNdx + 1
If rowNdx = recCount Then
Exit Do
End If
Loop
Next parentRow
myConnection.Close()

Distinct Rows From Vb.Net DataTable

I have a scenario, in which I have to apply distinct filter onto DataTable and find the rows only which are distinct,
I am using dt.DefaultView.ToTable(True, Columns) this statement but no effect.
Here is my chunk of code..
Try
Dim dTable As New DataTable()
dTable.Columns.Add("AutoID")
dTable.Columns.Add("AnotherID")
dTable.Columns.Add("CitY")
Dim row As DataRow = Nothing
For i As Integer = 0 To 4
row = dTable.NewRow()
row("AutoID") = i + 1
row("AnotherID") = i + 10
row("City") = "Vetican"
dTable.Rows.Add(row)
Next
dTable.Rows.Add(6, "11", "Oslo")
dTable.Rows.Add(7, "12", "Toronto")
Dim TobeDistinct As String() = {"AnotherID"}
Dim dtDistinct As DataTable = GetDistinctRecords(dTable, TobeDistinct)
Catch ex As Exception
End Try
and the method ..
Public Shared Function GetDistinctRecords(ByVal dt As DataTable, ByVal Columns As String()) As DataTable
Dim dtURecords As New DataTable()
dtURecords = dt.DefaultView.ToTable(True, Columns)
Return dtURecords
End Function
Here is the screen shot , which I want..
Which rows do you want to keep and which rows should be removed? If you just want to keep one row per AnotherID it seems to be arbitrary to keep Vetican instead of Oslo. Maybe you want to concat both as in Vetican, Oslo.
I would use Linq instead:
Dim resultTable = dTable.Clone() ' empty table same columns
Dim idGroups = dTable.AsEnumerable().GroupBy(Function(r) r.Field(Of String)("AnotherID"))
For Each grp In idGroups
Dim r As DataRow = resultTable.Rows.Add()
r.SetField("AutoID", grp.First().Field(Of String)("AutoID"))
r.SetField("AnotherID", grp.Key)
Dim cities = From row In grp Select row.Field(Of String)("City")
r.SetField("City", String.Join(", ", cities))
Next

convert a datatable

I have a datatable like this
X,Y,Z
0,0,A
0,2,B
0,0,C
1,0,A
1,0,C
2,2,A
2,2,B
2,0,C
3,2,B
3,1,C
4,3,A
4,0,B
4,1,C
5,3,A
5,2,B
5,0,C
and I want to convert it to something like this:
X,A,B,C
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
I tried with dataset and linq but not I wasn't lucky.
My code for linq:
Dim q = (From c In dt _
Select c("Z") Distinct) 'I found out which categories I have in Z column (my example :A,B,C)
Dim ldt(q.Count) As DataTable
For i = 0 To q.Count - 1
Dim sfil As String = q(i).ToString
Dim r = (From c In dt _
Select c Where c("Z") = sfil)
ldt(i) = r.CopyToDataTable
Next
So now I have 3 tables (ldt(0) with values for A, ldt(1) with values for B, ldt(2) with values for C)
and I was thinking to do something like leftJoin but anything that I tried is fail.
Any solution or even a better idea?
Thanks
So a new example it would be:
I have this table:
id,Price,Item
0,0,Laptop
0,2,Tablet
0,0,Cellphone
1,0,Laptop
1,0,Tablet
2,2,Laptop
2,2,Cellphone
2,0,Tablet
3,2,Cellphone
3,1,Tablet
4,3,Laptop
4,0,Cellphone
4,1,Tablet
5,3,Laptop
5,2,Cellphone
5,0,Tablet
and I would like to convert it to this:
X,Laptop,Tablet,Cellphone
0,0,2,0
1,0, ,0
2,2,2,0
3, ,2,1
4,3,0,1
5,3,2,0
The values for each of the columns Laptop, Tablet, Cellphone are the Y values from the first table.
I hope it make more sense now.
I believe you can create a DataTable with column names corresponding to the item names. Then you group the previous DataTable by id and use each grouping to populate a row. Forgive me if I get anything wrong. I don't work with VB or DataTables that much.
Dim itemNames = (From c In dt _
Select c("Item") Distinct)
Dim newDt as DataTable = new DataTable()
Dim idColumn As DataColumn = new DataColumn()
idColumn.DataType = System.Type.GetType("System.Int32")
idColumn.ColumnName = "id"
idColumn.ReadOnly = True
idColumn.Unique = True
newDt.Columns.Add(idColumn)
For Each itemName As String In itemNames
Dim column As DataColumn = new DataColumn()
column.DataType = GetType(Nullable(Of Integer))
column.ColumnName = itemName
column.ReadOnly = True
column.Unique = False
newDt.Columns.Add(column)
Next
Dim groupingById = From row in dt
Group By Id = row("id")
Into RowsForId = Group
For Each grouping In groupingById
Dim row as DataRow = newDt.NewRow()
row("id") = grouping.Id
For Each rowForId in grouping.RowsForId
row(rowForId("Item")) = rowForId("Price")
Next
newDt.Rows.Add(row)
Next