【问题标题】:How does DataAdapter.Update() work with Stored ProceduresDataAdapter.Update() 如何与存储过程一起使用
【发布时间】:2015-05-20 09:10:15
【问题描述】:

我正在处理一些遗留代码,试图了解它是如何工作的。

代码有一个MySqlCommand,它调用存储过程来填充DataTable,如下所示:

    _apptCmd = new MySqlCommand("CALL get_appointments(@date)", _systemState.Connection);
    _apptCmd.Parameters.AddWithValue("@date", endDateDte.DateTime.Date);
    _apptDa = new MySqlDataAdapter(_apptCmd);
    _apptDa.Fill(_scheduleDataSet.appointments);
    _apptCb = new MySqlCommandBuilder(_apptDa);

_scheduleDataSet 是一个 c# DataSet 文件,约会是一个在其中配置的 DataTable。我认为这就是更新的原因,但我不知道为什么。

这用于填充用户可以在应用程序中操作的表格。稍后,在完成所有更改后,通过DataAdapter.Update() 函数将更改持久化到数据库中。

    if (_scheduleDataSet.appointments.GetChanges() != null && _apptDa != null)
    {
        if (_apptCb == null)
        {
            _apptCb = new MySqlCommandBuilder(_apptDa);
        }

        _apptDa.Update(_scheduleDataSet.appointments);
    }

调试的时候,所有的命令都是空的,说明有一个变化是UpdateBatchSize的一部分

这段代码工作得很好,但是当没有.Insert().Update() 功能被定义为数据适配器的一部分时,它怎么知道更新数据库中的相应表?

更新

根据要求,我添加了一个消息框来显示更新次数。

【问题讨论】:

  • 你怎么知道有任何变化,我很确定没有任何变化。
  • @PhilipStuyck 我检查了数据库并确认更改已保留。
  • 命令生成器将为您即时生成插入和更新命令。
  • @PhilipStuyck 是否有任何地方的文档?我搜索了 MSDN 并没有看到任何表明这一点的内容。

标签: c# mysql dataadapter


【解决方案1】:

像这样更改代码:

int nbrUpdates = _apptDa.Update(_scheduleDataSet.appointments);
MessageBox.Show(nbrUpdates.toString());

只是为了验证确实确实发生了更新。你这样做了,更新实际上正在发生。伟大的!

commandbuilder 无论如何都会尝试根据提供的 select 命令创建更新和插入命令。但问题是它什么时候会这样做?

当您实例化 commandbuilder 时,它将设置其 dataadapter 属性。像这样:

public DbDataAdapter DataAdapter
{
  get
  {
    return this._dataAdapter;
  }
  set
  {
    if (this._dataAdapter == value)
      return;
    this.RefreshSchema();
    if (this._dataAdapter != null)
    {
      this.SetRowUpdatingHandler(this._dataAdapter);
      this._dataAdapter = (DbDataAdapter) null;
    }
    if (value == null)
      return;
    this.SetRowUpdatingHandler(value);
    this._dataAdapter = value;
  }
}

所以它在某些事件中挂钩。无论如何,在构造函数中,您可能希望它会创建一个更新删除和插入命令,但它没有这样做。 那么它正在创建的命令是什么,它们实际上是什么时候创建的呢? 好吧,正如我所说的,有一些事件已注册,一个 rowupdateinghandler,构建器肯定会监听一些更新事件并会对它们做出反应。但它也有一些有趣的方法:

例如:

public SqlCommand GetInsertCommand()
{
  return (SqlCommand) base.GetInsertCommand();
}

并且用于行更新的事件处理程序是这样的:

protected void RowUpdatingHandler(RowUpdatingEventArgs rowUpdatingEvent)
{
  if (rowUpdatingEvent == null)
    throw ADP.ArgumentNull("rowUpdatingEvent");
  try
  {
    if (rowUpdatingEvent.Status != UpdateStatus.Continue)
      return;
    StatementType statementType = rowUpdatingEvent.StatementType;
    DbCommand dbCommand1 = (DbCommand) rowUpdatingEvent.Command;
    if (dbCommand1 != null)
    {
      DbCommand dbCommand2;
      switch (statementType)
      {
        case StatementType.Select:
          return;
        case StatementType.Insert:
          dbCommand2 = this.InsertCommand;
          break;
        case StatementType.Update:
          dbCommand2 = this.UpdateCommand;
          break;
        case StatementType.Delete:
          dbCommand2 = this.DeleteCommand;
          break;
        default:
          throw ADP.InvalidStatementType(statementType);
      }
      if (dbCommand2 != rowUpdatingEvent.Command)
      {
        dbCommand1 = (DbCommand) rowUpdatingEvent.Command;
        if (dbCommand1 != null && dbCommand1.Connection == null)
        {
          DbDataAdapter dataAdapter = this.DataAdapter;
          DbCommand dbCommand3 = dataAdapter != null ? dataAdapter.SelectCommand : (DbCommand) null;
          if (dbCommand3 != null)
            dbCommand1.Connection = dbCommand3.Connection;
        }
      }
      else
        dbCommand1 = (DbCommand) null;
    }
    if (dbCommand1 != null)
      return;
    this.RowUpdatingHandlerBuilder(rowUpdatingEvent);
  }
  catch (Exception ex)
  {
    if (!ADP.IsCatchableExceptionType(ex))
    {
      throw;
    }
    else
    {
      ADP.TraceExceptionForCapture(ex);
      rowUpdatingEvent.Status = UpdateStatus.ErrorsOccurred;
      rowUpdatingEvent.Errors = ex;
    }
  }
}

您会看到 updatecommand insertcommand 和 deletecommands 即时获取值。

【讨论】:

    【解决方案2】:

    您实际上可以使用 Update 命令指定要更新的表。

    daCountry.Update(dsCountry, "Country");
    

    来源:http://dev.mysql.com/doc/connector-net/en/connector-net-tutorials-data-adapter.html

    此文档:https://msdn.microsoft.com/en-us/library/system.data.idataadapter.update.aspx 是数据适配器规范 - 声明它

    检查 RowState 属性,并为每一行迭代地执行所需的 INSERT、UPDATE 或 DELETE 语句

    基本上,整个事情都是即时生成的。

    【讨论】:

    • 这是有道理的,但代码没有将要更新的表指定为填充命令的一部分。
    • 好吧,imo,如果您不指定要更新的表,它会更新 DS 中的所有表,无论是按名称还是其他条件,它都可以与 DB 表匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 2012-12-01
    • 1970-01-01
    • 2018-07-25
    • 2010-12-11
    • 1970-01-01
    相关资源
    最近更新 更多