• 全部
  • .NET Framework
  • ASP
  • Web Services
  • .NET互联网桌面应用
  • VB
  • 图表区
  • 分析与设计
  • 组件/控件开发
  • AppLauncher
  • 问答

一个关于事务与封锁的问题.

swzheng 2004-11-06 10:52:19
我的一个数据库里有两个表,一个是everyid,另一个是work。everyid的作用是存放work表中主键id的最大值,work存放一些有用的东西。每次我往work添加东西的时候先将id的值先从everyid中取出来,然后+1,在把这个id作为主键添加入表work,最后再把every的id+1。
但是,但遇到到流量数据的时候,有可能两次插入数据时取出来的id都一样,在插入work是就有可能两条数据的主键时一样的,造成插入不成。

如果用封锁解决问题的话要怎么办了?
我现在了解的封锁好像只能对一个事物而言的,对于这个要怎么解决。
...全文
174 点赞 收藏 18
写回复
18 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
tonybaobao 2004-11-10
其实只要你放在一个存储过程里面就不要担心什么并发冲突的问题了,一个存储过程就是一个事务,所以只会整体提交,或者整体撤销。
回复
brightheroes 2004-11-10
你担心什么独占锁
数据库自己就帮你锁了
回复
swzheng 2004-11-10
楼上的链接上这种方法好像可以。我试试。


还有,独占锁要怎么使用!!!!!
回复
swzheng 2004-11-10
哦,原来是这样。
谢谢!!
回复
brightheroes 2004-11-09
Transaction 属性尚未初始化
----http://community.csdn.net/Expert/topic/3494/3494575.xml?temp=.684292
回复
swzheng 2004-11-09
还有,怎么使用独占锁?????
回复
swzheng 2004-11-09
下面是一个类conne的部分代码。
Public Function GetIdTN(ByVal TableN As String)
GetNum = New GetId
GetNum.Database = Chen
GetNum.TableName = TableN

Conn = New OleDb.OleDbConnection(ConnString)
Comm = New OleDb.OleDbCommand("select maxnumber from everynum where tablename= '" & TableN & "'", Conn)
Conn.Open()
TrnOle = Conn.BeginTransaction()
Comm.Transaction = TrnOle
DR = Comm.ExecuteReader
Do While DR.Read
EveId = DR(0)
Loop
'Conn.Close()
End Function

Public Sub Choose(ByVal Num As Integer)
If Num = 1 Then
ConnString = "provider=microsoft.jet.oledb.4.0;data source =" & Server.MapPath("aaa.mdb")
ElseIf Num = 2 Then
ConnString = "provider=microsoft.jet.oledb.4.0;data source =" & Server.MapPath("..\data\aaa.mdb")
ElseIf Num = 3 Then
ConnString = "provider=microsoft.jet.oledb.4.0;data source =" & Server.MapPath("..\..\data\aaa.mdb")
End If
Chen = Num
'ConnString = "Provider=SQLOLEDB.1;Password=z520;Persist Security Info=True;User ID=sa;Initial Catalog=apzz;Data Source=10.5.70.253;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=10.5.70.253;Use Encryption for Data=False;Tag with column collation when possible=False"
'ConnString = "Provider=MySQLProv.3.0;Data Source=apzz;User ID=zrsw;Password=z520"
End Sub


Public Sub updata()
Conn = New OleDb.OleDbConnection(ConnString)
Comm = New OleDb.OleDbCommand(SqlString, Conn)
Try
Conn.Open()
Comm.ExecuteNonQuery()
If AddYN = True Then
GetNum.add()
TrnOle.Commit()
End If
DoYes = True
Back = "添加成功"
Catch exp As Exception
TrnOle.Rollback()
DoYes = False
Back = exp.ToString
Finally
If Conn.State = ConnectionState.Open Then
Conn.Close()
End If
End Try
End Sub

然后我再程序中调用它:
Dim Conne As New connec
Conne.Choose(3)
Conne.AddYN = True
Conne.GetIdTN("Mend")
Conne.SqlString = String.Format("insert into Mend(id,patrolid,actualtime,filltime,mender,explain,ApplyYN,filler) values('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}')", Conne.EveId, PatrolId, MendTime, FillTime, Mender, Explain, MendApply, Session("name"))
Conne.updata()
错误提示为:Transaction已经结束。出错行为:TrnOle.Commit()。
谢谢!
回复
saucer 2004-11-07
show your code
回复
simonzone 2004-11-07

这样做当然不行啦。
-----------------------------------
也没什么不行的。
回复
BeginnerBBB 2004-11-07
回复
commonmood 2004-11-07
没必要加表everyid,如果要得到work中最大的id,可以用sql先查出来,比如:
select id top 1 from work order by id desc,
transaction在command中使用应该方便点吧,不要用goto之类的
回复
swzheng 2004-11-07
这个问题还是没有解决.
我用的上OleDbDataAdapter来取出id .在connection.BeginTransaction() 的时候,他错误提示是:“当分配给命令的连接处于挂起的本地事务中时,命令必须具有事务对象才能执行。该命令的 Transaction 属性尚未初始化”
是不是Transaction必须要用在command中才能使用了?
回复
listhome 2004-11-07
那自增长烈不是没有用了?
回复
swzheng 2004-11-07
如果系统从新格盘的话,在里面从零开始添加了记录.而本来的原始记录也有从零开始的.那么就没法把它们导入到一起了.
回复
wangrenda 2004-11-07
导入导出有什么不方便?
回复
swzheng 2004-11-07
自动增加的话,有很多不方便,不如数据的导入导出等。
用这种方法我觉得挺好的。
我试试saucer(思归) 的方法。
不过我使用vb.net 写的,所以得改一下。
回复
smallfools 2004-11-06
晕啊!
这样做当然不行啦。
感觉你的数据库设计有问题。everyid这个表不要了。work表里加个ID的字段,让它自动增长就可以了。
回复
saucer 2004-11-06
write a stored procedure, do something like

....

DECLARE @intErrorCode INT
DECLARE @id INT

BEGIN TRAN
SELECT @id = maxid from everyid
set @id = @id + 1

Insert INTO Work (id, .....) Values (@id,....)

SELECT @intErrorCode = @@ERROR
IF (@intErrorCode <> 0) GOTO PROBLEM

Update everyid set maxid = @id

SELECT @intErrorCode = @@ERROR
IF (@intErrorCode <> 0) GOTO PROBLEM

COMMIT TRAN

PROBLEM:
IF (@intErrorCode <> 0) BEGIN
PRINT 'Unexpected error occurred!'
--RAISERROR('some error', 16, 1)
ROLLBACK TRAN
END

note, this might affect the performance if you have a lot of concurrent users
回复
相关推荐
发帖
.NET技术社区
创建于2007-09-28

5.8w+

社区成员

.NET技术交流专区
申请成为版主
帖子事件
创建了帖子
2004-11-06 10:52
社区公告
暂无公告