当传递包含已修改行的DataRow集合时,更新需要有效的UpdateCommand。

18

上周我曾让它工作了。至少,我当时是这么认为的!DataGridView更新

然后今天我再次开始处理这个项目,却出现了以下问题:

传递了包含已修改行的DataRow集合时,更新需要有效的UpdateCommand。

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

StagingTableAdapter有一个额外的查询,该查询将“filter”作为参数。该查询用于填充DataGridView。在创建该查询的向导中,我看到“更新已生成”。我发现大多数帖子都要求使用命令构建器生成更新语句来解决此错误。那我该怎么办?

12个回答

29

当你在更新表格时,如果该表没有定义主键,也会显示此消息。


你甚至可以添加一个带有主键的新行 - 只有更新/删除会失败。 - MrTelly
我花了好几个小时才弄明白这个问题。这是我自己的一个愚蠢错误。谢谢。 - braX

17

我遇到了和Sam一样的问题。我的代码原本是正常工作的,但突然间就无法正常运行了。当我编写代码时并不知道,但它一定是自动推断更新命令,然后停止了。可能是微软在版本之间发布了一个我们没有注意到的服务包。不管怎样,我发现的解决办法是使用一个(在我的情况下是针对Oracle数据库的)OracleCommandBuilder,该构建器以DataAdapter(在调用fill方法之后)为参数传递给构造函数,然后调用GetUpdateCommand()方法,并将其分配给DataAdapter的UpdateCommand属性。

pseudocode:

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

这对我使用SQLiteCommandBuilder(当然,我正在使用SQLiteDataAdapter)起作用。 - styfle
这对我也适用,使用Postgresql和NpgsqlDataAdapter。 - Kvothe
1
可能有些多余,但这也适用于SqlCommandBuilder和SqlDataAdapter。 - user230910

9
丹的解决方法对我有用,但是我可以使用SqlCommandBuilder而不是OracleCommandBuilder:
DataAdapter da = new DataAdapter(...)
...
da.Fill();
da.UpdateCommand = new SqlCommandBuilder(da).GetUpdateCommand();
...
da.Update();

9
错误很明显:适配器需要一个有效的SQL更新语句。数据集设计师和命令生成器可以为您生成这些语句,但手工编写SQL也没有问题。无论如何,您需要验证(调试器)更新语句是否已配置以及它实际上是什么。这可能更多是SQL而不是C#的问题。
编辑:命令生成器工具只能处理直接、单表的Select语句。使用Join或任何高级操作都得自己动手。

3
正如其他人所说,您需要确保在表上设置了主键,以便自动生成更新代码。我已经这样做了,但仍然看到相同的消息:
“当传递带有修改行的 DataRow 集合时,更新要求有效的 UpdateCommand。”
然后我发现您还需要刷新表适配器(当您考虑它时是有意义的!)。
在执行此操作时,也值得再次检查是否选择了“生成插入、更新和删除语句”选项(如下所示)。

enter image description here

然后只需按照向导的步骤进行操作,最终屏幕应该确认它将创建所需的代码(现在包括主键):

enter image description here


谢谢您的回答!无论我是否添加主键,当我进入高级选项时,“刷新数据表”这个最后一个复选框甚至都没有启用!您知道如何启用它吗?谢谢! - manooooh
@manooooh - 对不起,我不知道,你确定已经做出了更改吗?我唯一能想到的是向导认为没有任何更改,因此禁用了复选框。 - d219
哦 :(. 我已经保存了所有更改(在数据集编辑器中创建 PK),关闭了我的 Visual Studio 应用程序并重新打开它,看到 PK 已创建,但复选框未启用。 - manooooh
只是想澄清一下:DB 是在 MS Access 2007 上制作的,只有一个表格,连接是使用 VS 2010 助手完成的,我正在使用 VB.NET 进行工作。此外,我尝试使用不同的名称保存来自 Access 的 DB 并建立新连接,但问题仍然存在。对于来自 Access 的新 DB,问题得到了解决。也许我的 DB 已经损坏了? - manooooh
1
我以前使用过 MS SQL - 时间有些久远,所以恐怕我记不清具体细节了。 - d219

2

我刚刚遇到了同样的问题,Jason的答案对我起作用了:我忘记为我的表分配主键。

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


直到我发布了答案后才看到这个,但你是对的;代码需要重新创建 - 你实际上不需要删除原始表,只需再次运行向导即可(但我猜两者所需时间差别不大!) - d219

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

0
你可以通过创建一个新的方法来读取数据库来实现它。
    public void Write(DataTable table) 
    {
     string selectStatement = "SELECT TOP (1000) [ID], [Artist], [Title], 
     [Album][Path] FROM [Prueba].[dbo].[Playlist]"; 
     SqlDataAdapter adapter = new SqlDataAdapter();
     adapter.SelectCommand = new SqlCommand(selectStatement, Connection); 
     SqlCommandBuilder sqlCommand = new SqlCommandBuilder();
     sqlCommand.DataAdapter= adapter;
     adapter.Update(table);
   }

:)


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到更多有关如何编写好答案的信息。 - Community

0

从页面上看:

注意:如果主查询中有足够的信息,则在生成TableAdapter时,默认情况下会创建InsertCommand、UpdateCommand和DeleteCommand命令。 如果TableAdapter的主查询不是单个表选择语句,则可能设计器将无法生成InsertCommand、UpdateCommand和DeleteCommand。 如果没有生成这些命令,执行TableAdapter.Update方法时可能会收到错误消息。

所以我可以确定,应该已经生成了这些语句。 我正在使用单个表。


1
请注意,对于没有主键的表,无法生成UPDATEDELETE语句。我遇到了同样的问题,数据库表中省略了PK,TableAdapter-Wizard未能生成UPDATE命令,导致上述行为发生。 - froeschli

0

我也遇到了同样的问题,得到了以下解决方案。请尝试。

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());           
    }
}

你的代码格式不正确,请进行格式化。 - Rahul Vishwakarma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接