DataAdapter.Update() 如何与存储过程一起使用
How does DataAdapter.Update() work with Stored Procedures
我正在处理一些遗留代码,试图了解它是如何工作的。
该代码有一个 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 文件,而appointments 是其中配置的DataTable。我认为这就是更新的原因,但我不知道为什么。
这用于填充用户可以在应用程序中操作的 table。稍后,在完成所有更改后,更改将通过 DataAdapter.Update()
函数持久保存到数据库中。
if (_scheduleDataSet.appointments.GetChanges() != null && _apptDa != null)
{
if (_apptCb == null)
{
_apptCb = new MySqlCommandBuilder(_apptDa);
}
_apptDa.Update(_scheduleDataSet.appointments);
}
调试时,所有的命令都是空的,它表明一个变化是 UpdateBatchSize 的一部分
这段代码工作得很好,但是当没有 .Insert()
或 .Update()
功能被定义为数据适配器的一部分时,它如何知道更新数据库中适当的 table ?
更新
根据要求,我添加了一个消息框来显示更新数量。
像这样更改代码:
int nbrUpdates = _apptDa.Update(_scheduleDataSet.appointments);
MessageBox.Show(nbrUpdates.toString());
只是为了验证确实更新确实发生了。你这样做了,更新实际上正在发生。伟大的!
commandbuilder 无论如何都会尝试根据提供的 select 命令创建更新和插入命令。但问题是它什么时候会这样做?
当您实例化 commandbuilder 时,它将设置其数据适配器 属性。像这样:
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 即时获得一个值。
您实际上可以使用更新命令指定要更新的table。
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
是数据适配器规格 - 说明它
examines the RowState property, and executes the required INSERT, UPDATE, or DELETE statements iteratively for each row
基本上,整个过程都是即时生成的。
我正在处理一些遗留代码,试图了解它是如何工作的。
该代码有一个 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 文件,而appointments 是其中配置的DataTable。我认为这就是更新的原因,但我不知道为什么。
这用于填充用户可以在应用程序中操作的 table。稍后,在完成所有更改后,更改将通过 DataAdapter.Update()
函数持久保存到数据库中。
if (_scheduleDataSet.appointments.GetChanges() != null && _apptDa != null)
{
if (_apptCb == null)
{
_apptCb = new MySqlCommandBuilder(_apptDa);
}
_apptDa.Update(_scheduleDataSet.appointments);
}
调试时,所有的命令都是空的,它表明一个变化是 UpdateBatchSize 的一部分
这段代码工作得很好,但是当没有 .Insert()
或 .Update()
功能被定义为数据适配器的一部分时,它如何知道更新数据库中适当的 table ?
更新
根据要求,我添加了一个消息框来显示更新数量。
像这样更改代码:
int nbrUpdates = _apptDa.Update(_scheduleDataSet.appointments);
MessageBox.Show(nbrUpdates.toString());
只是为了验证确实更新确实发生了。你这样做了,更新实际上正在发生。伟大的!
commandbuilder 无论如何都会尝试根据提供的 select 命令创建更新和插入命令。但问题是它什么时候会这样做?
当您实例化 commandbuilder 时,它将设置其数据适配器 属性。像这样:
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 即时获得一个值。
您实际上可以使用更新命令指定要更新的table。
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 是数据适配器规格 - 说明它
examines the RowState property, and executes the required INSERT, UPDATE, or DELETE statements iteratively for each row
基本上,整个过程都是即时生成的。