DataTable.Rows.Find error: "Table doesn't have a primary key." [duplicate] - vb.net

This question already has an answer here:
Table doesn't have a primary key
(1 answer)
Closed 9 years ago.
I can't search my datatable. It keeps repeating the same error "table doesn't have a primary key." and I don't know what to do. I already added the .FillSchema, but it still won't work. I'm using Visual Basic.
Dim con As New OleDb.OleDbConnection
Dim da As New OleDb.OleDbDataAdapter
Dim ds As New DataSet
Dim sql As String
Dim pass As Integer
Dim cmd As New OleDb.OleDbCommand
Dim dr As OleDb.OleDbDataReader
Dim dRow As DataRow
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Drug Emporium.accdb"
con.Open()
cmd.CommandText = "Select * From Inventory"
cmd.CommandType = CommandType.Text
cmd.Connection = con
sql = "Select * From Inventory"
dr = cmd.ExecuteReader()
da = New OleDb.OleDbDataAdapter(sql, con)
da.FillSchema(ds, SchemaType.Source, "Drug Emprorium")
da.Fill(ds, "Drug Emporium")
Dim cb As New OleDb.OleDbCommandBuilder(da)
dRow = ds.Tables("Drug Emporium").Rows.Find(intItemNum)
dRow.Delete()
con.Close()
I tried this but it still didn't work. It now gives a null reference exception on the Delete()
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Drug Emporium.accdb"
con.Open()
cmd.CommandText = "Select * From Inventory"
cmd.CommandType = CommandType.Text
cmd.Connection = con
sql = "Select * From Inventory"
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "Drug Emporium")
da.FillSchema(ds, SchemaType.Source, "Drug Emprorium")
Dim cb As New OleDb.OleDbCommandBuilder(da)
ds.Tables("Drug Emporium").PrimaryKey = New DataColumn() {ds.Tables("Drug Emporium").Columns("InventoryNumber")}
dRow = ds.Tables("Drug Emporium").Rows.Find(intItemNum)
dRow.Delete()
con.Close()

Your Problem is in the Table structure. You should normally show the DDL (SQL to create the table), but I understand it is uncommon with Access.
Anyway, I suspect your error happens in the delete: if you want to modify an resultset some Drivers need a primary key in the Table (and the selected colums) in order to be able to sent a clear modification operation back to the DB.

Related

DataSet update error requires InsertCommand

Trying to add a row to an Access 2010 database with VB 2013. Everything seems to work until the UPDATE statement when I get this error:
Update requires a valid InsertCommand when passed DataRow collection with new rows.
My code is:
Dim sqlConnection As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\CLI_CRVM.accdb")
Dim cmd As New System.Data.OleDb.OleDbCommand()
Dim ds As New DataSet1()
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "SELECT * FROM [extract] ;"
cmd.Connection = sqlConnection
sqlConnection.Open()
Dim da = New OleDb.OleDbDataAdapter(cmd.CommandText, sqlConnection)
da.Fill(ds, "extract")
ds.Clear()
Dim newExtractRow As DataRow = ds.Tables("extract").NewRow()
newExtractRow("Field1") = "ABC123"
ds.Tables("Extract").Rows.Add(newExtractRow)
da.Update(ds, "Extract")
sqlConnection.Close()
Everything I've found so far seems to reference an SQL database, not OleDb connection.
You can probably use an OleDbCommandBuilder, like so
' your existing OleDbDataAdapter
Dim da = New OleDb.OleDbDataAdapter(cmd.CommandText, sqlConnection)
' add the following lines:
Dim cb = New OleDbCommandBuilder(da)
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
For details, see
OleDbCommandBuilder Class
Working Example
For an Access table named extract with fields
ID - AutoNumber, Primary Key
Field1 - Text(255)
and data
ID Field1
-- -------
1 TEST999
the following VB.NET code will insert a second row into the table in the Access database
Using con As New OleDbConnection
con.ConnectionString =
"Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=C:\Users\Public\Database1.accdb;"
con.Open()
Using da As New OleDbDataAdapter("SELECT * FROM [extract]", con)
Dim cb = New OleDbCommandBuilder(da)
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
Dim dt = New DataTable
da.Fill(dt)
Dim dr As DataRow = dt.NewRow
dr("Field1") = "ABC123"
dt.Rows.Add(dr)
da.Update(dt)
End Using
con.Close()
End Using
with the result
ID Field1
-- -------
1 TEST999
2 ABC123
The OleDbCommandBuilder object automatically (and invisibly) creates the INSERT, UPDATE, and DELETE commands based on the SELECT command that was supplied when the OleDbDataAdapter object was created.
You need to set the InsertCommand property
Dim da = New OleDb.OleDbDataAdapter(cmd.CommandText, sqlConnection)
da.InsertCommand = cmd
da.Fill(ds, "extract")
More info here

VB.net | how can i turn an access db record in to a tabcontrol add tabpage?

I have a question, I want to add a TabPage to my TabControl from an access record? I think it's something along these lines but it didn't work:
Dim con As OleDbConnection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & My.Application.Info.DirectoryPath.ToString() & "\data\testing.Accdb;Persist Security Info=False;")
con.Open()
Dim constr As String = "SELECT ProductType, Discription FROM TblProductType"
Dim cmd As OleDbCommand = New OleDbCommand(constr, con)
Dim da As OleDbDataAdapter = New OleDbDataAdapter(cmd)
Dim ds As DataSet = New DataSet()
da.Fill(ds, "TblProductType")
Me.TabControl1.TabPages.Add("Discription")
con.Close()
You have to iterate over the row collection of the table:
Using cmd As New OleDbCommand("SELECT ProductType, Discription FROM TblProductType", con)
Using rdr As OleDbDataReader = cmd.ExecuteReader
While rdr.Read
TabControl1.TabPages.Add(rdr("Discription").ToString)
End While
End Using
End Using
Of course, this only gives you an empty TabPage for every record and in it's current implementation, you don't have any reference to the record anymore. That ProductType, if it's unique, should be used somewhere, too.

How to call a query from MS Access 2010 (.accdb) within VB.Net 2010?

I have this code that populates a datagridview with data from ms access:
Dim con As New OleDbConnection
Dim ds As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim Sql As String
Sql = "SELECT * FROM myTable WHERE case_no=?"
Try
con.ConnectionString = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Sample.accdb;Persist Security Info=True;Jet OLEDB:Database Password=dbadmin2010"
con.Open()
Dim cmd As OleDbCommand = New OleDbCommand(Sql, con)
da.SelectCommand = cmd
cmd.Parameters.AddWithValue("case_no", case_no)
Dim ds As DataSet = New DataSet
da.Fill(ds, "Case Info")
DataGridView1.DataSource = ds.Tables("Case Info")
Catch ex As Exception
MsgBox(ex.Message)
End Try
Now I had just finished creating a query from design view within MS Access itself, is there a way to call that query and retrieve the results to my datagridview?
Just use the query name and set the command type, for example, in addition to what you already have, you can use the following notes:
Try
con.ConnectionString = enter_connection_string_here
con.Open()
cmd.Connection = con
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "NameOfQuery"
da.SelectCommand = cmd
cmd.Parameters.AddWithValue("case_no", case_no)
da.Fill(ds, "Case Info")

VB.NET error adding a record to database

I'm using the code from http://homeandlearn.co.uk/NET/nets12p9.html for adding a record to the database.
It says when using a commandbuilder I should not get the error message:
Update requires a valid InsertCommand when passed DataRow collection with new rows.
However when I do the update I still get the error message. How can I fix this?
This is my code:
Dim dbProv As String
Dim dbSource As String
Dim con As New OleDb.OleDbConnection
Dim ds As New DataSet
Dim da As New OleDb.OleDbDataAdapter
Dim sql As String
Dim Command As OleDb.OleDbCommand
Dim dr As DataRow
Dim cb As New OleDb.OleDbCommandBuilder(da)
sql = "SELECT * FROM Cliënten"
dbProv = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = [mydatabase]"
con.ConnectionString = dbProv & dbSource
con.Open()
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "Cliënten")
dr = ds.Tables("Cliënten").NewRow()
dr.Item("Field1") = TextBox1.Text
dr.Item("Field2") = TextBox2.Text
ds.Tables("Cliënten").Rows.Add(dr)
da.Update(ds, "Cliënten")
MsgBox("New Record added to the Database")
con.Close()
To make da.Update() works, you must assign a valid InsertCommand, then the DataAdapter will execute it automatically. Here an example:
da.InsertCommand = New OleDb.OleDbCommand("INTERT INTO Cliënten (Field1, Field2) VALUES (#field1, #field2)")
da.InsertCommand.Parameters.Add(New OleDb.OleDbParameter("#field1", OleDb.OleDbType.VarChar, 0, "Field1"))
da.InsertCommand.Parameters.Add(New OleDb.OleDbParameter("#field2", OleDb.OleDbType.VarChar, 0, "Field2"))
da.Update(ds, "Cliënten")
WARNING: I've presumed you are using OleDb.OleDbType.VarChar for Field1 and Field2; if not you have to replace it with correct DB data format.
From what I read here it seems as though CommandBuilder should auto-generate the INSERT command for you based on the SELECT.
I think you are creating your CommandBuilder object too early - ie Before you specify the SELECT command / initialise Connection etc.
Perhaps this may work better...
Dim dbProv As String
Dim dbSource As String
Dim con As New OleDb.OleDbConnection
Dim ds As New DataSet
Dim da As New OleDb.OleDbDataAdapter
Dim sql As String
Dim Command As OleDb.OleDbCommand
Dim dr As DataRow
sql = "SELECT * FROM Cliënten" 'Consider specifying columns
'individually rather than using *
dbProv = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
dbSource = "Data Source = [mydatabase]"
con.ConnectionString = dbProv & dbSource
con.Open()
da = New OleDb.OleDbDataAdapter(sql, con)
Dim cb As New OleDb.OleDbCommandBuilder(da) 'Init CommandBuilder here
cb.RefreshSchema() 'This may also help
da.Fill(ds, "Cliënten")
dr = ds.Tables("Cliënten").NewRow()
dr.Item("Field1") = TextBox1.Text
dr.Item("Field2") = TextBox2.Text
ds.Tables("Cliënten").Rows.Add(dr)
da.Update(ds, "Cliënten")
MsgBox("New Record added to the Database")
con.Close()

How to determine the id of a data in vb.net?

I'm currently working on an ms access database in vb.net.
And I need a code that can determine which data I am updating in the database. Because when I try to update the data, the previous data is being cloned and it will generate two data(the updated and the previous data), and the program will also generate a random id number for the updated data, which is not good.
Here is my code for the update button:
'update
Dim cb As New OleDb.OleDbCommandBuilder(da)
ds.Tables("GH").Rows(INC).Item(1) = TextBox13.Text
ds.Tables("GH").Rows(INC).Item(2) = TextBox14.Text
ds.Tables("GH").Rows(INC).Item(3) = TextBox15.Text
da.Update(ds, "GH")
MsgBox("Data updated")
My code for form load:
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\ACCESS DATABASE\search.mdb"
con.Open()
sql = "SELECT * FROM GH"
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "GH")
con.Close()
I'm using system.data.oledb namespace
Here are my declarations:
Dim cmd As OleDbCommand
Dim cn As OleDbConnection
Dim dr As OleDbDataReader
Dim ds As New DataSet
Dim con As New OleDb.OleDbConnection
Dim da As OleDb.OleDbDataAdapter
Your question is not clear to me at all, but if you want to find the last ID of an insert, you would usually check the results of "SELECT ##IDENTITY" immediately after the record is inserted.