【问题标题】:Update requires a valid UpdateCommand when passed DataRow collection with modified rows当传递带有修改行的 DataRow 集合时,更新需要有效的 UpdateCommand
【发布时间】:2010-10-09 22:57:29
【问题描述】:

所以我上周进行了这项工作。至少,我以为我做到了! DataGridView Update

然后我今天又开始做这个项目了,我得到了

在传递 DataRow 集合时,更新需要有效的 UpdateCommand 修改后的行。

开启

scDB.SSIS_Configurations_StagingDataTable table = (scDB.SSIS_Configurations_StagingDataTable)stagingGrid.DataSource;
myStagingTableAdapter.Update(table);

StagingTableAdapter 有一个附加查询,它以“过滤器”作为参数。那是用来填充DataGridView。在创建该查询的向导中,我看到“生成了更新”。我看到大多数带有此错误的帖子都需要使用命令生成器生成更新语句。我该怎么办?

【问题讨论】:

    标签: c# .net tableadapter


    【解决方案1】:

    当您没有在要更新的表上定义主键时,也会显示此消息。

    【讨论】:

    • 即使使用主键,您也可以添加新行 - 更新/删除失败
    • 我花了好几个小时才弄明白。对我来说这是一个多么愚蠢的错误。谢谢。
    【解决方案2】:

    我遇到了和 Sam 一样的问题。我的工作代码突然不再工作了。不知道什么时候写的,应该是自动推断更新命令,然后就停止了。也许是我们从未注意到的版本之间的 MS 服务包。无论如何,我遇到的解决方案是使用(在我的情况下为 oracle)一个 OracleCommandBuilder,它将 DataAdapter(在调用填充之后)作为构造函数的参数,然后调用 GetUpdateCommand() 并将其分配给 DataAdapter 上的 UpdateCommand。

    pseudocode:
    
    DataAdapter da = new DataAdapter(...)
    ...
    da.Fill();
    da.UpdateCommand = new OracleCommandBuilder(da).GetUpdateCommand();
    ...
    da.Update();
    

    【讨论】:

    • 这适用于我的 SQLiteCommandBuilder(当然我使用的是 SQLiteDataAdapter)。
    • 这也适用于我使用 Postgresql 和 NpgsqlDataAdapter
    • 可能是多余的,但这也适用于 SqlCommandBuilder 和 SqlDataAdapter
    【解决方案3】:

    这个错误很明确:适配器需要一个有效的 SQL 更新语句。数据集设计器和 CommandBuilders 将为您生成这些,但手工编写一些 SQL 也没有错。

    无论如何,您必须验证(调试器)Update 语句是否仍然配置以及它实际上是什么。它可能更像是一个 SQL 而不是 C# 问题。

    编辑:Command Builder 工具将只处理直接、单表、Select 语句。使用 Join 或任何花哨的东西,你就靠自己了。

    【讨论】:

      【解决方案4】:

      Dan 的解决方法对我有用,但我可以使用 SqlCommandBuilder 代替 OracleCommandBuilder:

      DataAdapter da = new DataAdapter(...)
      ...
      da.Fill();
      da.UpdateCommand = new SqlCommandBuilder(da).GetUpdateCommand();
      ...
      da.Update();
      

      【讨论】:

        【解决方案5】:

        正如其他人所说,您需要确保在表上设置了主键,以便创建自动生成的更新代码。我这样做了,但仍然看到相同的消息

        在传递 DataRow 集合时,更新需要有效的 UpdateCommand 修改后的行。

        然后我发现您还需要刷新表适配器(仔细想想,这很有意义!)。

        在您执行此操作时,可能还需要仔细检查您是否选择了生成插入、更新和删除语句选项(如下所示)。

        然后只需单击向导,最终屏幕应确认它将创建所需的重做代码(现在使用主键):

        【讨论】:

        • 感谢您的回答!无论我是否添加主键,当我转到高级选项时最后一个复选框“刷新数据表”甚至都没有启用!你知道如何启用它吗?谢谢!
        • @manooooh - 我不害怕,你确定做出改变了吗?我唯一能想到的是,向导不相信有任何改变,所以复选框被禁用了。
        • 哦 :(。我已保存所有更改(在数据集编辑器中创建 PK),关闭我的 Visual Studio 应用程序并重新打开它,看到创建的 PK 并且未启用复选框。
        • 澄清一下:数据库是在 MS Access 2007 上创建的,只有一个表,连接是使用 VS 2010 助手完成的,我正在使用 VB.NET。此外,我尝试使用不同的名称从 Access 中保存数据库并建立新连接,但问题仍然存在。 使用 Access 中的新数据库,问题就解决了。 也许我的数据库已损坏?
        • 我使用的是 MS SQL - 这是很久以前的事了,所以我不记得详细信息了
        【解决方案6】:

        我刚刚遇到了同样的问题,Jason 的回答确实对我有用:我忘记为我的表分配主键。

        再补充一点提醒:纠正表中的问题后,返回Visual Studio时,在包含数据集的.xsd文件中,确保删除原始表并从服务器重新添加资源管理器或数据库资源管理器。否则错误仍然存​​在。

        【讨论】:

        • 直到我发布我的答案后才看到这个,但你是对的;代码需要重新创建-您实际上不需要删除原始表,只需再次注意向导即可(但我猜两者的时间差异不大!)
        【解决方案7】:

        您应该始终有一个主键定义的列字段。否则问题永远存在。如果您没有主键字段,SqlCommandBuilder 将无法帮助您。

        【讨论】:

          【解决方案8】:

          我也遇到了同样的问题并得到了以下解决方案。试试看。

          private void btnSave_Click(object sender, EventArgs e)
          {
              ConnStr = "Data Source=FIN03;Initial Catalog=CmsTest;Integrated Security=True";
              cn = new SqlConnection(ConnStr);
              cn.Open();
              SqlCommand cmd = new SqlCommand();
              cmd.Connection = cn;
              mytran = cn.BeginTransaction(IsolationLevel.Serializable );
          
              cmd.Transaction = mytran;
              try
              {
          
                  scb = new SqlCommandBuilder(da);
                  da.Update(ds, "tblworker");
                  mytran.Commit ();
                  MessageBox.Show("Data update successfully"); 
          
              }
              catch (Exception err)
              {
          
                     mytran.Rollback();
          
                      MessageBox.Show(err.Message.ToString());           
              }
          }
          

          【讨论】:

          • 您的代码格式不正确。请格式化。
          【解决方案9】:

          从页面:

          注意如果主查询中有足够的信息, 创建 InsertCommand、UpdateCommand 和 DeleteCommand 命令 默认情况下,在生成 TableAdapter 时。如果 TableAdapter 的 主查询是多于一个表的 SELECT 语句,它是 设计者可能无法生成 InsertCommand, 更新命令和删除命令。如果没有生成这些命令, 执行 TableAdapter.Update 时可能会收到错误消息 方法。

          所以据我所知,这些语句应该已经生成。我正在使用一张桌子。

          【讨论】:

          • 请注意,没有主键的表无法生成UPDATEDELETE 语句。刚遇到同样的问题,数据库表省略了PK,TableAdapter-Wizard未能生成UPDATE命令,导致上述行为。
          【解决方案10】:

          您可以对任何表格使用以下代码,它会自动为您生成插入、更新和删除命令。

          private void savechanges(String tbl, SqlDataAdapter sqldap, DataSet dset)
              {
          
                  try
                  {
                      SqlCommandBuilder scb = new SqlCommandBuilder(sqldap);
                      scb.ConflictOption = ConflictOption.CompareRowVersion;
                      sqldap.Update(dset, tbl);
                      dset.AcceptChanges();
                  }
                  catch (Exception ex)
                  {
                      MessageBox.Show(ex.Message.ToString());
                  }
              }
          

          【讨论】:

            【解决方案11】:

            您所要做的就是编辑数据库并确保至少有一列被标识为主键

            在我的简单示例中,这可能是名称列 - 尽管更现实地我会添加一个自动编号的标识列,这将确保该列中的所有值都是唯一的。

            重新保存所有内容,重新创建一个新的 DataSet,像以前一样使用拖放替换 DataGridView,一切顺利。

            像往常一样,当你知道答案时,答案很简单——当你不知道时,非常令人沮丧。

            Source.

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-12-23
              • 2013-09-05
              • 2014-07-10
              • 2011-05-05
              • 2016-04-18
              • 2016-01-13
              • 2016-10-11
              相关资源
              最近更新 更多