Getting LINQ Data Into DataTable - vb.net

I've been tasked to take over some legacy reporting written in Visual Basic and have been tasked with updating some of the reports which the only way I can see is to use LINQ which I'm having a heck of a time with and I've spent the past week on Google trying to sort it out but I'm just missing "something".
What I have is a datatable that has like 10 columns and I need to group on two taking the results of the grouping and placing it into another datatable.
What I have so far is...
Dim Rep_Country_DataTable As New System.Data.DataTable
Dim Rep_Country_Group As IEnumerable = From Data_Row In Export_DataTable.Select("REP IS NOT NULL").AsEnumerable
Group Data_Row By Rep = Data_Row.Field(Of String)("REP"),
Country = Data_Row.Field(Of String)("COUNTRY") Into Group
Select Rep, Country
The LINQ works and I can see the grouped data in "Rep_Country_Group". My problem now is getting that data into the "Rep_Country_Group_DataTable" datatable, that's the part I can't figure out.
I would appreciate any help with this as I know it's something simple I'm missing.

Thanks to those that replied. Using the replies I was able to refine my Google searches and found my solution.
Here's the revised code that solved my issue...
Dim Rep_Country_DataTable As New System.Data.DataTable
With DomainCountry_DataTable.Columns
.Add("REP", GetType(String))
.Add("COUNTRY", GetType(String))
End With
Dim Rep_Country_Group As IEnumerable(Of System.Data.DataRow) = (From Data_Row As System.Data.DataRow In Export_DataTable.Select("REP IS NOT NULL").AsEnumerable
Group Data_Row By Rep = Data_Row.Field(Of String)("REP"),
Country = Data_Row.Field(Of String)("COUNTRY") Into Group
Select New With {.Rep = Rep,
.Country = Country}).Select(Function(new_row)
Dim New_DataRow As System.Data.DataRow = DomainCountry_DataTable.NewRow()
New_DataRow("REP") = new_row.Rep
New_DataRow("COUNTRY") = new_row.Country
Return New_DataRow
End Function)

Related

SQL Aggregation keeping non aggregated columns from separate tables in VB.NET

I am utilizing VB.NET to pull data from a database via an SQLDataAdapter, place it into a DataSet, and then display it in a DataGridView. This all works fine but I need to Group the data by the EquipmentName column and then display only the Max StateChangeID of the group while still display the non-aggregated fields as well (EquipmentStateName etc...). I also know how to create the query that selects just EquipmentName and StateChangeID wile grouping and aggregating but getting the data from both is stumping me.
Initially ask this as a VB.NET question thinking there may be a way to pull two seperate querys and then combine them but I never could figure that out. I was advised to amend the question to focus on SQL so I have.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myConnection As SqlConnection
Dim myCconnectionString As String = "Server=SCDCMMSSQL02;Database=CMMS_PROD;Trusted_Connection=yes;"
Dim mySqlAdapter As SqlDataAdapter
Dim myDS As New DataSet
myConnection = New SqlConnection(myCconnectionString)
myConnection.Open()
mySqlAdapter = New SqlDataAdapter("
SELECT
RTP.vwt_EquipmentStateChange.EquipmentStateChangeID,
RTP.vwt_Equipment.EquipmentName,
RTP.vwt_EquipmentState.EquipmentStateName,
RTP.vwt_EquipmentStateChange.Comments,
RTP.vwt_EquipmentStateChange.LastUpdatedBy,
RTP.vwt_EquipmentStateChange.LastUpdated
FROM
RTP.vwt_EquipmentStateChange
LEFT OUTER JOIN
RTP.vwt_EquipmentState
ON RTP.vwt_EquipmentStateChange.EquipmentStateID = RTP.vwt_EquipmentState.EquipmentStateID
LEFT OUTER JOIN
RTP.vwt_Equipment
ON RTP.vwt_EquipmentStateChange.EquipmentID = RTP.vwt_Equipment.EquipmentID
WHERE
(RTP.vwt_EquipmentStateChange.CreatedDate > DATEADD(WEEK,-4,GETDATE()) )
AND
(RTP.vwt_EquipmentStateChange.Comments NOT LIKE '%Cluster%')
ORDER BY
RTP.vwt_Equipment.EquipmentName ASC", myConnection)
'Reading from DB to DataSet and displaying by data grid
mySqlAdapter.Fill(myDS, "EXEC")
DataGridView1.DataSource = myDS
DataGridView1.DataMember = "EXEC"
myConnection.Close()
myConnection.Dispose()
End Sub
What would be the best way to accomplish this. Should I do it within the initial SQL (Which I cant figure out). Should I manipulate it while it is in the DataSet. Should I attempt accomplish the Group By / Aggregation using LINQ (Which I would need to learn and would).
Any pointers would be appreciated!

count the specific record from access in vb.net

So i am making a voting program but i am stuck right now.
I have searched for solutions and i have followed them precisely but still no result.
Basically i want to count the total occurrence for each specific record from access in visual basic.
For example i have the candidate number 1 voted by three persons and candidate 2 by 7 persons, i want to show this voting result in a textbox but somehow it always shows me the wrong number
So here is my code:
Dim TotalVotes As Integer
myCommand = New OleDbCommand("SELECT CandidateNumber, COUNT (*) FROM Student_Voting GROUP BY CandidateNumber", dbconn)
TotalVotes = myCommand.ExecuteScalar
NovTextBox.Text = TotalVotes
myCommand.Dispose()
myReader.Close()
This query here gives a result of the first candidate number not the total votes for selected candidate number:
SELECT CandidateNumber, COUNT (*) FROM Student_Voting GROUP BY CandidateNumber
I have tried this too but still wrong result:
SELECT COUNT(CandidateNumber) AS NoVotes FROM Student_Voting GROUP BY CandidateNumber
I don't know what's the problem here, it's suppose to be simple but yet.
If anyone could help i'd very much appreciate it.
Thanks in advance
First of all, the initial query you're running would return more than one record if you had more than one candidate. ExecuteScaler returns only the first column of the first row.
The question is, do you want all of the records or do you just want one person's record? If you just want one person's record you'll need add a WHERE clause to your sql statement to specify on that candidate.
If you want all of the records it would look something like this:
Using myCommand = New OleDbCommand("SELECT CandidateNumber, COUNT (*) AS CountValue FROM Student_Voting GROUP BY CandidateNumber", dbconn)
Using dr = myCommand.ExecuteReader
' Loops over all the canidate counts one by one.
While dr.Read
Dim totalVotes As Integer = CInt(dr("CountValue"))
Dim candidateNumber As String = dr("CandidateNumber")
End While
End Using
End Using
If you want only one record then you can use ExecuteScaler something like this:
Using myCommand = New OleDbCommand("SELECT COUNT (*) AS CountValue FROM Student_Voting WHERE CandidateNumber = #CandidateNumber GROUP BY CandidateNumber", dbconn)
myCommand.Parameters.Add("#CandidateNumber", OleDbType.VarChar).Value = "1"
Dim totalVotes = CInt(myCommand.ExecuteScalar)
End Using
I don't know the actual types in your database so you would need to tweak the OleDbType to fit your table setup and perhaps some of the casts.

Filtering SQL data into multiple DataTables in a single DataSet

This should be simple, but it's escaping me right now as I have not written in VB in over a decade.
I have a stored procedure that gets a list of students and their assigned homeroom teacher.
Very basic - just the three columns: FirstName, LastName, Teacher.
What I need is to load the data into a DataSet where each Teacher has their own DataTable filled with the students assigned to them.
Sample data:
So in the example above, I would end up with 3 DataTables named Adams, Taggert and Dublin, each populated with the students associated with them all in a single DataSet in such a way that I could call the data with:
For Each dr As DataRow In ds.Tables("Taggert").Rows
' Do something with dr("FirstName").ToString
Next
Any help would be appreciated.
I ultimately used elements from both answers to find a solution. I ended up using DataViews to create the tables, and added them into the new DataSet. It works perfectly. It iterates through every record, but for the few hundred students it handles, it's actually quite
efficient. Thanks for the comments.
For Each row As DataRow In ds.Tables(0).Rows
Dim Teacher As String = row("Teacher").ToString()
If Not dsOutput.Tables.Contains(Teacher) Then
Dim dvStudents = ds.Tables(0).DefaultView
dvStudents.RowFilter = "Teacher = '" & Teacher & "'"
Dim subTable As New DataTable(Teacher)
subTable = dvStudents.ToTable(Teacher)
dsOutput.Tables.Add(subTable)
End If
Next
old_datatable with all teachers , i will declare this but you use your own
Dim old_datatable As New DataTable
Dim new_dataset As New DataSet
For Each row As DataRow In old_datatable.Rows
Dim teacher As String = row("Teacher")
If new_dataset.Tables.Contains(teacher) = False Then
Dim new_datatable As New DataTable
new_dataset.Tables.Add(new_datatable)
End If
new_dataset.Tables(teacher).Rows.Add(row)
Next
For Each dr As DataRow In new_dataset.Tables("Taggert").Rows
' Do something with dr("FirstName").ToString
Next

Creating datatable from 2 datatables created at runtime VB.net

I have a pretty long code which creates two datatables and fills them with data at runtime. And i need to create one table, but not the way merge does it but like adding columns from one datatable as new columns(but filled with data) to the other one. Best example i can thing of is Join in SQL but i will try to draw some example. I can not put my code here as i said it't too long.
Example:
(only column names but imagine that under each |something| is a lot of rows)
Table1:
Date|AA|AA2|AA3|AA4|AA5|AA6|
Table2:
Date|BB|BB2|BB3|BB4|BB5|BB6|
Result:
Date|AA|AA2|AA3|AA4|AA5|AA6|BB|BB2|BB3|BB4|BB5|BB6|
The DataTable.Merge method is perfectly capable of yielding your desired result. As your two tables have only one column in common Date, I am assuming that it is PrimaryKey of at least Table 1.
Dim dt1 As New DataTable
Dim pk As DataColumn = dt1.Columns.Add("Date", GetType(DateTime))
dt1.PrimaryKey = {pk}
dt1.Columns.Add("C1")
dt1.Columns.Add("C2")
dt1.Rows.Add(#1/1/2018#, "c1", "c2")
Dim dt2 As New DataTable
Dim pk2 As DataColumn = dt2.Columns.Add("Date", GetType(DateTime))
dt2.Columns.Add("C3")
dt2.Columns.Add("C4")
dt2.Rows.Add(#1/1/2018#, "c3", "c4")
dt2.Rows.Add(#1/2/2018#, "c3a", "c4a")
Dim dt3 As DataTable = dt1.Copy
dt3.Merge(dt2)
DataGridView1.DataSource = dt3
This code yield this result:

Use Select on Datatable/ Dataset

I'm trying to get data from both Tables, where Usage.ArticleId equals Article.idArticle. Below are my Tables.
I load the Dataset and Datatable like that:
DataSet1 = CType(Me.FindResource("DataSet1"),
KleinteilContainerVerwaltung.DataSet1)
DataSet1.ReadXml(XMLPath)
Dim article As DataTable = DataSet1.Article
Dim usage As DataTable = DataSet1.Usage
Below is my attempt using LINQ. But the Select doesn't work.
Dim queryResults = From art In article
Group Join use In usage On
art.Field(Of Int32)("idArticle") Equals use.Field(Of Int32)("ArticleId")
Into _list = Group
Select art.Field(Of Int32)("Article")
And is there a way to use art.idArticle instead of art.Field(Of Int32)("idArticle")? And are there other ways instead of using LINQ?