我不明白SqlCommandBuilder
如何做到这一点。我有以下代码:
public void TestCommandBuilder()
{
var pubsDataSet = new DataSet("Pubs");
var pubs = ConfigurationManager.ConnectionStrings["PubsConnectionString"];
var connection = new SqlConnection(pubs.ConnectionString);
SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Publishers";
var da = new SqlDataAdapter(cmd);
da.Fill(pubsDataSet, "publishers");
foreach (DataRow row in pubsDataSet.Tables["publishers"].Rows)
{
row["pub_name"] = "Updated " + DateTime.Now.Minute + DateTime.Now.Second;
}
// The variable builder is not used
var builder = new SqlCommandBuilder(da);
da.UpdateBatchSize = 3;
da.RowUpdated += DaRowUpdated;
da.Update(pubsDataSet, "publishers");
}
private void DaRowUpdated(object sender, SqlRowUpdatedEventArgs e)
{
Console.WriteLine("Rows: " + e.RecordsAffected + "\r\n");
}
变量builder
未在任何地方使用,我不会像MSDN那样调用GetUpdateCommand()
方法。我只创建了SqlCommandBuilder
,并将其传递给SqlDataAdapter
。但是代码运行正常。
如果你看一下代码,就好像是行
var builder = new SqlCommandBuilder(da);
可以安全删除。事实上,ReSharper建议删除它。但是如果我这样做,代码就不再运行了,因为SqlDataAdapter
不知道如何执行更新。
在调试模式下,我注意到在执行该行后,SqlDataAdapter
的{{1}}属性仍为UpdateCommand
。从MSDN - 文档中我得到null
将自己注册到SqlCommandBuilder
的{{1}}事件。
但是当触发该事件时它会怎么做? RowUpdated
实际上是在执行更新吗?
我发现其他一些内容,如果我删除SqlDataAdapter
,我的SqlDataBuilder
方法会在SqlCommandBuilder
语句发生InvalidOperationException之前触发一次。我没想到的是。我认为只有当一行实际更新时才会发生DaRowUpdated
事件。
所以...三个具体问题:
da.Update
这样的类是不好的做法,其中代码没有以任何方式表明创建实例正在传递RowUpdated
的内容?答案 0 :(得分:3)
如果您没有使用变量,那么绝对没有必要。如果在 的构造函数中发生了某些事情,你仍然可以调用它:
var builder = new SqlCommandBuilder(da);
应该是:
new SqlCommandBuilder(da);
这应该在不改变代码行为的情况下处理警告。它看起来有点奇怪,如果真的有必要,我会对SqlCommandBuilder
的设计提出质疑。但实际上,这样的用法与普通的方法调用基本相同。
答案 1 :(得分:1)
根据我对这个问题的评论:
public void TestCommandBuilder()
{
var pubs = ConfigurationManager.ConnectionStrings["PubsConnectionString"];
using (var pubsDataSet = new DataSet("Pubs"))
using (var connection = new SqlConnection(pubs.ConnectionString))
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Publishers";
using (var da = new SqlDataAdapter(cmd))
using (new SqlCommandBuilder(da))
{
da.UpdateBatchSize = 3;
da.RowUpdated += DaRowUpdated;
da.Fill(pubsDataSet, "publishers");
foreach (DataRow row in pubsDataSet.Tables["publishers"].Rows)
{
row["pub_name"] = "Updated " + DateTime.Now.Minute + DateTime.Now.Second;
}
da.Update(pubsDataSet, "publishers");
}
}
}
private void DaRowUpdated(object sender, SqlRowUpdatedEventArgs e)
{
Console.WriteLine("Rows: " + e.RecordsAffected);
}
答案 2 :(得分:0)
我的理解是在构造命令构建器对象期间,它在DataAdapter上添加了对它自己的引用,因此它知道如何构建CRUD命令。
请注意您在上面发布的链接备注下的此部分。
*
SqlDataAdapter不会自动生成Transact-SQL 协调对DataSet所做的更改所需的语句 SQL Server的关联实例。但是,您可以创建一个 SqlCommandBuilder对象自动生成Transact-SQL 如果设置SelectCommand,则表单更新的语句 SqlDataAdapter的属性。然后,任何其他Transact-SQL 您未设置的语句由SqlCommandBuilder生成。
*