独占式编辑

本节讲述如何避免多人同时编辑同一行,既如何实现独占式编辑。

提醒:由于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

这样在关闭项目前,将清除当前用户锁定的全部行。

 


本页地址:http://www.foxtable.com/webhelp/topics/2295.htm