独占式编辑
本节讲述如何避免多人同时编辑同一行,既如何实现独占式编辑。
提醒:由于OpenQQ的出现,本节的内容已经过时,请参考:用OpenQQ实现独占式编辑
虽然本节的内容有些过时,但是依然有参考价值,所以我们依然保留了这一节的内容,有兴趣的话,可以看看。
示例一
本示例可以参考CaseStudy目录下的文件:独占式编辑之一.Table
请分别启动多个Foxtable打开此文件,并以不同的用户登录,同一行只要有人开始编辑,那么直到此人保存此行,其他人都不能编辑此行。
设计步骤:
1、首先给表增加一个字符列,名为"编辑者",用于记录正在编辑某行数据的用户名。
2、在项目事件AfterOpenProject设置代码:
'解锁非正常退出时被锁定的记录
DataTables("员工").ReplaceFor("编辑者",Nothing,"编辑者
= '" & User.Name
& "'")
DataTables("员工").Save()
Tables("员工").Cols.Remove("编辑者")
'移除编辑者列,避免用户直接修改此列
3、将表事件StartEdit代码设置为:
If
e.Row("编辑者")
= User.Name
Then '如果编辑者是当前用户
Return
End
If
Dim
cmd As
New
SQLCommand
Dim
exp As
String = "编辑者 Is
Null And [_Identify] = " &
e.Row("_Identify")
cmd.CommandText
= "Update {员工} Set 编辑者 = '"
& User.Name
& "' Where "
&
exp
If
cmd.ExecuteNonQuery
= 1 Then
e.Row("编辑者")
= User.Name
Else
cmd.CommandText
= "Select 编辑者 From {员工} Where [_Identify] = "
& e.Row("_Identify")
Dim
nm As
String = cmd.ExecuteScalar
If nm
> "" Then
MessageBox.show(nm
&
"正在编辑此行!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
Else
MessageBox.show("此行可能已经被删除,无法编辑!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
End
If
e.Cancel
= True
'取消编辑
End
If
注意这里用的是StartEdit事件,而不是PrepareEdit事件,也就是只有用户真正开始编辑数据时,才会执行上述代码。
我们来分析一下上述代码的工作原理,假定某行没有人编辑,张三和李四同时开始编辑此行,同时开始执行上述代码,如果张三抢先了一点,那么执行了Update语句之后,编辑者列的内容成为“张三”,由于Update语句设置了条件,只有编辑者列为空时,Update语句才会执行,所以随后李四在执行Update语句时,由于已经没有符合条件的行,导致ExecuteNonQuery方法返回0,
于是取消编辑,并用Select语句从后台找出正在编辑此行的用户名,告知李四。
4、将表事件DataRowAdding代码设置为:
e.DataRow("编辑者") = User.name
5、将表事件BeforSaveDatarow代码设置为:
If
e.DataRow.RowState
= DataRowState.Added
Then '如果是新增行
e.DataRow("编辑者")
= Nothing
Else
Dim cmd
As New
SQLCommand
cmd.CommandText
= "Update {员工} Set 编辑者 = Null Where [_Identify] = "
& e.DataRow("_Identify")
If cmd.ExecuteNonQuery
= 1 Then
e.DataRow("编辑者")
= Nothing
End If
End
If
上述代码在保存行之前,清除此行的编辑者列内容,也就是解锁此行。
你也许会奇怪,为什么新增行可以直接清空编辑者列的内容,但其它行要通过Update语句设置?
假定现有一行数据,用户张三双击此行某个单元格开始编辑,系统执行StartEdit事件,将编辑者列的内容设置为“张三”,后台此列的内容也通过Update语句设置为了“张三”,如果此用户在编辑过程中,没有做任何修改,就选择了其他单元格,然后保存,此时如果在BeforeSaveDataRow事件中直接清空编辑者列内容,那么此行所有列的内容和最初完全一样,Foxtable将不会保存此行,所以虽然你清空了编辑者列的内容,但是后台的编辑者列还是“张三”,导致记录被锁死。
这里涉及到Foxtable的保存机制:在保存某行之前,系统会进行一个判断,如果此行所有列内容和最初完全相同,则跳过此行,以提高保存效率。
6、最后设置BeforeCloseProject事件代码为:
Dim
cmd As
New SQLCommand
cmd.CommandText
= "Update {员工} Set 编辑者 = Null Where 编辑者 = '"
& User.Name
& "'"
cmd.ExecuteNonQuery
这样在关闭项目前,将清除当前用户锁定的全部行。
示例二
上面讲述的是直接在表中录入数据的时候,如何实现独占式编辑,下面讲述如何在窗口中实现独占式编辑。
本示例可以参考CaseStudy目录下的文件:独占式编辑之二.Table
请分别启动多个Foxtable打开此文件,并以不同的用户登录,只要有人双击某行开始编辑,那么直到此人结束编辑,其他人都不能编辑此行。
1、首先给表增加一个字符列,名为"编辑者",用于记录正在编辑某行数据的用户名。
2、在项目事件AfterOpenProject设置代码:
'解锁非正常退出时被锁定的记录
DataTables("员工").ReplaceFor("编辑者",Nothing,"编辑者
= '" & User.Name
& "'")
DataTables("员工").Save()
Tables("员工").Cols.Remove("编辑者")
'移除编辑者列,避免用户直接修改此列
3、将表事件PrepareEdit代码设置为:
e.Cancel = True
4、将表事件DataRowAdding代码设置为:
e.DataRow("编辑者") = User.name
5、将表事件DoubleClick代码设置为:
If
e.Row("编辑者")
= User.Name
Then '如果编辑者是当前用户
Return
End
If
Dim
cmd As
New
SQLCommand
Dim
exp As
String = "编辑者 Is
Null And [_Identify] = " &
e.Row("_Identify")
cmd.CommandText
= "Update {员工} Set 编辑者 = '"
& User.Name
& "' Where "
&
exp
If
cmd.ExecuteNonQuery
= 1 Then
e.Row("编辑者")
= User.Name
e.Row.Save()
Forms("编辑窗口").Open()
Else
cmd.CommandText
= "Select 编辑者 From {员工} Where [_Identify] = "
& e.Row("_Identify")
Dim
nm As
String = cmd.ExecuteScalar
If nm
> "" Then
MessageBox.show(nm
&
"正在编辑此行!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
Else
MessageBox.show("此行可能已经被删除,无法编辑!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
End
If
End
If
上述代码的前面已经讲述,这里就不重复了。
6、设计一个下图所示的编辑窗口,注意在设计窗口的时候,应该将“显示控制框”属性设置为False,这样窗口就没有了关闭按钮,避免用户直接关闭窗口:
7、窗口“保存修改”按钮的代码为:
Tables("员工").Current("编辑者")
= Nothing
Tables("员工").Current.Save()
e.Form.Close()
8、窗口“撤销修改”按钮的代码为:
Tables("员工").Current.Reject()
'撤销编辑
Tables("员工").Current("编辑者")
= Nothing
Tables("员工").Current.Save()
e.Form.Close()
这样不管用户保存还是撤销修改,编辑者列的内容都会被清除,让后来者得以继续编辑此行。
9、最后设置BeforeCloseProject事件代码为:
Dim
cmd As
New SQLCommand
cmd.CommandText
= "Update {员工} Set 编辑者 = Null Where 编辑者 = '"
& User.Name
& "'"
cmd.ExecuteNonQuery
这样在关闭项目前,将清除当前用户锁定的全部行。