日期:2014-05-19  浏览次数:20925 次

ADO.Net 并发冲突 异常
数据库中有表   table1[int   工号,int   状态],其中   aaa   为主键。
内存中有与之对应的表,初始时Rows.Count=0。
当收到一个   工号   时,首先   查询数据库中有没有此工号的记录,如果没有则添加记录,如果有则修改记录。我的语句如下

DataTable   t;
void   form1_Load(object   sender,   System.EventArgs   e)
{
        t=dber.CreateDataTable( "select   工号,状态   from   table1   where   'a '= 'b ' ")//根据SQL语句创建   DataTable。“where   'a '= 'b '”一个不可能的条件,为了使Rows.Count=0。
        t.PrimaryKey=new   DataColumn[]{t.Columns[ "工号 "]};
}
void   收到工号(int   工号,int   状态)
{
        DataRow   row=t.Rows.Find(工号);
        if(row==null)
        {
                row=t.Rows.Add(now   object[]{工号,0});//状态不会为0
                row.AcceptChanges();//DataRowState.Unchanged
                row[ "状态 "]=状态;//DataRowState.Modified
                dber.Update(row);//★这里出错。
        }
        else
        {
                row[ "状态 "]=状态;
                dber.Update(row);
        }
}




------解决方案--------------------
1。
虽然搞不大懂 DataSet 和 DataAdapter.Update ,但是基本明白懂 lZ 的 “策略”了,


2。
这时如果我用 dataadapter.Update()会出错,因为数据库中已经有了ID=2的行。
所以我就将 行(2,d)的状态改为Modified。
然后再dataadapter.Update(),这样 行(2,d)所运用的SQL就是更新语句了。
=========
事实上, LZ 这个“策略”确实有点 “hack”,

为什么呢? 因为你这样会导致并发冲突!!!
而且,你是自己跟自己并发了,当然数据库不理解你和自己,
数据库还是认为你和自己是两个人,

我们举 你 和 我 哈,
比如你和我,你读取了数据库的数据,而我在你更新之前也读取了数据准备修改(假设乐观锁),此时我们的数据是一样的,如下,

ID str
---------
1 a
2 b
3 c

然后我们做同样的操作,你准备更新

ID str
--------
2 d --------行状态为 Added
4 e --------行状态为 Added

而我准备更新

ID str
--------
2 Z --------行状态为 Added
4 e --------行状态为 Added

假如,我动作比你跨,我执行了更新之后,你在执行,那么你说最后的 ID =2 的 str 列数据是什么呢? 我的更新被你覆盖了啊??????


3。
问题是行的状态该了,但是dataadapter.Update()却发生“ADO.Net 并发冲突” 异常
=============
明白了没有?