none
遇到一个DataSet的Update问题 RRS feed

  • 问题

  • 如果往DataSet中添加一条记录,然后Update
    然后再在DataSet中删除这条记录,然后再Update
    为什么会出现"违反并发性: DeleteCommand 影响了预期 1 条记录中的 0 条。"的错误提示呢?

    设置了.AcceptChangesDuringUpdate = True也还是出现一样的提示。


    我的代码是设置了DataGridView1.DataSource = BindingSource来显示数据的,
    而BindingSource.DataSource = DataSet
    BindingSource.DataMember = "表名"
    2009年1月31日 6:05

答案

  • 如果是绑定  应该id会自动填写一个 小于0的整数
     把id <0的那个行删除掉  应该就可以了
    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555
    2009年2月1日 16:24

全部回复

  • 想了想,这个跟自动编号字段有没有关系呢?
    2009年1月31日 6:11
  •  DataSet删除之前刷新了没,找不到数据
    http://feiyun0112.cnblogs.com/
    2009年1月31日 6:18
    版主
  • 做实验才能回答,要做实验只有下班回家
    不重要的其实最重要
    2009年1月31日 6:30
  • feiyun0112 说:

     DataSet删除之前刷新了没,找不到数据


    http://feiyun0112.cnblogs.com/



    怎样刷新?
    不应该是.AcceptChanges()对吧?
    还是重新调用Fill?这个怕效率会比较低

    在哪个时候刷新?在添加记录的时候Dataset的Update语句之后,还是DataGridView1.RowsRemoved之前?

    谢谢:)
    2009年1月31日 7:03
  •  并发错误  是因为你在调用 delete 的时候 找不到数据

     

    找不到数据的原因 是因为  insertcommand  没有写全  没有把 自动更新的最后一条更新到数据集合中  这样没有办法把行的内容

     

    所以insertcommand 里面  不但要写  insert into

    还需要写一个  select

     

    比如

     INSERT INTO [dbo].[Table1] ([aaabbb]) VALUES (@aaabbb);
    SELECT id, aaabbb FROM Table1 WHERE (id = SCOPE_IDENTITY())

     

     

     

    如果不是自动id  也需要一个 select  因为有一些触发器  自动值  可能影响并发

    INSERT INTO [dbo].[aspnet_Users] ([ApplicationId], [UserId], [UserName], [LoweredUserName], [MobileAlias], [IsAnonymous], [LastActivityDate]) VALUES (@ApplicationId, @UserId, @UserName, @LoweredUserName, @MobileAlias, @IsAnonymous, @LastActivityDate);


    SELECT ApplicationId, UserId, UserName, LoweredUserName, MobileAlias, IsAnonymous, LastActivityDate FROM aspnet_Users WHERE (UserId = @UserId)

     

    如果你拿不准怎么写  insert command

    请用结构化数据集 的 Tableadepter  或者sqlhelper 生成


    卑鄙是卑鄙者的通行证 技术需要通行证
    2009年1月31日 8:11
  • InsertCommand 我不是自己写的,我使用的代码是这样的
    Private Function CreateCustomerAdapter(ByVal TableName As StringAs OleDbDataAdapter      
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter("Select * From " & TableName, Connection)      
    Dim objcmdBuilder As OleDbCommandBuilder = New OleDbCommandBuilder(Adapter)      
    4 Adapter.UpdateCommand = objcmdBuilder.GetUpdateCommand     
    5 Adapter.InsertCommand = objcmdBuilder.GetInsertCommand       
    6 Adapter.DeleteCommand = objcmdBuilder.GetDeleteCommand      
    7        
    8 Adapter.Fill(DBDataSet, TableName)      
    Return Adapter     
    10 End Function     




    不知道这样的话应该怎么修改呢?
    谢谢:)
    2009年1月31日 8:47
  •  
    abcjackson 说:

    InsertCommand 我不是自己写的,我使用的代码是这样的

     

    Private Function CreateCustomerAdapter(ByVal TableName As String) As OleDbDataAdapter
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter("Select * From " & TableName, Connection)
    Dim objcmdBuilder As OleDbCommandBuilder = New OleDbCommandBuilder(Adapter)
    Adapter.UpdateCommand objcmdBuilder.GetUpdateCommand<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 
    Adapter.DeleteCommand = objcmdBuilder.GetDeleteCommand
    Adapter.Fill(DBDataSet, TableName)
    Return Adapter
    End Function 



    不知道这样的话应该怎么修改呢?
    谢谢:)



    不知道你的表结构哦

    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 

    按照道理说 commandbuilder是可以生成 自动流水更新语句的
    可能是自动生成的流水ID字段 没有设置为主键  所以 commandbuilder 没有办法生成select
    你在这一句后面 增加一句
    console.write (Adapter.InsertCommand.CommandText)  让我看看生成了什么语句好么




    或者可以先实验下

    Adapter.InsertCommand.CommandText = Adapter.InsertCommand.CommandText + " SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())"




    卑鄙是卑鄙者的通行证 技术需要通行证
    2009年1月31日 16:12
  • 韦恩卑鄙 说:

     

    abcjackson 说:

    InsertCommand 我不是自己写的,我使用的代码是这样的

     

    Private Function CreateCustomerAdapter(ByVal TableName As String) As OleDbDataAdapter
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter("Select * From " & TableName, Connection)
    Dim objcmdBuilder As OleDbCommandBuilder = New OleDbCommandBuilder(Adapter)
    Adapter.UpdateCommand objcmdBuilder.GetUpdateCommand<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 
    Adapter.DeleteCommand = objcmdBuilder.GetDeleteCommand
    Adapter.Fill(DBDataSet, TableName)
    Return Adapter
    End Function 



    不知道这样的话应该怎么修改呢?
    谢谢:)



    不知道你的表结构哦

    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 

    按照道理说 commandbuilder是可以生成 自动流水更新语句的
    可能是自动生成的流水ID字段 没有设置为主键  所以 commandbuilder 没有办法生成select
    你在这一句后面 增加一句
    console.write (Adapter.InsertCommand.CommandText)  让我看看生成了什么语句好么




    或者可以先实验下

    Adapter.InsertCommand.CommandText = Adapter.InsertCommand.CommandText + " SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())"




    卑鄙是卑鄙者的通行证 技术需要通行证



    我仔细看了

    生成的InsertCommand.CommandText如下:

    INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?)

    与数据库比较了一下,发现少了一个自动编号的列,不知道这个有没有影响?

    您说的Select子句后面的WHERE限定我不知道该怎么加上去,是不是改成“INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?) SELECT * FROM TableName WHERE (id字段 = ?)”,然后加个@序号?

    2009年1月31日 16:59
  • abcjackson 说:

    韦恩卑鄙 说:

     

    abcjackson 说:

    InsertCommand 我不是自己写的,我使用的代码是这样的

     

    Private Function CreateCustomerAdapter(ByVal TableName As String) As OleDbDataAdapter
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter("Select * From " & TableName, Connection)
    Dim objcmdBuilder As OleDbCommandBuilder = New OleDbCommandBuilder(Adapter)
    Adapter.UpdateCommand objcmdBuilder.GetUpdateCommand<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 
    Adapter.DeleteCommand = objcmdBuilder.GetDeleteCommand
    Adapter.Fill(DBDataSet, TableName)
    Return Adapter
    End Function 



    不知道这样的话应该怎么修改呢?
    谢谢:)



    不知道你的表结构哦

    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 

    按照道理说 commandbuilder是可以生成 自动流水更新语句的
    可能是自动生成的流水ID字段 没有设置为主键  所以 commandbuilder 没有办法生成select
    你在这一句后面 增加一句
    console.write (Adapter.InsertCommand.CommandText)  让我看看生成了什么语句好么




    或者可以先实验下

    Adapter.InsertCommand.CommandText = Adapter.InsertCommand.CommandText + " SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())"




    卑鄙是卑鄙者的通行证 技术需要通行证



    我仔细看了

    生成的InsertCommand.CommandText如下:

    INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?)

    与数据库比较了一下,发现少了一个自动编号的列,不知道这个有没有影响?

    您说的Select子句后面的WHERE限定我不知道该怎么加上去,是不是改成“INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?) SELECT * FROM TableName WHERE (id字段 = ?)”,然后加个@序号?



     SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())
    SCOPE_IDENTITY() 表示最新插入的序号  (sql2000以上)

    ADO.net,很有趣
    2009年2月1日 2:14
  • 韦恩卑鄙 说:

    abcjackson 说:

    韦恩卑鄙 说:

     

    abcjackson 说:

    InsertCommand 我不是自己写的,我使用的代码是这样的

     

    Private Function CreateCustomerAdapter(ByVal TableName As String) As OleDbDataAdapter
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter("Select * From " & TableName, Connection)
    Dim objcmdBuilder As OleDbCommandBuilder = New OleDbCommandBuilder(Adapter)
    Adapter.UpdateCommand objcmdBuilder.GetUpdateCommand<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   
    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 
    Adapter.DeleteCommand = objcmdBuilder.GetDeleteCommand
    Adapter.Fill(DBDataSet, TableName)
    Return Adapter
    End Function 



    不知道这样的话应该怎么修改呢?
    谢谢:)



    不知道你的表结构哦

    Adapter.InsertCommand = objcmdBuilder.GetInsertCommand 

    按照道理说 commandbuilder是可以生成 自动流水更新语句的
    可能是自动生成的流水ID字段 没有设置为主键  所以 commandbuilder 没有办法生成select
    你在这一句后面 增加一句
    console.write (Adapter.InsertCommand.CommandText)  让我看看生成了什么语句好么




    或者可以先实验下

    Adapter.InsertCommand.CommandText = Adapter.InsertCommand.CommandText + " SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())"




    卑鄙是卑鄙者的通行证 技术需要通行证



    我仔细看了

    生成的InsertCommand.CommandText如下:

    INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?)

    与数据库比较了一下,发现少了一个自动编号的列,不知道这个有没有影响?

    您说的Select子句后面的WHERE限定我不知道该怎么加上去,是不是改成“INSERT INTO 表1 (列1, 列2, 列3, 列4) VALUES (?, ?, ?, ?) SELECT * FROM TableName WHERE (id字段 = ?)”,然后加个@序号?



     SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())
    SCOPE_IDENTITY() 表示最新插入的序号  (sql2000以上)

    ADO.net,很有趣



    这个序号是数据库生成的,所以在Update之前我在DataSet这边很难预测这个序号是多少,是一个自动编号字段,
    feiyun0112给的链接说的那样
    2009年2月1日 11:20
  •   SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())
    SCOPE_IDENTITY() 表示最新插入的序号  (sql2000以上)


    我的意思是 不需要你把序号替换SCOPE_IDENTITY()
    SCOPE_IDENTITY()本身就能代表最新的序号 这是一个sql server 内部的函数

    他的结果就是最新自动生成的那个值

    我说清楚了没有?
    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555
    2009年2月1日 12:37
  • 韦恩卑鄙 说:

      SELECT * FROM TableName WHERE (id字段 = SCOPE_IDENTITY())
    SCOPE_IDENTITY() 表示最新插入的序号  (sql2000以上)



    我的意思是 不需要你把序号替换SCOPE_IDENTITY()
    SCOPE_IDENTITY()本身就能代表最新的序号 这是一个sql server 内部的函数

    他的结果就是最新自动生成的那个值

    我说清楚了没有?
    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555



    哦,原来是这样,那如果我的数据库里面是有两个字段都是自动编号的,例如一个是长整数无序编号,一个是GUID编号,或者两个都是长整数无序编号,,或者两个都是GUID编号,那么是不是应该写成:
    SELECT * FROM TableName WHERE(自动编号字段1 = SCOPE_IDENTITY() AND 自动编号字段2 =  SCOPE_IDENTITY())
    2009年2月1日 12:59
  • 我说的 SCOPE_IDENTITY() 是主键状况才能正确查询
     我特意测试了下 sql2k5  如果两个列都是数字 都是主key  无法设置成都是自动增长的.  当你设置一个是自动增长  另一个自然会取消标识
    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555
    2009年2月1日 13:25
  • 韦恩卑鄙 说:

    我说的 SCOPE_IDENTITY() 是主键状况才能正确查询
     我特意测试了下 sql2k5  如果两个列都是数字 都是主key  无法设置成都是自动增长的.  当你设置一个是自动增长  另一个自然会取消标识


    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555



    你说的是SQL2005吗?我不太了解。我是在VB2008里编程,用的是Access的数据库,

    Access的数据表只允许有一个主键,但是可用允许多个字段都用自动编号类型。

    另外,我也试过在用SQL语句调用Access时使用函数,发现Access的SQL 大概似乎可能也许并不是 完全支持全部SQL的函数,不知道是不是我调用的语句有问题,
    SCOPE_IDENTITY()是不是能在这里用我得再试验一下。

    先谢谢啦:)
    2009年2月1日 13:48
  • 哦  access 数据库就不能用这个了

    单独执行下 SELECT * FROM TableName T1 WHERE(自动编号字段 =  ( select max(自动编号字段) from tablename)) 可能比较好

    不过要先把原来的行去掉  然后dataadepter 要把clear before fill 设置为false


    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555
    2009年2月1日 14:23
  • 韦恩卑鄙 说:

    哦  access 数据库就不能用这个了

    单独执行下 SELECT * FROM TableName T1 WHERE(自动编号字段 =  ( select max(自动编号字段) from tablename)) 可能比较好

    不过要先把原来的行去掉  然后dataadepter 要把clear before fill 设置为false


    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555



    那就有点儿郁闷了,我是用代码生成Adpter的,不是自动生成的DataAdpter,没有clear before fill的属性。

    我现在只是
    按照这个属性的做法,也就是先DataSet.Table("表名").Clear,然后再Adpter.Fill(DataSet,"表名"),这样就不会报错了,不过这样做有很多后遗症,效率就是其一,只是临时救急了。

    如果不做DataSet.Table("表名").Clear,直接Adpter.Fill(DataSet,"表名"),则DataSet.Table("表名")里面会有2份一样的记录显示在绑定的DataGridView控件上,不知道该怎么解决好?

    呵呵,先谢谢了:)
    2009年2月1日 15:26
  • 如果是绑定  应该id会自动填写一个 小于0的整数
     把id <0的那个行删除掉  应该就可以了
    最近30天回答问题被论坛清除了 大家踊跃提问 踊跃标记正确 帮我重回top10阿~~~5555
    2009年2月1日 16:24