当前位置:首页 » 多媒体相关

.net的这经典bug


最近在做项目时,发现.net对自动编号的表多条数据进行更新时有个严重bug,导致项目几乎要重做。  
  1、先建这样一个表  
  create   table   tb(id   int   identity   primary   key,  
  value   char(10));  
  2、用.net   ide的服务器资源管理器将这个表拖到窗体上,讲设计器生成的连接命名为con,数据适配器命名为sda,然后右击适配器,将生成的类型化数据集命名为ds  
  3、在窗体上添加添加一个按钮button1,按钮的代码如下:  
  try  
  {  
   
  ds1.clear();  
  for   (int   i=0;i<30;i++)  
  {  
  ds.tbrow   r=ds1.tb.newtbrow();  
  r.beginedit();  
  r.value="aaa";  
  r.endedit();  
  ds1.tb.addtbrow(r);  
  }  
  con.open();  
  }  
  sda.update(ds1.tb);  
  messagebox.show("ok");  
  }  
  catch(system.exception   ex)  
  {  
  messagebox.show(ex.message);  
  }  
  finally  
  {  
  con.close();  
  }  
  4、运行代码,会产生这样的错误  
  列"id"被约束为唯一的,值1已存在  
  5、有时候这种现象会消失,但是如果新建一个表,一定会重复出现。而且最可怕的是,这种现象会不规则的出现。  
  6、以下sql代码可以重建这个表  
  drop   table   tb;  
  create   table   tb(id   int   identity   primary   key,  
  value   char(10));  
  select   count(*)   from   tb  
  7、如果自己用windows生成的sql命令,则可以更新数据,但是会引起删除时的并发错误问题。  
  try  
  {  
   
  ds1.clear();  
  for   (int   i=0;i<30;i++)  
  {  
  ds.tbrow   r=ds1.tb.newtbrow();  
  r.beginedit();  
  r.value="aaa";  
  r.endedit();  
  ds1.tb.addtbrow(r);  
  }  
  con.open();  
  for(int   i=0;i<ds1.tb.count;i++)  
  {  
  sda.insertcommand.parameters["@value"].value=ds1.tb[i].value;  
  sda.insertcommand.executenonquery();  
  }                                               messagebox.show("ok");  
  }  
  catch(system.exception   ex)  
  {  
  messagebox.show(ex.message);  
  }  
  finally  
  {  
  con.close();  
  }  
   
  大家有兴趣可以讨论一下,看有没有办法解决这个大型bug

推荐阅读

  • [视频]Premiere Pro音频编辑:音轨操作 [详细内容]
  • 酷睿2御用平台 17款P965主板横评新天下 磐英 BP1Intel主板 [详细内容]
  • 酷睿2御用平台 17款P965主板横评双敏 UNIKA UP965PN-VIntel主板 [详细内容]
  • [视频]Premiere Pro音频编辑:静音平衡 [详细内容]
  • 关于手机用数据线连接上网的实用方法 [详细内容]
  • 酷睿2御用平台 17款P965主板横评致铭 ZM-PN65-GIntel主板 [详细内容]
  • [视频Premiere Pro音频编辑:电子相册 [详细内容]
  • 网友回答:
    网友:csharplove

    如果确认是bug,最好反馈到微软,希望能使.net更完善

    网友:layershow

    原来如此,前面说的可能不是很对.  
      呵呵,都是个人理解.:)  
       
      我追踪一下每条记录的insert过程  
      问题并不是出在sql语句上.  
      问题出在datatable上  
      确实是偶尔发生  
      这个问题是这样的:  
      因为在datatable中定义了主键,就是id  
      在新建行的时候它没有被手工赋值.  
      于是自动产生一个数字.  
      正如我所说.dataset是脱机操作.并不能知道数据源的目前id  
      可能会被赋值为如下序列:0,1,2,3,4  
      在更新第0条的时候.数据成功了,但是@@identity   是1   因为数据库中是从1   开始的  
      于是自动update要更新第1条数据(id   为   0   这条)  
      datatable的id被设为主键.不能重复.于是datatable不能更新这单条记录  
      与第二条的id重复(这条的id还是1,如果它被insert就会变成2,但是还没有,所以报错)  
      这个错误不是数据库中的错误  
      是datatable本地错误.无法同时允许两个相同id(所有行都update完不会有这种情况)  
      过程如下     (数据库从1   开始,这里是说的datatable中的id)  
      0,1,2,3,4     初始状态  
      1,1,2,3,4     更新第一条报错     有两个1  
      1,2,2,3,4     如此循环下去......但是前面就抛出异常了  
       
      楼主所说的偶尔发生是这种情况  
      datatable中的id是   100,101,102,103  
      数据库中是从1开始的.  
      过程就是:  
      1,101,102,103     更新第一条  
      1,2,102,103     更新第二条  
      1,2,3,103   更新第三条  
      1,2,3,4   更新第四条  
      这样更新到最后也不会出错  
       
      我也不能说这是不是bug了.呵呵.但问题就是这样  
      解决办法就是把生的数据集中   对自增序列的pk去掉  
      允许在datatable中某时刻有重复id(只是瞬间,呵呵)  
       
      一般自增序列是由数据库维护的.不能编辑,定义它为pk没有什么意思.因为必不会重复  
      建议pk就加在别的字段上面吧.  
       
     

    网友:jiezhi

    建議把數據操作(insert,update,delete)寫成自己的方法,讓用戶傳入值,你在方法里面拼裝成sql語句,然后送到數據庫執行之。這樣就不會有什么問題,而且效率也不錯。當然注意數據的操作基本都是在內存中,到提交時候才訪問數據庫。

    .

    讨论区

    Login