I have to retrieve the Auto_Increment primary key (id) after inserting a new row in a mdb access database.
Having mdb file in the old Access 97 version too, I cannot use "SELECT ##Identity;", because it is not supported.
Besides, in a multi users environment I do not like the idea to use Max(ID).
Actually the only solution I have, it is to use the DAO as:
Dim db As Database 'Test Database
Dim rs As Recordset 'Test Table
...
rs.AddNew
id = rs!id
but I have to add a reference to the DAO COM DLL, while I would like to have a full managed .NET code.
Do you have any suggestion how to retrieve the Auto_Increment primary key (after inserting a new row) without using DAO or Max(ID)?
Here my code to add a new row:
Using oConn As New OleDbConnection(m_ConnString)
oConn.Open()
Using cmd As New OleDbCommand(sqlInsert, oConn)
cmd.ExecuteNonQuery()
End Using
End Using
Thank you.
If there is any other mandatory field in this table that has a unique index, you may query its value after your insertion with something like DFirst("ID", "tablename", "myfield = givenvalue"). If you're running in a transaction, use a recordset (perhaps the same as for the insertion) instead of DFirst.
Related
I use following pattern to work with SQL Server temp tables from .NET applications:
Open the connection
Create a temp table (only with ad hoc command!!!)
Write a lot of data into it via SqlBulkCopy
Perform a select/update with join to this temp table (this request can already be parameterized)
Close the connection
Using cn As New SqlConnection("Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;") : cn.Open()
Using cm As New SqlCommand("create table #T1(C1 int primary key, C2 int)", cn)
cm.ExecuteNonQuery()
End Using
Using bk As New SqlBulkCopy(cn)
bk.DestinationTableName = "#T1"
bk.WriteToServer(dataToWrite)
End Using
Using cm As New SqlCommand("update a set a.C2=b.C2 from SomeTable a join #T1 b on a.C1=b.C1 where a.C3=#PC3", cn)
cm.Parameters.Add("C2", SqlDbType.Int).Value = c3Value
cm.ExecuteNonQuery()
End Using
End Using
Unfortunately, I can't explicitly influence whether the “create temp table” as ad-hoc command runs.
Although the SqlCommand source code describes this behavior in comments (// Send over SQL Batch command if we are not a stored proc and have no parameters), but nothing is specified in the documentation.
Theoretically, the behavior of SqlCommand in future .NET versions can be changed, so that "create table #T..." will be packed into sp_executesql. Using temporary tables from .NET code will become impossible and the application will become inoperable.
Do I understand the problem correctly?
Can I remain assured that in future versions of .NET will still not package parameterless queries in sp_executesql?
I am having trouble updating my database table with datagridview, I've read some thread about the problem and nothing seem to work in my case. Here is the code i use when populating the datagridview.
Public Sub filldatagridserver(ByRef SQL As String, ByRef dg As DataGridView)
Dim myDataset As DataSet = New DataSet
myAdptr.SelectCommand = New SqlCommand(SQL, cnSQL)
myAdptr.Fill(myDataset)
dg.DataSource = myDataset.Tables(0)
dg.AutoResizeColumns()
myAdptr.Dispose()
myDataset.Dispose()
cnSQL.Close()
End Sub
then i call this sub procedure with the ff code:
Call filldatagridserver("SELECT * FROM tblQuarterCollection", dgQuarter)
i already used myAdptr.update but i keep getting error about table mapping etc. I also tried to quote out the dispose and close in that sub procedure but it still doesn't work.
is there anyway to properly populate the datagridview and update changes made to database. I think my last resort here would be looping thru each record the update the data according to current value in the datagridview. Please help.
try this :
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim addcmd as new sqlcommand("INSERT INTO TableName VALUES(#col1,#col2)",YourConnectionString)
addcmd.parameters.addwithvalue("#col1",txtCol1.text)
addcmd.parameters.addwithvalue("#col2",txtCol2.text)
addcmd.executenonQuery
End Sub
At last I managed to get my code working. I reviewed my database and reset the primary key and now it is working perfectly fine
If you call the Update passing also the name of the table then you need to add that name when you fill initially the DataSet
myAdptr.SelectCommand = New SqlCommand(SQL, cnSQL)
myAdptr.Fill(myDataset, "tblPayMTC")
Another important point to get the automatic update working is to have a primary key returned by the SELECT query otherwise you need to write your own commands for the UpdateCommand, InsertCommand and DeleteCommand of the SqlDataAdapter instance.
The primary key is a column in your table tblQuarterCollection that uniquely identifies your records (usually an ID column with Identity set to true) but it can be also a group of columns that taken togheter works as Primary Key.
While it is not mandatory to have a column with this property set, it is highly advisable to have one
I want to update my server database from my local database
Dim mycon As New SqlConnection(myserverConString)
Dim myAdapter As New SqlDataAdapter("SELECT * FROM MYTABLE", mycon)
Dim mybuilder As New SqlCommandBuilder(myAdapter)
myAdapter.UpdateCommand = mybuilder.GetUpdateCommand(True)
dim dt as datatable
'code to fill dt from my local db
'using select statement
For Each DR As DataRow In dt.Rows
DR.SetModified()
Next
dt.AcceptChanges()
myAdapter.Update(dt)
the problem is the used datatable in fact contain no changes
and the command builder updatecommand use the wrong "where"
I found the used update command is
UPDATE [MYTABLE] SET [COLUMN0] = #COLUMN0, [COLUMN1]=#COLUMN1 WHERE
([COLUMN0]=#Original_COLUMN0) AND ([COLUMN1]=#Original_COLUMN1))
COLUNM0 IS THE PRIMARY KEY
COLUMN1 IS THE UPDATED VALUE IN THE LOCAL DB,
AND I WANT TO UPDATE IT IN THE SERVER DB WHICH IS THE SAME SCHEMA.
COLUMN1 CAN'T used in "WHERE clause " as it is the changed value
and the dt doesn't have an original value for it.
My code doesn't give any errors,
but it also doesn't update anything.
If you are updating from your local DB why check the value of COLUMN1 in the WHERE clause? Just update all rows to the local COLUMN1 value.
Just use
UPDATE [MYTABLE]
SET [COLUMN1] = #COLUMN1
WHERE [COLUMN0] = #Original_COLUMN0
EDIT: You may well be better off adding a timestamp to your rows to make it easier for the SqlCommandBuilder to detect changes.
From The SQLCommandBuilder is way Better than its Reputation
The SQLCommandBuilder supports different ConflictOptions to detect
optimistic update conflicts:
OverwriteChanges (= no control) CompareAllSearchableValues (compares
the values of all searchable columns) CompareRowVersion (compares the
value the column with datatype RowVersion (~Timestamp) I prefer using
CompareRowVersion. See DB Concurrency Control with .NET-Details.
Also have a read of DB Concurrency Control with .NET – Details to see how to do this.
I found the answer,
just added one line of code before update statement
dt=dt.getchanges()
myAdapter.update(dt)
I have a database with a few multi-valued lookup fields. When i split my database, there is a repeated error that the junction table is not found. I know Access makes shadow tables when you use the lookup wizard. How do i link these tables?
I tried the following code:
Sub refresh()
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT [Name] FROM [MSysObjects] WHERE ([Type] = 6);", dbOpenSnapshot, dbForwardOnly)
Do While (Not rs.EOF)
db.TableDefs.Delete rs.Fields("Name").Value
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
but when I ran it it still gave me the same error message, that the hidden junction table "in this case called "TblAudienceTblProg"" was not found.
Is there any way to get around this or do I have to restructure the whole back end to include the actual junction tables?
I think the multivalued datatype is only really useful when the backend is going to be in SharePoint or you do not plan to split a local database.
Basically what a multivalued field type is is a many to many relationship without the hassle of creating a bridge table yourself.
Please click here for more information
I have a DataGridView that displays data from a SQL Server database. It allows the user to edit the data and save it back to the database.
The way that data gets saved back to the database is something like this:
Dim da As New SqlDataAdapter
Dim cmdBuilder As New SqlCommandBuilder(da)
da.SelectCommand = New SqlCommand(sql, conn)
da.InsertCommand = cmdBuilder.GetInsertCommand
da.UpdateCommand = cmdBuilder.GetUpdateCommand
Dim cb As SqlCommandBuilder = New SqlCommandBuilder(da)
da.Update(dt)
This works fine when I'm saving to ordinary tables. However I also want to save to a view that has an INSTEAD OF trigger that fires on insert, update and delete. When I try to use the above with this view I get the error:
Dynamic SQL generation for the UpdateCommand is not supported against a SelectCommand that does not return any key column information.
How can I save to this view? I don't want to save directly to the underlying table because I want the trigger to fire.
Thanks!
EDIT: I also tried manually generating the InsertCommand and UpdateCommand, but got the same error.
EDIT 2: It turned out I got the commands wrong when I manually generated them. Once I fixed that it worked fine - my view gets updated and the trigger fires as expected. I guess that you just can't autogenerate the commands for a view with SqlCommandBuilder.
a quick google search shows that this problem may occur if your table does not have a primary key value. your select query must return that value for the update query (in a case where there is no primary key column, it wouldnt.)
http://social.msdn.microsoft.com/Forums/en-NZ/Vsexpressvcs/thread/5dec5633-ac84-48d9-8fd6-5c7601be4ccd