数据库中有表 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);
}
}
内存中有与之对应的表,初始时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);
}
}
解决方案 »
- 关于C#生成的exe文件的小疑惑
- 配置开发与编码开发的区别?
- c# repeater中判断
- 大家帮忙看看这个异常出现在哪?我定义了范围,可还是说有异常!在线等答案!
- 这个函数,怎么调用哪!protected virtual string FileName(string cf)
- ◆如何让一个Winform应用程序(test.exe)执行时,接收参数??◆
- 高手求助啊!!!!谁来看看这是什么问题?
- C#界面怎样产生类似于excel表的输入文本格式
- 有个广播站,想实现其广播内容在网上在线播放,如何做?
- 两个.net软件安装的问题
- c#自动打印excel
- 急急急!在线等。DLL参数传递。C# []string传递到C++ DLL string[].怎么传啊?
{
row=t.Rows.Add(now object[]{工号,0});//状态不会为0
dber.Update(row);//★这里出错。
row.AcceptChanges();//DataRowState.Unchanged
row["状态"]=状态;//DataRowState.Modified
}
-----------------------------------
table1中已经有了相同的行,如果先Update则会主键冲突(执行 Insert 语句),我是想修改记录。
--------------------------------------------------------------------------------
你rows.add之后,数据库中又没有添加新纪录,怎么会已经存在相同的行?数据库不添加纪录你怎么修改纪录??dber到底是什么对象,他的update方法是执行的什么操作?是不是dataadapter的update方法的包装?
靠那句DataRow row=t.Rows.Find(工号);?这个不是查找内存的?
还是举个例子吧:
数据库中有:
ID str
---------
1 a
2 b
3 c内存中的表初始为空,运行一段时间后:
ID str
--------
2 d --------行状态为 Added
4 e --------行状态为 Added
这时如果我用 dataadapter.Update()会出错,因为数据库中已经有了ID=2的行。
所以我就将 行(2,d)的状态改为Modified。
然后再dataadapter.Update(),这样 行(2,d)所运用的SQL就是更新语句了。问题是行的状态该了,但是dataadapter.Update()却发生“ADO.Net 并发冲突” 异常
虽然搞不大懂 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 并发冲突” 异常
=============
明白了没有?
事实,
DataAdapter.Update() 内部使用的 update 语句 where 子句会带一个版本参数的控制,有点像UPDATE tableName str='hello' WHERE ID=2 AND Version=@Verion而这个 Version 的值,你从数据库 SELECT 出来的时候读出来的,当用你的策略,通过给 DataTable 添加一个行数据以存在的记录 ID=2,然后修改 RowState,想“骗”过数据库,但是你没有 Version , Update 的时候,数据库会检查 Update WHERE 子句中的 Version 与 数据库的值是否相同,如果不同,就是发生了 并发冲突 ,
然而,好像是可以关闭 DataAdapter 这个并发策略的控制的,具体的我就不清楚了,查查看了,
但是这会导致真正的多用户并发问题,慎重考虑之。
关于版本控制的问题,Version 列有多种实现方式,最常见的就是使用时间戳。