E
E®!k \\/!sser
I have a problem with Concurrency control.
The situation.
- A Datadriven form. I pass a name for the table to show and a PK value.
This is how the databinding is done:
LOCAL oTextbox AS System.Windows.Forms.TextBox
oTextbox := System.Windows.Forms.TextBox{}
oTextbox:Size := System.Drawing.Size{ wEditWidth,
wHeight+wEditHeight}
oTextbox:Location := System.Drawing.Point{ wLeft+wTextWidth+wVerGap,
wPixelHeight+7 }
oTextbox:Name := cName
oTextboxataBindings:Add(Binding{"Text", dt, cName } )
SELF:Controls:Add( oTextbox )
This is how the datastuff gets initialized:
oCommand:CommandText := cSqlUpdate
SELFaUpdate := SqlDataAdapter{}
SELFaUpdate:SelectCommand := oCommand
SELFtUpdate := DataTable{}
SELFaUpdate:Fill( SELF:dtUpdate )
SELFBindingSource := BindingSource{}
SELFBindingSourceataSource := SELF:dtUpdate
When the user has edited data in the form and presses the OK/Save button,
the UpdateDatabase method is called.
This works all fine!!
Now I have added code to handle situations where someone else has changed
the same record
It is based upon a sample here:
http://msdn.microsoft.com/en-us/library/ms171936.aspx
So when a dbConcurrency execption is raized, I like to show the current row
on the database (the content changed by the oher user) ,
the content of the row when de user strated editing en the changed ccontent.
Now here is where it goes wrong . When the user selects to have the database
updated with his changes (pressed yes) The call to UpdateDatabases() still
leads to a
DBConcurrencyException.
So my question is, what to do to force the changes writtten to the database?
The code in the ProcessResponce method is the same as used in several
samples I have found on the MS website, so that cannot be wrong <g>. So my
guess is it has somethnig to do with the (way I use) databinding.
Any suggestions??
tia,
Erik
VIRTUAL Method UpdateDatabase() AS System.Boolean
LOCAL lReturn AS LOGIC
TRY
lReturn := FALSE
SELF:Validate()
SELFBindingSource:EndEdit()
SqlCommandBuilder{ SELF:daUpdate }
SELF:daUpdate:Update( SELF:dtUpdate )
SELF:dtUpdate:AcceptChanges()
lReturn := TRUE
CATCH ex AS System.Data.DBConcurrencyException
LOCAL drResponse AS DialogResult
LOCAL oRow AS DataRow
oRow := (DataRow) ex:Row
drResponse := MessageBox.Show( SELF:CreateMessage( oRow ),
"Multi-user probleem",MessageBoxButtons.YesNo )
SELFrocessResonse( drResponse )
CATCH ex AS System.Exception
MessageBox.Show( ex:Message )
FINALLY
//clean up
END TRY
RETURN lReturn
VIRTUAL METHOD CreateMessage( oRow AS DataRow ) AS STRING
RETURN "Database: " + SELF:GetRowData( SELF:GetCurrentRowInDB(oRow),
DataRowVersion.Default) +CRLF +;
"Origineel: " + SELF:GetRowData(oRow, DataRowVersion.Original)
+ CRLF +;
"Voorgesteld: " + SELF:GetRowData(oRow, DataRowVersion.Current)
+ CRLF +;
"Wilt u nog steeds de Database updaten met de voorgestelde
waarde(n)?"
VIRTUAL METHOD GetRowData( oRow AS DataRow , RowVersion AS DataRowVersion )
AS String
LOCAL rowData AS STRING
LOCAL i AS System.Int32
rowData :=""
FOR i := 0 UPTO oRow:ItemArray:Length-1
RowData := RowData + oRow:Item[i, RowVersion]:ToString() + " "
NEXT
RETURN rowData
VIRTUAL METHOD GetCurrentRowInDB( oErrorRow AS DataRow ) AS DataRow
LOCAL drCurrentRow AS DataRow
SELFTempTable := DataTable{}
SELFAUpdate:Fill( SELFTempTable )
drCurrentRow := oTempTable:Select("ID="+ oErrorRow:Item[0]:ToString())[1]
RETURN drCurrentRow
VIRTUAL METHOD ProcessResonse( dr AS DialogResult )AS VOID
IF dr=Windows.Forms.DialogResult.Yes
SELF:dtUpdate:Merge( SELFTempTable, TRUE )
SELF:UpdateDatabase()
ELSEIF dr=Windows.Forms.DialogResult.No
SELFTUpdate:Merge( SELFTempTable )
ENDIF
RETURN
The situation.
- A Datadriven form. I pass a name for the table to show and a PK value.
This is how the databinding is done:
LOCAL oTextbox AS System.Windows.Forms.TextBox
oTextbox := System.Windows.Forms.TextBox{}
oTextbox:Size := System.Drawing.Size{ wEditWidth,
wHeight+wEditHeight}
oTextbox:Location := System.Drawing.Point{ wLeft+wTextWidth+wVerGap,
wPixelHeight+7 }
oTextbox:Name := cName
oTextboxataBindings:Add(Binding{"Text", dt, cName } )
SELF:Controls:Add( oTextbox )
This is how the datastuff gets initialized:
oCommand:CommandText := cSqlUpdate
SELFaUpdate := SqlDataAdapter{}
SELFaUpdate:SelectCommand := oCommand
SELFtUpdate := DataTable{}
SELFaUpdate:Fill( SELF:dtUpdate )
SELFBindingSource := BindingSource{}
SELFBindingSourceataSource := SELF:dtUpdate
When the user has edited data in the form and presses the OK/Save button,
the UpdateDatabase method is called.
This works all fine!!
Now I have added code to handle situations where someone else has changed
the same record
It is based upon a sample here:
http://msdn.microsoft.com/en-us/library/ms171936.aspx
So when a dbConcurrency execption is raized, I like to show the current row
on the database (the content changed by the oher user) ,
the content of the row when de user strated editing en the changed ccontent.
Now here is where it goes wrong . When the user selects to have the database
updated with his changes (pressed yes) The call to UpdateDatabases() still
leads to a
DBConcurrencyException.
So my question is, what to do to force the changes writtten to the database?
The code in the ProcessResponce method is the same as used in several
samples I have found on the MS website, so that cannot be wrong <g>. So my
guess is it has somethnig to do with the (way I use) databinding.
Any suggestions??
tia,
Erik
VIRTUAL Method UpdateDatabase() AS System.Boolean
LOCAL lReturn AS LOGIC
TRY
lReturn := FALSE
SELF:Validate()
SELFBindingSource:EndEdit()
SqlCommandBuilder{ SELF:daUpdate }
SELF:daUpdate:Update( SELF:dtUpdate )
SELF:dtUpdate:AcceptChanges()
lReturn := TRUE
CATCH ex AS System.Data.DBConcurrencyException
LOCAL drResponse AS DialogResult
LOCAL oRow AS DataRow
oRow := (DataRow) ex:Row
drResponse := MessageBox.Show( SELF:CreateMessage( oRow ),
"Multi-user probleem",MessageBoxButtons.YesNo )
SELFrocessResonse( drResponse )
CATCH ex AS System.Exception
MessageBox.Show( ex:Message )
FINALLY
//clean up
END TRY
RETURN lReturn
VIRTUAL METHOD CreateMessage( oRow AS DataRow ) AS STRING
RETURN "Database: " + SELF:GetRowData( SELF:GetCurrentRowInDB(oRow),
DataRowVersion.Default) +CRLF +;
"Origineel: " + SELF:GetRowData(oRow, DataRowVersion.Original)
+ CRLF +;
"Voorgesteld: " + SELF:GetRowData(oRow, DataRowVersion.Current)
+ CRLF +;
"Wilt u nog steeds de Database updaten met de voorgestelde
waarde(n)?"
VIRTUAL METHOD GetRowData( oRow AS DataRow , RowVersion AS DataRowVersion )
AS String
LOCAL rowData AS STRING
LOCAL i AS System.Int32
rowData :=""
FOR i := 0 UPTO oRow:ItemArray:Length-1
RowData := RowData + oRow:Item[i, RowVersion]:ToString() + " "
NEXT
RETURN rowData
VIRTUAL METHOD GetCurrentRowInDB( oErrorRow AS DataRow ) AS DataRow
LOCAL drCurrentRow AS DataRow
SELFTempTable := DataTable{}
SELFAUpdate:Fill( SELFTempTable )
drCurrentRow := oTempTable:Select("ID="+ oErrorRow:Item[0]:ToString())[1]
RETURN drCurrentRow
VIRTUAL METHOD ProcessResonse( dr AS DialogResult )AS VOID
IF dr=Windows.Forms.DialogResult.Yes
SELF:dtUpdate:Merge( SELFTempTable, TRUE )
SELF:UpdateDatabase()
ELSEIF dr=Windows.Forms.DialogResult.No
SELFTUpdate:Merge( SELFTempTable )
ENDIF
RETURN