编辑:确实,如果您在 GridView 上使用 AutoGenerateColumns="true" 并通过 SqlDataSource 填充,它会自动将控件的值按名称绑定到 SQL 查询中的适当参数,而无需任何额外代码。但是,我们必须使用GetInsertCommand(true)
,等等,以便命令使用列名(请参见下面的代码,其中我展示了如何使用SqlCommandBuilder
。有一些陷阱,但是正如我在测试中发现的那样:
- 您需要设置
DataKeyNames
GridView
- 您需要
OldValuesParameterFormatString="Original_{0}"
在 sqlDS 上进行设置。
- 如果您只想更新而不比较旧值,则需要
scb.ConflictOption = System.Data.ConflictOption.OverwriteChanges;
您的。SqlCommandBuilder
- 看来,如果您以编程方式在 SqlDataSource 上填充 Select/Update/DeleteCommand,则必须在每次回发时执行此操作。
但是,如果您需要自定义,SqlDataSource
控件会提供事件Inserting
, Updating
,Deleting
您可以在对数据库执行 SQL 操作之前使用这些事件来填充参数:
sqlDS.Updating += new SqlDataSourceCommandEventHandler(sqlDS_Updating);
protected void sqlDS_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
e.Command.Parameters["@Name"].Value = // retrieve value from user entry
}
同样的事情可以通过访问在Inserting
和Deleting
事件中完成e.Command.Parameters[...]
。
请注意,您还可以使用SqlCommandBuilder
该类自动生成适当的删除/插入/更新命令,这样您就不必构建包含所有表的巨大 switch 语句。这是一个例子:
string tableName = ddl.SelectedValue;
string connectionString = ConfigurationManager
.ConnectionStrings["MyConnectionString"].ConnectionString;
string select = "SELECT * FROM [" + tableName + "]";
SqlDataAdapter sda = new SqlDataAdapter(select, connection);
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
sqlDS.SelectCommand = select;
sqlDS.InsertCommand = scb.GetInsertCommand(true).CommandText;
sqlDS.UpdateCommand = scb.GetUpdateCommand(true).CommandText;
sqlDS.DeleteCommand = scb.GetDeleteCommand(true).CommandText;
这当然需要您的所有表都具有可用于生成相关更新和删除语句的主键。如果没有,您将收到有关动态 SQL 生成的异常。即使由于在数据库引擎上查找模式的运行时成本而您不喜欢这种方法,您也可以始终使用 T4 模板预先生成它们,而不是手动输入它们。