我正在处理一些遗留代码,试图了解它是如何工作的。
代码有一个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数据集文件,约会是在其中配置的数据表。我想这就是最新消息,但我不知道为什么。
这用于填充用户可以在应用程序中操纵的表。稍后,在完成所有更改之后,这些更改将通过DataAdapter.Update()函数持久化到数据库中。
    if (_scheduleDataSet.appointments.GetChanges() != null && _apptDa != null)
    {
        if (_apptCb == null)
        {
            _apptCb = new MySqlCommandBuilder(_apptDa);
        }

        _apptDa.Update(_scheduleDataSet.appointments);
    }

调试时,所有命令都为空,这表明一个更改是UpdateBatchSize的一部分
这段代码工作得很好,但是当没有将.Insert().Update()功能定义为dataadapter的一部分时,它如何知道更新数据库中的相应表?
更新
根据要求,我添加了一个消息框来显示更新的数量。

最佳答案

更改代码如下:

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

只是为了确认确实有更新。你这么做了,事实上正在更新。伟大的!
commandbuilder仍将尝试基于提供的select命令创建update和insert命令。但问题是它什么时候能做到?
当您实例化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;
  }
}

所以它牵扯到一些事件中。无论如何,在构造函数中,您可能希望它创建update delete and insert命令,但它没有这样做。
那么它创建的命令是什么?它们实际上是什么时候创建的?
好吧,正如我所说,有一些事件被注册,一个rowupdateinghandler,构建器肯定会监听一些更新事件,并且会对它们做出反应。但它也有一些有趣的方法:
例如:
public SqlCommand GetInsertCommand()
{
  return (SqlCommand) base.GetInsertCommand();
}

用于行更新的eventhandler如下所示:
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和delete命令动态地获得一个值。

关于c# - DataAdapter.Update()如何与存储过程一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29107570/

10-11 18:08