How to update database from unchanged datatable - sql-server

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)

Related

is there any way to lock a row temporarily

I am using sql server with my VB.NET application where in multiple instance of the application is run from different server (CITRIX). I am sorting and picking up one individual Row for processing and immediately marking that row as picked in a column so that other instance doesn't pick up the same row and waste time. The issue is, in between picking up the row and updating as picked, another instance of the application is picking up the row. I have been suggested for using with DB Lock but the concept is not that much clear to me like whether it will solve my problem, whether I need admin right to use it (I do not have admin right in client DB) etc. Below is the code snippet I have used.
Dim MyConnection As SqlConnection
Try
MyConnection = New SqlConnection(connString)
MyConnection.Open()
Dim tableName As String = myTableName
Dim sqlQuery As String = "Select Top 1 * from " + tableName + " where "<some condition>
Dim MyCommand As SqlDataAdapter = New SqlDataAdapter(sqlQuery, MyConnection)
Dim DS as DataSet = New DataSet
MyCommand.Fill(DS, tableName)
If DS.Tables(0).Rows.Count >= 1 Then
sqlQuery = "UPDATE " + tableName + " SET Fld = #fld where Cond1= '" + DS.Tables(0).Rows(0).Item("Cond1").ToString + "'"
Dim cmd As New Data.SqlClient.SqlCommand(sqlQuery)
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("#fld", Data.SqlDbType.VarChar).Value = "Picked"
Try
cmd.Connection = MyConnection
cmd.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End If
Catch ex As Exception
MsgBox(ex.ToString)
Finally
MyConnection.Close()
End Try
I want it to make in such way that if an instance picks up a row, until it finishes updating the row, the row will not be visible to other instance with same query on the table, but other instance will continue to work with the other rows at the same time.
Two options I see:
Change your SELECT and UPDATE queries to a single UPDATE query. I didn't see where your SELECT was buying you anything.
If the SELECT is truly needed, then use a stored procedure on the database to handle the SELECT and the UPDATE on the database server side. You can lock the row during the transaction. See: Transaction Locking and Row Versioning Guide
Note that in general you should try to move your database queries to stored procedures. Not only does this reduce the amount of network traffic moving datasets back and forth, it increases the reliability, separates your database code from the UI, allows updates to the procedures without having to push new versions of the client application out and also avoids SQL injection.

Updating SQL server table with vb.net 2010 datagridview

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

How to get the auto increment primary key in old mdb database?

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.

Update from DataGridView with SqlDataAdapter

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

Using Select Statement from 1 database to insert into another database using VB .NET

I am currently writing a VB .NET application where I am trying to open 1 database, create a select statement and then post the results into another database file using Microsoft Access database 2003.
The code seems to stop executing at the statement cmdJetDB.ExecuteNonQuery()
I am using the following code:
Dim conn1 As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data source=C:\Sample.mdb")
Dim conn2 As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data source=C:\db2.mdb")
conn1.Open()
conn2.Open()
Dim mySelectQuery As String
mySelectQuery = "SELECT Sample.LANE_ADDR, Sample.LANE_DT, Sample.LANE_TM, Sample.LANE_SPEED FROM (Sample) WHERE ((Sample.LANE_ADDR) = '164.909' OR (Sample.LANE_ADDR) = '164.909' AND Sample.LANE_DT BETWEEN #4/4/2003# AND #4/5/2003#)"
Dim cmdJetDB As New OleDbCommand(mySelectQuery, conn1)
cmdJetDB.ExecuteNonQuery()
Dim cmdInsert As String
cmdInsert = "Insert INTO Table1 (Sample.LANE_ADDR, Sample.LANE_TM,Sample.LANE_SPEED) VALUES ('164.909', '00:12:30' , '30' )"
Dim cmdJetDB2 As New OleDbCommand(cmdInsert, conn2)
cmdJetDB2.ExecuteNonQuery()
conn2.Close()
conn1.Close()
Question: What is it that I am not doing. I opened both connections, stated my two SQL statements, yet it is still not working. I really need to get this application working. Please Help.........
ExecuteNonQuery cannot be used to SELECT stuff from a database. You should use ExecuteReader and use the result in a loop to set the parameters of the INSERT statement and then run ExecuteNonQuery in that loop. From the code you've written, how you'd expect the values should be populated in the INSERT statement?
Here is a sugestion,
If the columns you are retriving have the same type as the columns you are inserting (Basicaly you are not making any conversion and/or transformations) do a single query that does this.
INSERT INTO TestTable2
SELECT * FROM TestTable1
You're using SELECT to try to return rows, but then calling ExecuteNonQuery(), which returns nothing. You'll want to use ExecuteReader() instead.
You'll probably get another error later because you're INSERTing into "Table1" but trying to reference fields in "Sample".
Also unrelated to the error, but you aren't doing anything with the data in the SELECT statement to use it in the INSERT statement.

Resources