VB.NET SQLClient Table Names are ambiguous - vb.net

Here is some simple sample code that demonstrates how I am getting results back from SQL Server:
Dim dtbTable As System.Data.DataTable
Dim sdaDataAdapter As New System.Data.SqlClient.SqlDataAdapter()
sdaDataAdapter = New System.Data.SqlClient.SqlDataAdapter("SELECT * FROM A; SELECT * FROM B", Connection)
dtbTable = New System.Data.DataTable()
dtbTable.Locale = System.Globalization.CultureInfo.InvariantCulture
sdaDataAdapter.Fill(dtbTable)
sdaDataAdapter = Nothing
objCommandBuilder = Nothing
In .Net, table A will come out TABLE and Table B will come out TABLE1... I want them to hold their real table names.
How do I get the real table names of the tables that come in from the SQL Query ? All the column names are correct, but the tables come out TABLE, TABLE1, TABLE2... I obviously know how to set them in my code or parse the table names and set them in code... I am wondering why .Net looses the table names in the first place and if there is a way for them to not be turned into ambiguous names.
Why would the writers of the SQLClient drivers not think we care about table names?
Any ideas from anyone on a way to get around this without having to set Table Name manually?

Here are two approaches - map the tables to DataTables and load the DataSet one table at a time w/desired name.
Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click
Dim Connection As New SqlConnection(OISConnectString)
Connection.Open()
Dim da As New System.Data.SqlClient.SqlDataAdapter("SELECT * FROM FIS..FIS_Log; SELECT * FROM FIS..FIS_Log_CA", Connection)
Dim ds As New DataSet
da.Fill(ds)
Debug.Print(ds.Tables(0).TableName) ' Table
Debug.Print(ds.Tables(1).TableName) ' Table1
Dim dtLog As DataTable = ds.Tables(0)
Dim dtLog_CA As DataTable = ds.Tables(1)
' work with DataTables by name
Stop
'reset
ds = Nothing
da = Nothing
ds = New DataSet()
da = New SqlDataAdapter("SELECT * FROM FIS..FIS_Log", Connection)
da.Fill(ds, "FIS_Log")
da = New SqlDataAdapter("SELECT * FROM FIS..FIS_Log_CA", Connection)
da.Fill(ds, "FIS_Log_CA")
Debug.Print(ds.Tables(0).TableName) ' Table
Debug.Print(ds.Tables(1).TableName) ' Table1
dtLog = ds.Tables("FIS_Log")
dtLog_CA = ds.Tables("FIS_Log")
Connection.Close()
End Sub
You might find TableAdapterManager useful depending on your platforms

Related

Why combo box is not loaded from join sql query

Dim cmd As New SqlCommand("SELECT MainDepartmentsTable.ID, FeesTable.ID,FeesTable.Particular,FeesTable.Fee from MainDepartmentsTable inner join SubDepartmentsTable on MainDepartmentsTable.ID = SubDepartmentsTable.MainDeptID inner join FeesTable on SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID WHERE FeesTable.ID = '" & TextDepartmentID.Text & "' ", con)
Dim DataAdopter = New SqlDataAdapter(cmd)
Dim dt As New DataTable
DataAdopter.Fill(dt)
Load_Deparments()
First you need to validate the user input.
Using blocks ensure that you connection and command are closed and disposed.
Parameters save your database from sql injection. I had to guess at the datatype.
Private ConStr As String = "Your connection string"
Private Sub OPCode()
Dim DeptID As Integer
If Not Integer.TryParse(TextDepartmentID.Text, DeptID) Then
MessageBox.Show("Please enter a valid department ID.")
Exit Sub
End If
Dim dt As New DataTable
Using con As New SqlConnection(ConStr),
cmd As New SqlCommand("SELECT MainDepartmentsTable.ID,
FeesTable.ID,
FeesTable.Particular,
FeesTable.Fee
from MainDepartmentsTable
inner join SubDepartmentsTable on
MainDepartmentsTable.ID = SubDepartmentsTable.MainDeptID
inner join FeesTable on
SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID
WHERE FeesTable.ID = #DepartmentID;", con)
cmd.Parameters.Add("#DepartmentID", SqlDbType.Int).Value = DeptID
con.Open()
dt.Load(cmd.ExecuteReader)
End Using
Load_Departments(dt)
End Sub
Private Sub Load_Departments(dt As DataTable)
ComboBox1.DataSource = dt
ComboBox1.DisplayMember = "Particular"
ComboBox1.ValueMember = "Fee"
End Sub
Let's simplify a bit:
Dim sql = "SELECT FeesTable.ID, CoNCAT(FeesTable.Particular, '-', FeesTable.Fee) as DisplayText
FROM
SubDepartmentsTable
inner join FeesTable on SubDepartmentsTable.MainDeptID = FeesTable.SubDepartmentID
WHERE SubDepartmentsTable.MainDeptID = #id"
Dim da As New SqlDataAdapter(sql, con)
da.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(TextDepartmentID.Text)) 'less worried about AWV with ints but read https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
Dim dt As New DataTable
da.Fill(dt)
'this part connects the data to the combo - it's the part you didn't show in your Q and what people are telling you is missing
yourCombo.DisplayMember = "DisplayText"
yourCombo.ValueMember = "ID"
yourCombo.DataSource = dt
This isn't intended to be a paste in fix for your problem; you've left out too much info from your question to know how to answer it exactly, so you're gonna have to modify this
Things you need to change:
The columns that are selected in the SQL - load one column you will show (I demonstrated how to combine two bits of info under one name of DisplayText) and one column for the backing value (ID)
The column that is filtered on in the where clause or the name of the text box TextDepartmentID - it seems odd to me that a Fee ID should be equal to a Department ID, so I've altered the SQL to retrieve the Fee details for a MainDepartmentID because I've assumed your textbox name is correct and that you intended to show the fees for a department via the subdepartments
Read the blog linked and perhaps choose adding a parameter in a different way
Change yourCombo to the name of your combobox
Change DisplayMember and ValueMember setting to match the names of the two columns your SQL query selects
You only need two columns if youre plumbing up a combo, but if you pass the datatable off somewhere you can add more

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.

OLEDB - select Count not working

Find below what I've done so far, but unfortunately it's not working.
Private BS as New BindingSource
Dim ds As New DataSet
' Make the Connection
Using con As New OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = Database1.mdb")
con.Open()
Dim Sql = "SELECT COUNT ([Eventname]) FROM Eventproposal"
Dim da = New OleDb.OleDbDataAdapter(Sql, con)
da.Fill(ds, "Eventproposal")
' Set the Binding Source
bs.DataSource = ds.Tables("Eventproposal")
con.Close()
End Using
TextBox1.DataBindings.Add("Text", bs, "")
Couple things, you should end all SQL Commands to MS Access with ;
Dim Sql = "SELECT COUNT ([Eventname]) FROM Eventproposal;"
And you did not name your column which will give you an error when you attempt to access it by name.
Dim Sql = "SELECT COUNT ([Eventname]) AS Eventname FROM Eventproposal;"
I believe it will give it a name but not what your thinking. Lastly, when you do your binding, you will have to reference the name of the field in the table.
TextBox1.DataBindings.Add("Text", bs, "Eventname")

OleDbDataAdapter Access not finding table

I've got a problem finding the data for one particular table. I've output the SQL statement and tested it in a query in Access and that query finds the relevant data, but in the code the dataset returns zero rows.
Private m_comm As OleDbCommand
Private m_SQL As String
Private m_ds As New DataSet
Private m_dt As New DataTable
Private m_da As OleDbDataAdapter
Private m_bd As OleDbCommandBuilder
' bit of code to connect to database
m_conn = ...
m_comm = New OleDbCommand
m_comm.Connection = m_conn
m_SQL = "SELECT * FROM [TableName];"
m_ds = New DataSet
m_dt = New DataTable
m_da = New OleDbDataAdapter(m_SQL, m_conn)
Dim n As Integer = m_da.Fill(m_ds)
At this point n = 0
This is the only table this happens with. The Table contains 1 row with two fields.
I've been trying to figure out what might be happening, but I need another set of eyes in case I'm missing the obvious. I have other tables with the same configuration and the SQL for them work so it's not the 1 row that is the problem....

Populate data from dataset and show in datagridview

I am working in VB.NET and I have a simple requirement:
I have added a MDB file to a DataSet and it contains 21 tables.
I have a DataGridView and a ComboBox on my form.
I was able to get the ComboBox populated with the table names available in the DataSet by iterating through dataset.Tables.
Now I want to the user to be able to select the table name from the ComboBox and then populate the contents of that table.
I tried the following code:
Datagridview1.DataSource = dataset1
Datagridview1.DataMember = dataset1.tables(combobox1.selecteditem)
Datagridview1.Refresh()
But I only got the column headers. Then I read that I need a TableAdapter to populate the DataSet with that table. But if I use the TableAdapter then I won't be able to populate the table in a generic way.
Currently if I have to populate TableA then I will have to create an instance of Dataset1TableAdapters.TableA and then use it's .Fill property to populate the table. I will also have to use "Dataset1TableAdapters.TableB`. Is there a generic method to populate any table in the DataSet?
The following worked for me:
Datagridview1.DataSource = dataset1.tables(combobox1.selecteditem)
C# but easily convertible to VB.Net (I suppose):
String connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""C:\test.mdb""";
String tableName = combobox1.SelectedItem.ToString();
String sqlSELECT = String.Format("select * from [{0}]", tableName);
System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter();
da.SelectCommand = new System.Data.OleDb.OleDbCommand(sqlSELECT, new System.Data.OleDb.OleDbConnection(connectionString));
DataGridView1.DataSource = dataSet1;
DataGridView1.DataMember = dataSet1.Tables(tableName);
da.Fill(dataSet1, tableName);
I was just sketching a proof that "it can be done in a generic way" to your problem, you should elaborate and maybe come with something more elegant (and safe).
Private Sub BindData()
With customersDataGridView
.AutoGenerateColumns = True
.DataSource = customersDataSet
.DataMember = "Customers"
End With
End Sub
Just to clarify this answer. For Future Reference.
Public Class Form1
Dim con As OleDbConnection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\test.accdb;")
Private Sub Button1_Click
Dim da As New OleDbDataAdapter
Dim table As String = ComboBox1.SelectedItem.ToString
Dim sql As String = String.Format("select * from [{0}]", table)
da.SelectCommand = New OleDbCommand(sql, con)
DataGridView1.DataSource = DataSet.Tables(table)
da.Fill(DataSet, table)
End Sub
End Class
Not trying to Ressurect, but i thought the working version of this VB Script should be posted.
I would like to point out that the dataset is held by Visual Studio, hence the strange source string.