Foxtable(狐表)用户栏目专家坐堂 → 关于独占式编辑问题


  共有5128人关注过本帖树形打印复制链接

主题:关于独占式编辑问题

帅哥哟,离线,有人找我吗?
lgz518
  1楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
关于独占式编辑问题  发帖心情 Post By:2020/4/9 15:51:00 [显示全部帖子]

问题1:我是用纯窗口开发,所以用下代码,就是可以实现独占式编辑,实现并发?

用OpenQQ实现独占式编辑

本节讲述如何避免多人同时编辑同一行,既如何实现独占式编辑。
利用OpenQQ,可以很轻松实现此功能。

要实现此功能,服务器端和客户端都要进行相应的设计,我们学习的时候,也要结合客户端和服务端的代码来理解。

一。服务器端的设计

1、在服务器端项目的全局代码中,加入如下代码:

Public tbrk As new Dictionary(of String,String)

tbrk是一个字典,用于登记每一行是谁在编辑。
我们约定接下来编码的时候:字典的键由表名和行的主键组合成,值则等于编辑者名。

2、在服务端项目的OpenQQ服务端的ReceivedMessage事件加上代码:

Dim msg As String = e.Message
If
 msg.StartsWith("?#"AndAlso msg.EndsWith("#?"Then '收到请求编辑信号
    
Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key) = False Then 
'
如果无人编辑此行
        tbrk.Add(Key,e.UserName) 
'
登记申请者为此行的编辑者
        e.ReturnValue = "OK" 
'
通知申请者可以编辑
    ElseIf tbrk(Key) = e.UserName Then 
'
如果申请者就是之前登记的编辑者
        e.ReturnValue = "OK" 
'
通知申请者可以编辑
    Else 
'
如果之前登记的编辑者为其他人
        e.ReturnValue = tbrk(Key) & 
"
正在编辑此行!" '告知申请者是谁在编辑此行
    
End If
ElseIf
 msg.StartsWith("!#"AndAlso msg.EndsWith("#!"Then '收到结束编辑信号
    Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key)  Then
        
tbrk.Remove(Key'从集合中移除此行的编辑登记
    End 
If

End
 If

上述代码的注释详尽明了,就不做解释了。

3、在服务端项目的OpenQQ服务端的UserLogout事件加上代码:

Dim Keys As New List(of String)
For
 Each Key As String In tbrk.Keys
   If tbrk(Key) = e.UserName Then
      Keys.Add(Key)
    End 
If

Next
For
 Each Key As String In Keys
    
tbrk.Remove(Key)
Next

这样当有用户退出登录时,不管他是正常退出还是异常退出,都可以将字典中该用户的编辑登记移除,避免死锁。
客户端用户异常退出时,服务端的编辑登记的移除会有一个延时,时长取决于QQServer的
HeartbeatTimeout(心跳超时)属性。
上述编码有一个地方需要注意,我们不能在遍历字典或集合的过程中移除其成员(运行时会报错),所以我们用一个临时的集合Keys,先将要移除的键值保存在这个集合中,最后遍历这个集合中的键值,从字典tbrk中移除这些键值。



二。如果是窗口编辑

上述方案针对的是直接在表中编辑数据,如果不是在表中编辑,而是在窗口编辑,编码方式也是基本相同的。
通常只需将打开编辑窗口的代码改为:

Dim r As Row = Tables("B").Current
If
 QQClient.Ready = False Then '如果QQClient没有启动,则禁止编辑
    PopMessage("
必须启动QQClient,才能编辑此表数据!","提示",PopIconEnum.Infomation,5)
    Return

End
 If
If
 r.DataRow.RowState <>  DataRowState.Added Then '如果不是新增行
    Dim key As String = "
B"  & ":" & r("_Identify")
    If tbrk.Contains(key) = False Then
        Dim msg = QQClient.SendWait("?#" & Key & "#?",5'
向服务器发送请求编辑信息
        If msg = "OK" Then '
如果服务器返回OK
            tbrk.Add(key) '
在本地登记正在编辑此行
        ElseIf msg > "" Then '
否则显示服务器返回的信息,并取消编辑
            PopMessage("
无法编辑此行,因为:" & vbcrlf & msg ,"提示",PopIconEnum.Infomation,5)
            Return
        Else '
如果服务器没有返回信息,则取消编辑
            
PopMessage("因服务器无响应,无法编辑此行!" ,"提示",PopIconEnum.Infomation,5)
            Return
        End If
    End If

End
 If
Forms
("编辑窗口").Open()


问题2:1、在服务器端项目的全局代码中,加入如下代码:

Public tbrk As new Dictionary(of String,String)


服务器端项目的全局,在哪里?“网络监测器”里没看到,项目事件倒是有全局?


图片点击可在新窗口打开查看此主题相关图片如下:服务器.jpg
图片点击可在新窗口打开查看



 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  2楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/4/9 16:20:00 [显示全部帖子]

'2.独占式编辑----在服务端项目的OpenQQ服务端的ReceivedMessage事件加上代码:

Dim msg As String = e.Message
If msg.StartsWith("?#") AndAlso msg.EndsWith("#?") Then '收到请求编辑信号
    Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key) = False Then '如果无人编辑此行
        tbrk.Add(Key,e.UserName) '登记申请者为此行的编辑者
        e.ReturnValue = "OK" '通知申请者可以编辑
    ElseIf tbrk(Key) = e.UserName Then '如果申请者就是之前登记的编辑者
        e.ReturnValue = "OK" '通知申请者可以编辑
    Else '如果之前登记的编辑者为其他人
        e.ReturnValue = tbrk(Key) & "正在编辑此行!" '告知申请者是谁在编辑此行
    End If
ElseIf msg.StartsWith("!#") AndAlso msg.EndsWith("#!") Then '收到结束编辑信号
    Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key)  Then
        tbrk.Remove(Key) '从集合中移除此行的编辑登记
    End If
End If

放上面代码,报错

图片点击可在新窗口打开查看此主题相关图片如下:服务器1.jpg
图片点击可在新窗口打开查看


 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  3楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/4/9 16:28:00 [显示全部帖子]

放在另一个,也是报错
图片点击可在新窗口打开查看此主题相关图片如下:服务器2.jpg
图片点击可在新窗口打开查看

 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  4楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/4/9 16:32:00 [显示全部帖子]

1.还是我表设为“制表人”或经办人字段,没设“编辑者”字段,因为想“制表人”或经办人字段代替“编辑者”字段,可行?还是一定“编辑者”字段?
2.关联表(主表和明细表)都要分别设“制表人”或经办人或编辑者字段?

 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  5楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 9:57:00 [显示全部帖子]

二。如果是窗口编辑

上述方案针对的是直接在表中编辑数据,如果不是在表中编辑,而是在窗口编辑,编码方式也是基本相同的。
通常只需将打开编辑窗口的代码改为:

Dim r As Row = Tables("B").Current
If
 QQClient.Ready = False Then '如果QQClient没有启动,则禁止编辑
    PopMessage("
必须启动QQClient,才能编辑此表数据!","提示",PopIconEnum.Infomation,5)
    Return

End
 If
If
 r.DataRow.RowState <>  DataRowState.Added Then '如果不是新增行
    Dim key As String = "
B"  & ":" & r("_Identify")
    If tbrk.Contains(key) = False Then
        Dim msg = QQClient.SendWait("?#" & Key & "#?",5'
向服务器发送请求编辑信息
        If msg = "OK" Then '
如果服务器返回OK
            tbrk.Add(key) '
在本地登记正在编辑此行
        ElseIf msg > "" Then '
否则显示服务器返回的信息,并取消编辑
            PopMessage("
无法编辑此行,因为:" & vbcrlf & msg ,"提示",PopIconEnum.Infomation,5)
            Return
        Else '
如果服务器没有返回信息,则取消编辑
            
PopMessage("因服务器无响应,无法编辑此行!" ,"提示",PopIconEnum.Infomation,5)
            Return
        End If
    End If

End
 If
Forms
("编辑窗口").Open()







 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  6楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 10:01:00 [显示全部帖子]

上面代码,有以下问题:

1.上述方案针对的是直接在表中编辑数据,如果不是在表中编辑,而是在窗口编辑,编码方式也是基本相同的。

通常只需将打开编辑窗口的代码-:

这里的“打开编辑窗口”“窗口AfterLoad事件”?关联?


2.Dim r As Row = Tables("B").Current,这个单表,如果关联要怎么写?

Dim r As Row = Tables("主表").Current,

Dim A As Row = Tables("明细").Current,

3.Forms("编辑窗口").Open(),如果打开编辑窗口”“窗口AfterLoad事件”,这里怎么还要写Forms("编辑窗口").Open()?看不是很明白,请老师,指导一下,谢谢


 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  7楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 10:43:00 [显示全部帖子]

老师,我做一个主窗体界面,其中有一个按键,是引向”采购窗口“进行录入,在这个”按键事件“,写下面代码,红色带线,这样对?请老师,批阅纠正,谢谢

Dim
 r As Row = Tables("表A").Current
Dim A As Row = Tables("表A.表B").Current
If
 QQClient.Ready = False Then '如果QQClient没有启动,则禁止编辑
    PopMessage("
必须启动QQClient,才能编辑此表数据!","提示",PopIconEnum.Infomation,5)
    Return

End
 If
If
 r.DataRow.RowState <>  DataRowState.Added Then '如果不是新增行
   
 Dim key As String = "表A"  & ":" & r("_Identify")
     Dim key As String = "表A.表B"  & ":" & r("_Identify")
    If tbrk.Contains(key) = False Then
        Dim msg = QQClient.SendWait("?#" & Key & "#?",5'
向服务器发送请求编辑信息
        If msg = "OK" Then '
如果服务器返回OK
            tbrk.Add(key) '
在本地登记正在编辑此行
        ElseIf msg > "" Then '
否则显示服务器返回的信息,并取消编辑
            PopMessage("
无法编辑此行,因为:" & vbcrlf & msg ,"提示",PopIconEnum.Infomation,5)
            Return
        Else '
如果服务器没有返回信息,则取消编辑
            
PopMessage("因服务器无响应,无法编辑此行!" ,"提示",PopIconEnum.Infomation,5)
            Return
        End If
    End If

End
 If
Forms
("采购窗口").Open()

 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  8楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 11:04:00 [显示全部帖子]

用OpenQQ实现独占式编辑

本节讲述如何避免多人同时编辑同一行,既如何实现独占式编辑。
利用OpenQQ,可以很轻松实现此功能。

要实现此功能,服务器端和客户端都要进行相应的设计,我们学习的时候,也要结合客户端和服务端的代码来理解。

一。服务器端的设计

1、在服务器端项目的全局代码中,加入如下代码:

Public tbrk As new Dictionary(of String,String)

tbrk是一个字典,用于登记每一行是谁在编辑。
我们约定接下来编码的时候:字典的键由表名和行的主键组合成,值则等于编辑者名。

2、在服务端项目的OpenQQ服务端的ReceivedMessage事件加上代码:

Dim msg As String = e.Message
If
 msg.StartsWith("?#"AndAlso msg.EndsWith("#?"Then '收到请求编辑信号
    
Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key) = False Then 
'
如果无人编辑此行
        tbrk.Add(Key,e.UserName) 
'
登记申请者为此行的编辑者
        e.ReturnValue = "OK" 
'
通知申请者可以编辑
    ElseIf tbrk(Key) = e.UserName Then 
'
如果申请者就是之前登记的编辑者
        e.ReturnValue = "OK" 
'
通知申请者可以编辑
    Else 
'
如果之前登记的编辑者为其他人
        e.ReturnValue = tbrk(Key) & 
"
正在编辑此行!" '告知申请者是谁在编辑此行
    
End If


 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  9楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 11:04:00 [显示全部帖子]

ElseIf msg.StartsWith("!#"AndAlso msg.EndsWith("#!"Then '收到结束编辑信号
    Dim Key As String = msg.SubString(2,msg.Length - 4)
    If tbrk.Containskey(Key)  Then
        
tbrk.Remove(Key'从集合中移除此行的编辑登记
    End 
If

End
 If

上述代码的注释详尽明了,就不做解释了。

3、在服务端项目的OpenQQ服务端的UserLogout事件加上代码:

Dim Keys As New List(of String)
For
 Each Key As String In tbrk.Keys
   If tbrk(Key) = e.UserName Then
      Keys.Add(Key)
    End 
If

Next
For
 Each Key As String In Keys
    
tbrk.Remove(Key)
Next

这样当有用户退出登录时,不管他是正常退出还是异常退出,都可以将字典中该用户的编辑登记移除,避免死锁。
客户端用户异常退出时,服务端的编辑登记的移除会有一个延时,时长取决于QQServer的
HeartbeatTimeout(心跳超时)属性。
上述编码有一个地方需要注意,我们不能在遍历字典或集合的过程中移除其成员(运行时会报错),所以我们用一个临时的集合Keys,先将要移除的键值保存在这个集合中,最后遍历这个集合中的键值,从字典tbrk中移除这些键值。

老师,看帮助,上面是服务器的设计,没有看到表,您说然后服务端分析接收的信息的时候也需要改改,先根据“|”筛分2个表的数据,再逐个判断。
这个要在哪里写,如何实现?谢谢

 回到顶部
帅哥哟,离线,有人找我吗?
lgz518
  10楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1271 积分:8670 威望:0 精华:0 注册:2019/6/13 9:57:00
  发帖心情 Post By:2020/5/11 13:33:00 [显示全部帖子]

老师,看帮助,上面是服务器的设计,没有看到表,您说然后服务端分析接收的信息的时候也需要改改,先根据“|”筛分2个表的数据,再逐个判断。
这个要在哪里写,如何实现?谢谢

 回到顶部
总数 30 1 2 3 下一页