SqlCommandBuilder如何处理它的内容以及如何阻止ReSharper删除它的建议?

时间:2012-06-24 19:08:34

标签: c# resharper dataadapter sqldataadapter sqlcommandbuilder

我不明白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事件。

所以...三个具体问题:

  1. 如何阻止ReSharper建议删除此行?
  2. 编写像da.Update这样的类是不好的做法,其中代码没有以任何方式表明创建实例正在传递RowUpdated的内容?
  3. 这是design pattern

3 个答案:

答案 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生成。

*