vb.net cannot update in oracle DB - vb.net

I am developing small program with VB.NET and Oracle DB.
There is a problem when I want to update the column value.
This is my code:
getOraConn()
trans = ora_conn.BeginTransaction(IsolationLevel.ReadCommitted)
cmdOr.Transaction = trans
Try
cmdOr.CommandText = "update tbl_study set flag='0'"
cmdOr.Connection = ora_conn
cmdOr.ExecuteNonQuery()
trans.Commit()
ora_conn.Close()
MessageBox.Show("sucess")
Catch ex As Exception
MessageBox.Show(ex.Message)
trans.Rollback()
End Try
When I running this code, it is always hangs at 'cmdOr.ExecuteNonQuery()' and then the column in DB still not change.
Here is my Oracle connection string:
Function getOraConn() As OracleConnection
Dim oradb As String = "Data Source=SPEC; User Id=sta; Password=sta123;Pooling=False;"
Try
ora_conn = New OracleConnection(oradb)
ora_conn.Open()
Catch ex As Exception
MsgBox("connection failed", MsgBoxStyle.Critical)
End Try
End Function

Related

Re-Open/Throw Error for OLE DB Connection Timeout

I built an app in VS where users can import call evaluations (written in vb.net). However, users continue to leave the application open all day and it appears at some point the OLE DB connection is timing out and not submitting records.
In my insert function I have:
Try
conn.ConnectionString = myconnection
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim myquery As String = "insert into ..."
Dim cmd As New OleDbCommand
With cmd
''more insert
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
conn.Close()
then on my import button I have an if statement to check for blank fields and elseif statement to perform the insert function
any ideas to check for a closed connection and if not open it? Or, any ideas on putting a timer that displays a message the connection has timed out?
any help is appreciated!
Update Question
Should I be doing a try catch with the connection itself and then the insert function?
ie:
Try
cnn = New OleDbConnection()
cnn.Open()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Dim myquery As String = "insert into ..."

How to show error message on forms project when its already catched in library

Have some windows form with nice circural progress bar which i show user during long database function process. There is also task which calls function which inside i got query with transaction and there is catch implemented to rollback if it fails and return either true/false about state of process after finished. I didn't place there memssage box to show error as it's not adviced to store message boxes along in library projects so i would like to show this error on my task level function (in catch). However since i am catching error inside my function i am not able to show it (catch it) on the task's catch. How to accomplish that?
The only idea in my head is to instead of returning only result also return catched error message with use of Tuple like this: Tuple(Of Boolean, String). So i would be able to return two things: result and error message text. I am not so sure if this is right way to do such things. Looking for your advice.
This comes from windows forms project:
Dim pic As New CircuralWindowsForms(eCircularProgressType.Donut)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
Dim resu = False
Try
resu = createArticle.ProcessArticle(data)
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
Finally
'--Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
End Try
Return resu
End Function)
'Show circural form
pic.ShowDialog()
Task.WaitAll(tsk)
if tsk.Result = true Then
...
This comes from library project:
Public Function ProcessArticle(data as Data) As Boolean
Dim result = false
Using connection As New SqlConnection(strcon)
Try
connection.Open()
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction()
.....
transaction.Commit()
result=true
Catch ex As Exception
result = False
transaction.Rollback()
End Try
End Using
return result
End Function
Extended question a bit (discussion with sstan):
Public Sub DeleteAllRelated(varId As Integer)
Using con As New SqlConnection(strcon)
Dim commit As Boolean = True
con.Open()
Dim tran As SqlTransaction = con.BeginTransaction
Dim dt As New DataTable
dt = CType(New Variation_VariationAttributeDAL().GetAllByVariationId(varId), DataTable)
If dt IsNot Nothing Then
For Each row As DataRow In dt.Rows
If commit Then commit = commit And New Artikel_VariationDAL().DeleteByVariation_VariationAttribute(CInt(row(0)), tran)
Next
End If
If commit Then commit = commit And New Variation_VariationAttributeDAL().DeleteAllWhereVarId(varId, tran)
If commit Then commit = commit And Delete(varId, tran)
If commit Then commit = commit And New DALSubKategorie_Variation().Delete(varId, tran)
If commit Then
tran.Commit()
Else
tran.Rollback()
End If
End Using
End Sub
this is e.g for: If commit Then commit = commit And New DALSubKategorie_Variation().Delete(varId, tran)
Public Function Delete(varId As Integer, Optional transaction As SqlTransaction = Nothing) As Boolean
Dim result As Boolean = False
If transaction Is Nothing Then
Try
Using con As New SqlConnection(strcon)
Using cmd As New SqlCommand("DELETE FROM " & SharedData.Write.T(SharedData.Tables.SubKategorie_Variation) & " WHERE FK_Variation_ID=#FK_Variation_ID", con)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#FK_Variation_ID", varId)
con.Open()
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
con.Close()
result = True
End Using
End Using
Catch ex as Exception
Throw
End Try
Else
Using cmd As New SqlCommand("DELETE FROM " & SharedData.Write.T(SharedData.Tables.SubKategorie_Variation) & " WHERE FK_Variation_ID=#FK_Variation_ID", transaction.Connection)
cmd.Transaction = transaction
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#FK_Variation_ID", varId)
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
result = True
End Using
End If
Return result
End Function
You're right that it would be wrong for your library to display message boxes directly. But that doesn't mean it should swallow exceptions either. In, fact, quite the opposite: you really should let the exception bubble up to the caller, and let the caller decide what to do with it.
With that in mind, I would change the ProcessArticle function to the following:
Public Sub ProcessArticle(data as Data)
Using connection As New SqlConnection(strcon)
Try
connection.Open()
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction()
' .....
transaction.Commit()
Catch ex As Exception
transaction.Rollback()
Throw 'Rethrow exception. The caller can decide what to do with it.
End Try
End Using
End Sub
Notice how the exception is still caught to enable the transaction rollback, but the exception is rethrown so that the caller can catch it. This in turn means that you no longer need to return a boolean to indicate success or failure.
EDIT
Not directly related to your question, but I would further move the code around a little bit so that I don't accidentally try to rollback a transaction before it has even begun (With you current code, ask yourself what would happen if an error occurred while trying to open the connection?):
Public Sub ProcessArticle(data as Data)
Using connection As New SqlConnection(strcon)
connection.Open()
Using transaction = connection.BeginTransaction()
Try
' do work here
transaction.Commit()
Catch ex As Exception
transaction.Rollback()
Throw 'Rethrow exception. The caller can decide what to do with it.
End Try
End Using
End Using
End Sub
EDIT 2
More on the Throw Statement:
A Throw statement with no expression can only be used in a Catch statement, in which case the statement rethrows the exception currently being handled by the Catch statement.
EDIT 3: Simplified version of your last edit
Public Sub DeleteAllRelated(varId As Integer)
Using con As New SqlConnection(strcon)
con.Open()
Using transaction = connection.BeginTransaction()
Try
Dim dt As New DataTable
dt = CType(New Variation_VariationAttributeDAL().GetAllByVariationId(varId), DataTable)
If dt IsNot Nothing Then
For Each row As DataRow In dt.Rows
New Artikel_VariationDAL().DeleteByVariation_VariationAttribute(CInt(row(0)), tran)
Next
End If
New Variation_VariationAttributeDAL().DeleteAllWhereVarId(varId, tran)
Delete(varId, tran)
New DALSubKategorie_Variation().Delete(varId, tran)
'If we made it this far without an exception, then commit.
tran.Commit()
Catch ex As Exception
tran.Rollback()
Throw 'Rethrow exception.
End Try
End Using
End Using
End Sub
Public Sub Delete(varId As Integer, Optional transaction As SqlTransaction = Nothing)
If transaction Is Nothing Then
Using con As New SqlConnection(strcon)
Using cmd As New SqlCommand("DELETE FROM " & SharedData.Write.T(SharedData.Tables.SubKategorie_Variation) & " WHERE FK_Variation_ID=#FK_Variation_ID", con)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#FK_Variation_ID", varId)
con.Open()
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
con.Close()
End Using
End Using
Else
Using cmd As New SqlCommand("DELETE FROM " & SharedData.Write.T(SharedData.Tables.SubKategorie_Variation) & " WHERE FK_Variation_ID=#FK_Variation_ID", transaction.Connection)
cmd.Transaction = transaction
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#FK_Variation_ID", varId)
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
End Using
End If
End Sub
EDIT 4: Example of exception chaining
Public Sub ProcessArticle(data as Data)
Try
' do work here
Catch ex As Exception
' If you want the original error to go up to the "upper levels"
' but with additional information, you need to throw a new
' instance of an exception with a new message that contains the additional information
' but you need to pass the original exception as a parameter to the constructor
' so that exceptions get chained together.
' If an "upper level" caller catches the chained exception,
' doing "ex.ToString" will provide all the information.
' Try it out, see how it works.
Throw New Exception("put your additional information here", ex)
End Try
End Sub

How to avoid Error "There is already an open DataReader associated with this Command" in MSSql 2000

I am using SqlBulkCopy to copy data to 2 separate table in same database.
obj_Command.CommandText = "Select * from tmpInvDtlMast where InvNo='111'"
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(con1)
bulkCopy.DestinationTableName = "tmpInvDtlMast"
Try
bulkCopy.WriteToServer(obj_Command.ExecuteReader())
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
bulkCopy.Close()
End Try
End Using
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(con1)
bulkCopy.DestinationTableName = "InvDtlMast"
Try
bulkCopy.WriteToServer(obj_Command.ExecuteReader())
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
bulkCopy.Close()
End Try
End Using
In the second Bulk upload this error occurs
There is already an open DataReader associated with this Command
I have tried "MultipleActiveResultSets=true" with my connection string
con1.ConnectionString = "Data Source=" & SqlServer & ";Initial Catalog=" & Database & ";Persist Security Info=True;User ID=" & User & ";Password=" & Pass & ";MultipleActiveResultSets=true"
After googling more solutions I got to know that MultipleActiveResultSets=true not support for MSSql 2000. Is there anything to do to solve this in Sql2000. Please help
Im using vb.net 2008
As a workaround try duplicating connection and command:
obj_Command.CommandText = "Select * from tmpInvDtlMast where InvNo='111'"
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(con1)
bulkCopy.DestinationTableName = "tmpInvDtlMast"
Try
bulkCopy.WriteToServer(obj_Command.ExecuteReader())
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
bulkCopy.Close()
End Try
End Using
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(**con2**)
bulkCopy.DestinationTableName = "InvDtlMast"
Try
bulkCopy.WriteToServer(**obj_Command2**.ExecuteReader())
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
bulkCopy.Close()
End Try
End Using
I have solved my problem myslf. What I did is remove
obj_Command.ExecuteReader()
with new SqlDataReader instance.
obj_Command.CommandText = "Select * from tmpInvDtlMast where InvNo='111'"
Dim dr as SqlDataReader()
dr=obj_Command.ExecuteNoneQuery()
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(con1)
bulkCopy.DestinationTableName = "tmpInvDtlMast"
Try
bulkCopy.WriteToServer(dr)
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
dr.Close()
End Try
End Using
Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(con1)
bulkCopy.DestinationTableName = "InvDtlMast"
Try
bulkCopy.WriteToServer(dr)
Application.DoEvents()
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
dr.Close()
End Try
End Using

Can a transaction span multiple statements in vb.net

Is this possible in vb.net
sub Main()
conn.open
transactions = conn.begintransaction("SAMPLE")
insertintotable1()
insertintotable2()
insertintotable3()
transactions.commit
end sub
sub insertintotable1
try
conn = new sql connection(connectionstring)
strsql = sql statement
cmd = new sql command(strsql, conn)
cmd.executenonquery
catch ex as exception
transaction.rollback
end try
end sub
sub insertintotable2
try
conn = new sql connection(connectionstring)
strsql = sql statement
cmd = new sql command(strsql, conn)
cmd.executenonquery
catch ex as exception
transaction.rollback
end try
end sub
sub insertintotable3
try
conn = new sql connection(connectionstring)
strsql = sql statement
cmd = new sql command(strsql, conn)
cmd.executenonquery
catch ex as exception
transaction.rollback
end try
end sub
My problem is that without transactions if I have a problem with my query in the 2nd table, table 1 data has already been inserted. SO i looked up transactions and in theory it would solve that issue because you can roll back the insert if something failed.
If you want to do that you need to instance one Sql connection and then pass it to the methods that will do the work on it. At the moment you are instancing a new connection in each method, so each one has it's own transaction.

Oracle transaction Rollback doesn't work

I created an Oracle transaction trying to save some data in two tables and I caused an error at the second procedure to call the rollback and check if it works.
The first procedure creates a job in USER_SCHEDULER_JOBS using the sys.dbms_scheduler.create_job.
Private Function CreateJobDef() As Integer
Try
Cursor.Current = Cursors.WaitCursor
conn = New OracleConnection
conn.ConnectionString = gApp.ConnectString
conn.Open()
Dim cmd As OracleCommand = conn.CreateCommand()
Dim oraclTrans As OracleTransaction
oraclTrans = conn.BeginTransaction()
cmd.Transaction = oraclTrans
Try
cmd.CommandText = "TEST.CREATE_JOB_SCHEDULE"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Clear()
OracleCommandBuilder.DeriveParameters(cmd)
cmd.Parameters("in_job_name").Value = txtName.Text
cmd.Parameters("in_schedule_name").Value = cboSchedule.SelectedValue
cmd.Parameters("in_enabled").Value = If(chkEnabled.Checked, 1, 0)
cmd.Parameters("in_comments").Value = txtComments.Text
cmd.ExecuteNonQuery()
'Everything is OK
'-----------------------------------------------
cmd.CommandText = "TEST.Update_Job_Def"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Clear()
OracleCommandBuilder.DeriveParameters(cmd)
cmd.Parameters("in_job_id").Value = "WQwqwq" 'I set this to a string to cause an error in the second procedure to check the rollback
cmd.Parameters("in_job_name").Value = txtName.Text
cmd.Parameters("in_job_type").Value = cboType.SelectedItem
cmd.Parameters("in_report_nav_id").Value = cboReport.SelectedValue
cmd.Parameters("in_mail_address_to").Value = txtMailTo.Text
cmd.ExecuteNonQuery()
oraclTrans.Commit()
Catch ex As OracleException
Msgbox(ex.ToString)
oraclTrans.Rollback()
Catch ex As Exception
Msgbox(ex.ToString)
oraclTrans.Rollback()
Finally
conn.Close()
If conn IsNot Nothing Then conn.Dispose()
If cmd IsNot Nothing Then cmd.Dispose()
End Try
Catch ex As OracleException
Msgbox(ex.ToString)
Catch ex As Exception
Msgbox(ex.ToString)
Finally
Cursor.Current = Cursors.Default
End Try
End Function
The problem is that the first procedure is create a new Job, although I have caused an error at the second procedure and the rollback is called.
Any ideas?
Thanks
There is an implicit commit in a DDL statement and in many Oracle procedure calls that create or modify objects such as a scheduled job. Therefore you cannot rollback a job creation procedure.