3

その仕組みがわかりません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はどこでも使用されておらず、 MSDNGetUpdateCommand()のようにメソッドを呼び出していません。を作成し、 を渡すだけです。しかし、コードは正常に機能します。SqlCommandBuilderSqlDataAdapter

コードを見ると、次の行のようです

var builder = new SqlCommandBuilder(da);

安全に削除できます。実際、ReSharper はそれを削除することを提案しています。SqlDataAdapterしかし、そうすると、更新の実行方法がわからないため、コードは実行されなくなります。

SqlDataAdapterデバッグ モードで、その行を実行した後、のUpdateCommandプロパティが のままであることに気付きましたnullMSDN -docsから、が のイベントにSqlCommandBuilder登録されていることがわかります。RowUpdatedSqlDataAdapter

しかし、そのイベントがトリガーされたとき、それは何をしますか? はSqlDataBuilder実際にアップデート自体を実行していますか?

他に気付いたことは、を削除すると、ステートメントで InvalidOperationException が発生する直前にSqlCommandBuilder、メソッドが 1 回トリガーされることです。それを予想しなかった。イベントは、行が実際に更新されたときにのみ発生すると思います。DaRowUpdatedda.UpdateRowUpdated

つまり... 3 つの具体的な質問:

  1. ReSharper がこの行の削除を提案しないようにするにはどうすればよいですか?
  2. インスタンスの作成が渡されたSqlCommandBuilderもので何かをしていることをコードがまったく示していない のようなクラスをプログラムするのは悪い習慣ですか?SqlDataAdapter
  3. これはデザインパターンですか?
4

3 に答える 3

3

変数を使用していない場合は、絶対に必要ありません。コンストラクターで何か有用なことが起こっている場合でも、それを呼び出すことができます。

var builder = new SqlCommandBuilder(da);

次のようにする必要があります。

new SqlCommandBuilder(da);

これにより、コードの動作を変更せずに警告を処理する必要があります。少し奇妙に見えますが、これが本当に必要な場合は、設計にSqlCommandBuilder少し疑問があります. しかし、実際には、このような使用法は通常のメソッド呼び出しと本質的に同じです。

于 2012-06-24T19:25:07.743 に答える
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);
    }
于 2012-06-25T02:02:53.690 に答える
0

コマンドビルダーオブジェクトの構築中の私の理解では、DataAdapterにそれ自体への参照が追加されるため、CRUDコマンドの構築方法がわかります。

上記のリンクのコメントの下にあるこのセクションに注意してください。

*

SqlDataAdapterは、DataSetに加えられた変更をSQLServerの関連付けられたインスタンスと調整するために必要なTransact-SQLステートメントを自動的に生成しません。ただし、SqlDataAdapterのSelectCommandプロパティを設定すると、SqlCommandBuilderオブジェクトを作成して、単一テーブルの更新用のTransact-SQLステートメントを自動的に生成できます。次に、設定しない追加のTransact-SQLステートメントがSqlCommandBuilderによって生成されます。

*

于 2012-06-25T01:19:48.113 に答える