How to get linked table details in dataview? - vb.net

I have two linked tables like this
Here myDataset.cat_table is already filled at form load,used for other purpose, and me getting data from myDataset.prod_table bydataview by the below script.
Dim myDataView As New DataView
myDataView.Table = Me.myDataSet.prod_table
For Each myRow As DataRow In myDataView.ToTable.Rows
Dim myId as integer
Dim myCatid as integer
Dim myCatName as object
Dim myprodDetails as object
myId = myRow("id")
myCatid = myRow("catid")
myCatName = ?
myprodDetails = myRow("details")
Next
Here in Dataview method, is it possible to get "myCatName" from the linked table? Me not looking for a separate query (by left join), because again i have to load query. And "Merge table" works for identical tables only i guess, So searching for other possible logics
Yours faithfully
Murulimadhav

Hopefully, these two tables are not just data sets but if they can possibly be real database tables from sql, my suggestion is that you can easily manipulate the data of linked tables by SQL query. P.S - Import the following references.
Imports System.Data.SqlClient
Private strConn As String
Private sqlConn As New SqlConnection
Private sqlcmd As New SqlCommand
Private Sub getdatatable()
strConn = "Data Source= Server_Name;Initial Catalog= DB_Name;User ID= User_name;Password= Password"
sqlConn = New SqlConnection(strConn)
sqlConn.Open()
Dim sqlcmd As New SqlCommand("SELECT p.id, c.catname, p.products, p.details FROM cat_table c, prod_table p WHERE c.catid = p.catid", sqlConn)
Dim myreader As SqlDataReader
myreader = sqlcmd.ExecuteReader
myreader.Read()
Do While myreader.HasRows
'datagridview.Rows.Add(myreader.Item("id").ToString, myreader.Item("catname").ToString, . . . and so on as your desire table columns that you want to show on datagridview)
Do While myreader.Read
'datagridview.Rows.Add(myreader.Item("id").ToString, myreader.Item("catname").ToString, . . . same coding as above Do while looping)
Loop
myreader.NextResult()
Loop
End Sub
Trigger this method on Form_load or button click or whatever as you like. Before you do this type of showing in datagridview, you must pre-define the respective columns first in datagridview. I hope I will help you a little bit.

Dim myDataView As New DataView
myDataView.Table = Me.myDataSet.prod_table
For Each myRow As DataRow In myDataView.ToTable.Rows
Dim myId As Integer
Dim myCatid As Integer
Dim myCatName As Object
Dim myprodDetails As Object
myId = myRow("id")
myCatid = myRow("catid")
Dim myCatPosi As Integer = cat_tableBindingSource.Find("id", myCatid)
If myCatPosi >= 0 Then
cat_tableBindingSourceBindingSource.Position = myCatPosi
myCatName = cat_tableBindingSourceBindingSource.Current("title").ToString
End If
myprodDetails = myRow("details")
Next

Related

vb.net Loading Images from Access Database to DataTable?

So I have a MS Access Database with 1 table (Records) and 2 fields in it ("RecordID" (Number), which is the primary key, and "LowRes" (OLE Object) which is a low Resolution image). There are about 100 records.
I/m trying to load the Access Table into a DataTable (ID_Table) in VB.net.
Code so far:
Dim cnString As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=SBS2257_ID.accdb;"
Dim theQuery As String = "SELECT [RecordID], [LowRes] FROM [Records];"
Using CN As New OleDbConnection(cnString)
Dim command As New OleDbCommand(theQuery, CN)
Using objDataAdapter = New OleDbDataAdapter(command)
Dim ID_Table As New DataTable
CN.Open()
Dim pictureData As Byte() = DirectCast(command.ExecuteScalar(), Byte())
Dim picture As Image = Nothing
Using stream As New IO.MemoryStream(pictureData)
picture = Image.FromStream(stream)
objDataAdapter.Fill(ID_Table)
End Using
End Using
End Using
However the "DirectCast" command fails when I tell it to look at more then 1 field in my SQL statement with a datatype mismatch (if I just do [LowRes] it does not throw a error). However, I get stuck again when trying to apply the result to the table via the objDataAdapter, it doesnt fill the table with anything? I also notice that "picture" only contains the first image in the database.
I could put this database query in a function using "WHERE RECORDID=..." and loop it manually building the table returning "picture" each time, but Id like to avoid running a function 100 times, esp one that access a database.
Is it possible to read the whole database that contains images and just load it directly into a Datatable in one big swoop?
EDIT: So I got this to work:
Dim strConnection As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=SBS2257_ID.accdb;"
Dim strSQL As String = "SELECT [RecordID], [LowRes] FROM [Records];"
Using objConnection = New OleDbConnection(strConnection)
Using objCommand = New OleDbCommand(strSQL, objConnection)
Using objDataAdapter = New OleDbDataAdapter(objCommand)
Dim objDataTable As New DataTable("IDs")
objDataAdapter.Fill(objDataTable)
Return objDataTable
End Using
End Using
End Using
how ever when I go to view row 0, col 1 which should be the first LowRes image via a .ToString Useing this code:
Private Sub PrintValues(ByVal table As DataTable)
For Each row As DataRow In table.Rows
For Each col As DataColumn In table.Columns
MsgBox(row(col).ToString())
Next col
Next row
End Sub
It just displays "System.Byte[]". It knows its a Byte datatype, but how do I display that in a picturebox?
The ExecuteScalar() executes the query, and returns the first column of the first row in the result set returned by the query.
as your query is
Dim theQuery As String = "SELECT [RecordID], [LowRes] FROM [Records];"
the first column is RecordID which is not a Byte().
you can change your query as following:
Dim theQuery As String = "SELECT [LowRes] FROM [Records];"
or you have to use other methods to get data from the database
Dim strSql As String = "SELECT [RecordID], [LowRes] FROM [Records]"
Dim dtb As New DataTable
Using cnn As New OleDbConnection(connectionString)
cnn.Open()
Using dad As New OleDbDataAdapter(strSql, cnn)
dad.Fill(dtb)
End Using
cnn.Close()
End Using

How to store database resultset?

I want to know which is the best way to store database value in vb.net, For example, I've this code:
Dim conn As MySqlConnection = Connection() 'Return a connection obj
conn.Open()
Dim transaction = conn.BeginTransaction
Dim cmd = New MySqlCommand("SELECT * FROM tb ORDER BY ID")
Dim ResultSet = Cmd.ExecuteReader
If ResultSet.HasRows Then
Do While ResultSet.Read
'Here the value should be store
Loop
End if
How you can see I take all table from my database, now I want store each records in a structure that allow me to access it like the table. An array is good for do this? A list? Which is the best way?
There is no best way. You have different options. For example:
As an option you can use a DataTable
Also you can store values in a generic List(Of T).
If you prefer working with DataTable it will be more simple to use DataAdapter to fill the DataTable. This way you can also create your List(Of T) from your DataTable.
Example of Using DataDapter to fill DataTable
Dim Connection = "Connection String"
Dim Command = "SELECT * FROM Category"
Dim Adapter = New SqlDataAdapter(Command, Connection)
Dim Table = New DataTable()
Adapter.Fill(Table)
This way the DataTable will have columns with name of columns in your result set.
Also you can fill your data in a List(Of T) using the DataTable this way:
Dim ListOfCategory = Table.Rows.Cast(Of DataRow) _
.Select(Function(Row)
Return New Category With
{
.Id = Row.Field(Of Integer)("Id"),
.Name = Row.Field(Of String)("Name")
}
End Function).ToList()
Note
If can change the way you are writing your application, you can use Entity Framework as a good option to work with data.

Dynamically add listbox columns based on columns in an Access Database?

I would like to do a populate a column in my listbox for each field in my Access Database.
Right now I have to manually add the field:
QUERBOX.Columns.Add("Requestor Name", 200, HorizontalAlignment.Left)
How can I adapt my code below to automatically add columns each time I run the sub?
Dim queryString As String = "SELECT * FROM Table1;"
Dim connection As OleDbConnection
Dim command As OleDbCommand
Dim data_reader As OleDbDataReader
querbox.clear
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\apt.accdb")
connection.Open()
command = New OleDbCommand(queryString, connection)
data_reader = Command.ExecuteReader
If data_reader.HasRows Then
While data_reader.Read
Dim newitem As New ListViewItem()
newitem.Text = data_reader.GetValue(0) 'first column
newitem.SubItems.Add(data_reader.GetValue(1)) 'second column
QUERBOX.Items.Add(newitem)
End While
End If
As Plutonix suggested in comments, a DataGridView would probably be best suited, but for the sake of answering the question here's how I've done something similar:
connection.Open()
'' Fill a DataTable with all of the Column schema for the given table of 'Table1'
Dim schemaTable As DataTable = connection.GetSchema("Columns", New String() {Nothing, Nothing, "Table1", Nothing})
'' Iterate through each column in the Schema Table
For i = 0 To schemaTable.Rows.Count - 1 Step 1
'' Declare a new item for the list
Dim newItem As New ListViewItem()
newItem.Text = schemaTable.Rows(i)!COLUMN_NAME.ToString()
newItem.SubItems.Add(schemaTable.Rows(i)!COLUMN_NAME.ToString()
'' Add new item to the interface
QUERBOX.Items.Add(newItem)
Next
connection.Close()
This has helped me in projects where the user is familiar with the database structure and may need to select the fieldname as part of the business logic. For example, allowing someone with little database knowledge to standardize the records within a given field.

Joining many-to-many DataTables in VB.Net

I have 2 data sources from different source types, like:
Dim connSql As String = "Data Source=sql_src;Initial Catalog=my_db;Persist Security Info=True;User ID=usr;Password=pwd;"
Dim connOle As String = "Provider=IBMDA400;Data source=src;User Id=usr;Password=pwd"
dim qrySql as String = "Select uniqueID, name From tblSql"
dim qryOle as String = "Select name, ID From tblOle"
I place them into DataTables using functions like this (mostly for reference):
Public Shared Function sqlQryDT(qry As String, conn As String) As DataTable
Dim dt As New DataTable
Dim sqlconn As New SqlClient.SqlConnection(conn)
sqlconn.Open()
Dim adapter As New SqlClient.SqlDataAdapter(qry, sqlconn)
Try
adapter.Fill(dt)
Catch ex As Exception
Finally
sqlconn.Close()
End Try
Return dt
End Function
Public Shared Function oleQryDT(qry As String, conn As String) As DataTable
Dim dt As New DataTable
Dim cn As New OleDb.OleDbConnection(conn)
Dim cmd As New OleDb.OleDbCommand("", cn)
Dim da As New OleDb.OleDbDataAdapter(cmd)
cmd.CommandText = qry
Try
cn.Open()
da.Fill(dt)
Catch ex As Exception
Finally
cn.Close()
End Try
Return dt
End Function
Dim dtSql as DataTable = sqlQryDT(qrySql, connSQL)
Dim dtOle as DataTable = oleQryDT(qryOle , connOle)
My goal is to have a DataTable consisting of uniqueID,name,ID
(Edit) If I could do an SQL query it would look like SELECT * FROM dtSql JOIN dtOle ON dtSql.name = dtOle.name
I have tried using a DataRelation by placing the tables into a DataSet and adding a relationship on name, but since names may not be unique, this fails.
I have also tried using LINQ, but that always returns IEnumerable(System.Collections.Generic) and I can't find an easy way to place the contents into a DataTable, except by iterating through every item. And, the code is messy when there are a large number of columns.
I feel like there should be a way to do this without using a For Each loop
I looked at these question, but they didn't fully help me.
How to inner join two already filled DataTables in VB.NET
Merging 2 data tables in vb.net

Conversion error in vb.net?

I am puzzled by why it does not retrieve the data and keep saying i have a error "InvalidCastException", i am currently doing these in compact framework and is totally new to it, i searched around looking for a way to get data into a listview base on what little i know about java .
these are my creation of table and inserting during formload
Dim createTable3 As SqlCeCommand = connection.CreateCommand
createTable3.CommandText = "CREATE TABLE product(product_id int IDENTITY(0,1) PRIMARY KEY,product_name nvarchar(50),bought_price float,sales_price float)"
connection.Open()
createTable3.ExecuteNonQuery()
Dim insertCmd2 As SqlCeCommand = connection.CreateCommand
insertCmd2.CommandText = "INSERT INTO product(product_name,bought_price)Values('Food',1.00)"
insertCmd2.ExecuteNonQuery()
Dim insertCmd3 As SqlCeCommand = connection.CreateCommand
insertCmd3.CommandText = "INSERT INTO product(product_name,bought_price)Values('Orange',1.50)"
insertCmd3.ExecuteNonQuery()
Dim insertCmd4 As SqlCeCommand = connection.CreateCommand
insertCmd4.CommandText = "INSERT INTO product(product_name,bought_price)Values('Apple',3.00)"
insertCmd4.ExecuteNonQuery()
Dim insertCmd5 As SqlCeCommand = connection.CreateCommand
insertCmd5.CommandText = "INSERT INTO product(product_name,bought_price)Values('Fruit',2.00)"
insertCmd5.ExecuteNonQuery()
connection.Close()
this is a code for a get info button
Dim itmListItem As ListViewItem
Dim shtFieldCntr As Short
Dim loopCmd As SqlCeCommand = connection.CreateCommand
loopCmd.CommandText = "SELECT * FROM product"
connection.Open()
Dim dr As SqlCeDataReader = loopCmd.ExecuteReader
Do While dr.Read
itmListItem = New ListViewItem()
If dr.IsDBNull(dr(0)) Then
itmListItem.Text = ""
Else
itmListItem.Text = dr(0)
End If
For shtFieldCntr = 1 To dr.FieldCount()
If dr.IsDBNull(shtFieldCntr) Then
itmListItem.SubItems.Add("")
Else
itmListItem.SubItems.Add(dr.GetString(shtFieldCntr)) ' error this line
End If
Next shtFieldCntr
lvProduct.Items.Add(itmListItem)
Loop
connection.Close()
picture
If you review the documentation for SqlCeDataReader.GetString, it mentions under "Remarks" that:
No conversions are performed;
therefore, the data retrieved must
already be a string.
This will be why you're getting an InvalidCastException. None of your fields, except for product_name, are strings. What you need to do is something like:
itmListItem.SubItems.Add(Convert.ToString(dr.GetValue(shtFieldCntr)))
When you know what all the fields in a table are, it would make more sense to call them and then add them to SubItems explicitly i.e:
Dim productId As Int32 = dr.GetInt32(dr.GetOrdinal("product_id"))
Dim productName As String = dr.GetString(dr.GetOrdinal("product_name"))
itmListItems.SubItems.Add(productId)
itmListItems.SubItems.Add(productName)