【问题标题】:SqlDataAdapter not updating rows in DatabaseSqlDataAdapter 不更新数据库中的行
【发布时间】:2016-02-26 13:29:05
【问题描述】:

我正在使用 SqlDataAdapter 更新我在另一种方法中从数据库中查询的数据表,并且在该方法中更新了列 Status 和 Is_processed。
现在,我希望将这些更改保留(更新)在数据库中。以下是实现的目标:

代码

 batchSize = 10;

string cmd;

    int updatedRows;
    try
    {
        string connString = db.ConnectionString;
        using (SqlConnection conn = new SqlConnection(connString))
        using (SqlDataAdapter adapter = new SqlDataAdapter())
        {
            cmd = "UPDATE IMPORTED_ACCOUNTS SET STATUS = @Status , IS_PROCESSED = @IsProcessed " +
                   ", CREATED_ON = @CreatedOn , CREATED_BY = @CreatedBy , UPDATED_ON = @UpdatedOn , UPDATED_BY = @UpdatedBy " +


 "WHERE CONVENTIONAL_ACCOUNT = @ConAcct";
        adapter.UpdateCommand = new SqlCommand(cmd, conn);
        adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
        adapter.UpdateCommand.Parameters.AddWithValue("@Status", "Status");
        adapter.UpdateCommand.Parameters.Add("@IsProcessed", SqlDbType.Bit, 1, dTable.Columns["IsProcessed"].ColumnName);
        adapter.UpdateCommand.Parameters.Add("@CreatedOn",SqlDbType.DateTime,30, dTable.Columns["CreatedOn"].ColumnName);
        adapter.UpdateCommand.Parameters.AddWithValue("@CreatedBy", dTable.Columns["CreatedBy"].ColumnName);
        adapter.UpdateCommand.Parameters.Add("@UpdatedOn",SqlDbType.DateTime,30, dTable.Columns["UpdatedOn"].ColumnName);
        adapter.UpdateCommand.Parameters.AddWithValue("@UpdatedBy", dTable.Columns["UpdatedBy"].ColumnName);
        adapter.UpdateCommand.Parameters.AddWithValue("@ConAcct", dTable.Columns["ConventionalAccount"].ColumnName);

        cmd = "INSERT INTO IMPORTED_ACCOUNTS ([STATUS],[IS_PROCESSED],[CREATED_ON],[CREATED_BY],[UPDATED_ON],[UPDATED_BY], CONVENTIONAL_ACCOUNT) " +
              "VALUES (@Status , @IsProcessed, @CreatedOn, @CreatedBy, @UpdatedOn, @UpdatedBy, @ConAcct) ";
        adapter.InsertCommand = new SqlCommand(cmd, conn);
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
        adapter.InsertCommand.Parameters.AddWithValue("@Status", dTable.Columns["Status"].ColumnName);
        adapter.InsertCommand.Parameters.Add("@IsProcessed", SqlDbType.Bit, 1, dTable.Columns["IsProcessed"].ColumnName);
        adapter.InsertCommand.Parameters.Add("@CreatedOn", SqlDbType.DateTime, 30, dTable.Columns["CreatedOn"].ColumnName);
        adapter.InsertCommand.Parameters.AddWithValue("@CreatedBy", dTable.Columns["CreatedBy"].ColumnName);
        adapter.InsertCommand.Parameters.Add("@UpdatedOn", SqlDbType.DateTime, 30, dTable.Columns["UpdatedOn"].ColumnName);
        adapter.InsertCommand.Parameters.AddWithValue("@UpdatedBy", dTable.Columns["UpdatedBy"].ColumnName);
        adapter.InsertCommand.Parameters.Add("@ConAcct", SqlDbType.VarChar, 100, dTable.Columns["ConventionalAccount"].ColumnName);

        cmd = "DELETE FROM IMPORTED_ACCOUNTS WHERE CONVENTIONAL_ACCOUNT = @ConAcct";
        adapter.DeleteCommand = new SqlCommand(cmd, conn);
        adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
        adapter.DeleteCommand.Parameters.AddWithValue("@ConAcct", dTable.Columns["ConventionalAccount"].ColumnName);
        adapter.UpdateBatchSize = batchSize;
        updatedRows = adapter.Update(dTable);  // point where code breaks
    }
    return updatedRows;
}
catch (Exception ex)
{
    return 0;
}

错误

catch 块中出现以下错误:

违反主键约束“PK_ACCTS”。无法插入 对象“dbo.IMPORTED_ACCOUNTS”中的重复键。

评论 为什么当它们应该被更新时,它试图在数据库中插入行,因为它们已经存在于数据库中? 当adapter.Update(dTable)方法触发Update而不是Insert时,条件是什么?

想不通... 非常感谢您的帮助!

【问题讨论】:

  • 检查您正在尝试更新的RowStateDataRows。如果他们有Added rowstate - 那么 dataadapter 将尝试插入适当的记录。
  • 我刚刚检查了 RowState 属性,是的,它具有“添加”值。我现在该怎么办?让它为空?
  • 哦,它是一个只读属性。那么我怎样才能阻止它插入“已添加”?

标签: c# .net sql-server ado.net


【解决方案1】:

在 .NET 中,DataAdapter 根据DataRow.RowState 属性进行数据库更改。

如果它有Added 值 - dataadapter 将尝试插入记录。 如果您需要更新记录 - 那么这个属性应该有 Modified 值。

您不能直接设置值 od RowState。例如,当您向 dataTable 添加行时,它已自动设置为 Added

不过,您仍然可以间接修改此值。为此,您应该为需要更新的数据行调用DataRow.AcceptChanges,这会将RowState 设置为Unchanged。然后您应该修改这些数据行中的任何内容,在这种情况下,它们将具有RowState = Modified

【讨论】:

  • 我有一个数据库表,我试图根据用户是否更改项目的描述来更新它。我已经设置了所有适配器和命令构建器以及一个。 if/elseif/then 语句遍历我用作更新表的表,并根据需要将行状态更改为已添加或已修改。但是,数据库项目描述永远不会更新。 Adapter.Update() 插入正常,但从不更新有问题的表。
  • @ARidder101 如果不查看您的实际代码,几乎不可能为您提供帮助。创建一个新问题,提供您的代码示例 - 肯定有人会帮助您解决问题。
  • 我在写完这篇评论后不久就创建了一个问题,在做了一些调试模式代码跟踪之后,我发现了我做错了什么,并在我的问题上发布了答案。我正在使用一个新的 DataTable,它在 null 行中具有先前的值,因此 DataAdapter 忽略了它,因为数据库中没有行具有 null 值。我修改了代码并让它正常运行。 stackoverflow.com/q/50355328/4801036
  • 只是添加到所选答案的末尾,我们也可以通过调用dataTable.AcceptChanges(); dataTable.Rows[i].SetModified();RowState设置为Modified。如果row[i] 具有RowStateAdded,则需要第一个命令,在这种情况下,如果单独执行第二个命令会产生异常。
【解决方案2】:

适配器将根据表中每一行的DataRow.RowState 决定何时插入、更新或删除。 请参阅https://msdn.microsoft.com/es-es/library/system.data.datarowstate(v=vs.110).aspx 了解可能的状态。

填写完DataTable后可以调用DataTable.AcceptChanges方法将所有行标记为不变。

此外,如果您有自动数字 PK,最好使用以下属性在 DataTable 中设置该字段:

  • 自动增量:真
  • 自动增量种子:-1

最后一个确保如果您在数据表中插入新值,新的 ID 值不会与现有的值冲突

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多