问题两个
1 时间戳如何传递?
2 我的代码是否可行?
以上虽然是两个问题,但是实质是一个昨天,在csdn和google baidu,搜索了一下午
大都一笔带过,所以我想多问问开发平台vs2005+sqlserver2005
vs2003+sqlserver2000
我想用时间戳来处理并发
就是最常见的一种情况:
user1 取出了row1
user2 也取出了row1
user1 修改后,点击button,向数据库提交修改数据
user2 也做了修改,在user1之后,这个时候,要告诉user2,如果你修改,则将把user1的数据覆盖
是否继续修改,等等一些类似这样的操作。
总结起来,大概就是这样:
1 select 时间戳
2 保存到前台的某个隐藏控件中
3 送回数据库的时候,将隐藏空间中的时间戳送回去
进行比对:如果等,更新,否则,报错
网上的例句是 sql = "update ... where id=" & id & " and tmstmp=" & tmstmp
这样出来的问题是,如何将隐藏控件中的值,转换为时间戳?因为在比对的时候,string型和时间戳的类型铁定不能比对
面对这个问题,我只能这么做,所以想求证,如下做可以吗?代码如下:1 取出时间戳
string sql = "select AdminAccount,AdminPwd,convert(bigint,optimistic) as optimistic from Admin";
或者 string sql = "select AdminAccount,AdminPwd,optimistic+0 as optimistic from Admin";2 保存到隐藏控件中,我的是gridview的某一隐藏列
3 送回数据库,此处是重点:public int AdminUpdate(string id, string pwd, string timestamp)//我说过了,因为无法比对时间戳类型,所以我只能比对string
{
//timestamp:从隐藏控件中传回来的值
int rowsAffected = 10;
string ts = tstamp(id);//在更新之前,再次通过id取得时间戳
if (string.Compare(ts, timestamp).Equals(0))
{
string sql = string.Format("update Admin set AdminPwd = '{0}' where AdminAccount = '{1}'", pwd, id);
using (SqlConnection conn = new SqlConnection(constring))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
//cmd.ExecuteNonQuery();
rowsAffected = cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
return rowsAffected;
}
private string tstamp(string id)
{
string ts;
string sql = string.Format("select convert(bigint,optimistic) as optimistic from Admin where AdminAccount = '{0}'",id);
using (SqlConnection conn = new SqlConnection(constring))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
cmd.Dispose();
if (reader.Read())
{
ts = reader[0].ToString();
}
else
{
ts = "0";
}
reader.Close();
return ts;
}
}
1 时间戳如何传递?
2 我的代码是否可行?
以上虽然是两个问题,但是实质是一个昨天,在csdn和google baidu,搜索了一下午
大都一笔带过,所以我想多问问开发平台vs2005+sqlserver2005
vs2003+sqlserver2000
我想用时间戳来处理并发
就是最常见的一种情况:
user1 取出了row1
user2 也取出了row1
user1 修改后,点击button,向数据库提交修改数据
user2 也做了修改,在user1之后,这个时候,要告诉user2,如果你修改,则将把user1的数据覆盖
是否继续修改,等等一些类似这样的操作。
总结起来,大概就是这样:
1 select 时间戳
2 保存到前台的某个隐藏控件中
3 送回数据库的时候,将隐藏空间中的时间戳送回去
进行比对:如果等,更新,否则,报错
网上的例句是 sql = "update ... where id=" & id & " and tmstmp=" & tmstmp
这样出来的问题是,如何将隐藏控件中的值,转换为时间戳?因为在比对的时候,string型和时间戳的类型铁定不能比对
面对这个问题,我只能这么做,所以想求证,如下做可以吗?代码如下:1 取出时间戳
string sql = "select AdminAccount,AdminPwd,convert(bigint,optimistic) as optimistic from Admin";
或者 string sql = "select AdminAccount,AdminPwd,optimistic+0 as optimistic from Admin";2 保存到隐藏控件中,我的是gridview的某一隐藏列
3 送回数据库,此处是重点:public int AdminUpdate(string id, string pwd, string timestamp)//我说过了,因为无法比对时间戳类型,所以我只能比对string
{
//timestamp:从隐藏控件中传回来的值
int rowsAffected = 10;
string ts = tstamp(id);//在更新之前,再次通过id取得时间戳
if (string.Compare(ts, timestamp).Equals(0))
{
string sql = string.Format("update Admin set AdminPwd = '{0}' where AdminAccount = '{1}'", pwd, id);
using (SqlConnection conn = new SqlConnection(constring))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
//cmd.ExecuteNonQuery();
rowsAffected = cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
return rowsAffected;
}
private string tstamp(string id)
{
string ts;
string sql = string.Format("select convert(bigint,optimistic) as optimistic from Admin where AdminAccount = '{0}'",id);
using (SqlConnection conn = new SqlConnection(constring))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
cmd.Dispose();
if (reader.Read())
{
ts = reader[0].ToString();
}
else
{
ts = "0";
}
reader.Close();
return ts;
}
}
解决方案 »
- 求助gridview合并相同字段的行
- 用户在登录网站后,用什么办法可以追踪到用户登录过哪写页面和用户修改过什么东西?
- 关于sql语句max值的问题,知道的帮忙看一下
- Forms验证问题,帮忙给一个Forms验证的例子,所要的工作是验证登陆页面,访问其他页面,若没有登陆则跳转到登陆(login.aspx),谢谢!!在
- gridview 更新事件
- HTML控件响应事件?
- HyperLinkColumn的点击事件写在哪里呢
- 如何将下面的thml文本,在后台保存为一个Excel文件
- 我对自定义控件中的,自定义事件看了很多遍都不了解!哪位仁兄对此非常清楚,发表见解!
- 为什么在private void InitializeComponent(){},事件有时候会消失?
- 在asp.net中有一个div我给他的背景定了一个背景图片是文件是1.swf的为什么我浏览器显示不出来?路径是对的
- OpenFlashChart 急!
user2 也取出了row1
user1 修改后,点击button,向数据库提交修改数据
user2 也做了修改,在user1之后,这个时候,要告诉user2,如果你修改,则将把user1的数据覆盖
是否继续修改,等等一些类似这样的操作。用事务处理怎么样?
但是如果user1和user2同时打开这个页面,
按照楼主的思路会将时间戳的值保存在user1和user2打开的页面上。并且值是相同的;
在user1修改时,会先去数据库查询当前记录的时间戳,
正巧user2这时候也修改,而user1还来不及执行update,那user2查到的时间戳就和user1是一样了。
那这时候比较的话。就不知道已经被user1修改过了。如果再更新就会覆盖user1的更新了。。问题就是查询时间戳操作和更新操作中间间隔越长,出现这种并发的可能性越大
建议将查询和更新操作不要分开操作。可以
Update Admin set AdminPwd = '{0}' where AdminAccount = '页面上隐藏控件的时间戳'SQL SERVER默认在更新时会加上排它锁,所以在这里不用担心有其他用户与之产生并发。
如果更新操作后,受影响行数为0,说明已经被人更改过了,如果受影响行数大于0,则修改成功。
SqlParameter[] accountParms = GetAccountParameters();
SqlParameter[] profileParms = GetProfileParameters(); signOnParms[0].Value = acc.UserId;
signOnParms[1].Value = acc.Password; SetAccountParameters(accountParms, acc);
SetProfileParameters(profileParms, acc); using (SqlConnection conn = new SqlConnection(SQLHelper.CONN_STRING_NON_DTC)) {
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction()) {
try {
SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_SIGNON, signOnParms);
SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_ACCOUNT, accountParms);
SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_PROFILE, profileParms);
trans.Commit(); }catch {
trans.Rollback();
throw;
}
}
}