Foxtable(狐表)用户栏目专家坐堂 → [分享]:在网络多用户并发情况下的申请不重复编号的解决方案


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

主题:[分享]:在网络多用户并发情况下的申请不重复编号的解决方案

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


加好友 发短信
等级:贵宾 帖子:102 积分:880 威望:0 精华:4 注册:2008/8/31 21:47:00
[分享]:在网络多用户并发情况下的申请不重复编号的解决方案  发帖心情 Post By:2009/9/2 12:29:00 [显示全部帖子]

关于使用外部数据源时,在网络多用户并发情况下的不重复编号的申请的解决方案:

目前有2套方案供大家选用。两者相同之处在于系统产生的编号都是自动加1的,申请后未使用的编号都不再收回。不同之处在于申请编号的时间点不同。

第一个方案是在用户申请时,系统及时产生一个新的不重复的编号显示反馈给用户,可在DataRowAdding中应用。一个是在保存时才由系统产生一个新的不重复的编号,在BeforeSaveDataRow中应用(见:http://www.foxtable.com/dispbbs.asp?BoardID=2&ID=1727&replyID=&skin=1

以下是我在实际应用中使用的方法(申请时获取编号):
先建立数据库,表名:getnumberid,字段有:

Tablename  表名

Colname     列名

Preletter     前缀字符

Len            序列号长度

Sqdate       申请时间

number      当前序列号


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

在设计之前,要知道SQL的2个锁的概念。我摘录文章如下:

SQL Server的基本锁是共享锁(S锁)和排它锁(X锁)。

共享锁(S锁):用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。共享锁锁定的资源可以被其他用户读取,但其他用户无法修改它,在执行Select时,SQL Server会对对象加共享锁。

排它锁(X锁): 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。执行数据更新命令时,SQL Server会自动使用独占锁。当对象上有其他锁存在时,无法对其加独占锁。
一般情况下,SQL Server能自动提供加锁功能,不需要用户专门设置。

当用SELECT语句访问数据库时,系统能自动用共享锁访问数据;在使用INSERT、UPDATE和DELETE语句增加、修改和删除数据时,系统会自动给使用数据加排它锁。

以下是获取不重复编号的自定义函数。

'举例: Functions.Execute("getnumber","cgswbc","xtbh")

'参数1:表名,字符型,如"cgswbc"

'参数2:列名,字符型,是参数1的表中列名,如"xtbh"

'-----------------------------------------------------------------------------

dim getbh as string  'return 编号

dim tbname as string=Args(0)  '读参数1,表名

dim clname as string=Args(1)  '读参数2,列名

dim sqldate,numdate as date   'SQL服务器时间,指定表的编号使用时间

Dim dt As DataTable

Dim dr As Datarow

Dim t As integer

dim xh as integer=0   'update所影响行数的结果作为循环依据

dim numpre,numlen as string   '准备存放前缀字符,序列号长度

dim num as integer   '        '准备存放表中当前序号

Dim cmd As New SQLCommand

cmd.C

cmd.CommandText = "select getdate()"

sqldate=cmd.ExecuteScalar()   '读SQL系统日期


do

    cmd.CommandText = "select  ISNULL(sqdate,GETDATE()) AS sqdate ,preletter,len, ISNULL(number,0) AS number from getnumberid where tablename='" & tbname & "' and colname='" & clname & "'"

    dt = cmd.ExecuteReader()   '读行记录

    if dt is nothing then

        Exit Do  '没有行记录则直接退出返回

    end if

    dr = dt.DataRows(0)    '取记录的第一行

    numdate=dr("sqdate")

    numpre=dr("preletter")

    numlen=dr("len")

    num=dr("number")   

    t=(sqldate-numdate).TotalDays   

    if t>0 then

        cmd.commandtext = "Update getnumberid Set number =1,sqdate='" & sqldate & "' where tablename='" & tbname & "' and colname='" & clname & "' and number=" & num    ’(此处关键,先读编号,根据编号更新。即使100个用户并发,也只有一个用户能成功申请,其余99个用户会申请失败,将会重新循环申请。)

        xh=cmd.ExecuteNonQuery()

        num=1   ' 新的一天,序列号置1

        numdate=sqldate  '填上新的日期

    else

        cmd.commandtext = "Update getnumberid Set number =" & num+1  & " where tablename='" & tbname & "' and colname='" & clname & "' and number=" & num

        xh=cmd.ExecuteNonQuery()

        num=num+1

    end if   

    getbh=numpre.Trim() & "-" & CStr(numdate.year).SubString(2) & CStr(numdate.Month).PadLeft(2 ,"0")  & CStr(numdate.Day).PadLeft(2 ,"0")   & "-" &  CStr(num).PadLeft(numlen ,"0")

Loop While xh=0

return getbh
------------------

[本帖被加为精华]
 回到顶部