0
 protected void btnFetch_Click(object sender, EventArgs e)
    {

    SqlConnection con = new SqlConnection(Helper.ConStr);
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "select * from emptable";
    con.Open();
    SqlDataReader dr = cmd.ExecuteReader();
    gv1.DataSource = dr;
    gv1.DataBind();

    dr.NextResult();

    **while (dr.Read())**//It is returning the value as false!
    {
        SqlCommand cmd1 = new SqlCommand();
        cmd1.CommandText = "select * from table1";
        Response.Write(dr[0]);
        Response.Write(dr[1]);
    }
    con.Close();
 }

データ リーダーが 1 つの「select ステートメント」を取得し、それを読み取って Gridview にバインドする理由について混乱していますが、次の一連の「select ステートメント」を使用することになると、データ リーダーは何もしません。 . dr.Read()になりfalseます。

なぜこれが起こるのか教えてください。

4

5 に答える 5

2

データ リーダーは転送専用です。つまり、すべての行を 1 回しか読み取ることができません。

したがって、GridView をバインドすると、Read()false が返されるまで (すべての行を埋めることができるように) データ リーダーを通過します。

したがって、ループを呼び出そうとすると、readerすでにレコードセットの最後にあります。

これについては、 MSDNで詳しく説明されています。

アップデート:

@Petoj が示しNextResult()たように、複数の SELECT ステートメントを に追加した場合、このメソッドは次の結果を選択するために使用されます。Command.CommandTextしたがって、コードではまったく効果がありません。

于 2013-03-28T15:19:23.373 に答える
1

は必要ありません。リーダーを次のバッチに進めますNextResultdr.NextResult();

using (var myCon = new SqlConnection(Helper.ConStr))
using (var selectCommand = new SqlCommand("select * from emptable", myCon))
{
    myCon.Open();
    using (var dr = selectCommand.ExecuteReader())
    {
        while (dr.Read()) 
        {
            // ...
        }
    }
}

したがって、2 つのテーブルを選択するNextResultと、次のテーブルを取得するために使用できます。

"select * from emptable; select * from otherTable"

ExecuteReaderすでに最初のバッチが返されているため、通常、このメソッドを使用する必要はありません。

using-statementを使用して、例外が発生した場合でも、管理されていないすべてのリソースが最後に破棄されるようにしていることに注意してください。可能な限り使用する必要があります。これは、実装するすべてのオブジェクトに対してです (不可能なときIDisposableに使用しようとすると、コンパイラ エラーが発生します)。using

SqlConnection.Disposeまた、接続を閉じるため、手動で行う必要はありません (これはすべての接続タイプに適用されます)。

MSDN

原則として、オブジェクトを使用するときはIDisposable、それを using ステートメントで宣言してインスタンス化する必要があります。using ステートメントは、オブジェクトの Dispose メソッドを正しい方法で呼び出します。using ブロック内では、オブジェクトは 読み取り専用であり、変更や再割り当てはできません。using ステートメントを使用すると、オブジェクトのメソッドを呼び出しているときに例外が発生した場合でも、 Dispose が確実に呼び出されます。

于 2013-03-28T15:21:08.407 に答える
1

代わりにこれを試してください

 protected void btnFetch_Click(object sender, EventArgs e)
 {

    SqlConnection con = new SqlConnection(Helper.ConStr);
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "select * from emptable;select * from table1";
    con.Open();
    SqlDataReader dr = cmd.ExecuteReader();
    gv1.DataSource = dr;
    gv1.DataBind();

    dr.NextResult();

    while (dr.Read())
    {
        Response.Write(dr[0]);
        Response.Write(dr[1]);
    }
    con.Close();
 }
于 2013-03-28T15:19:46.847 に答える
0

dr.NextResult();クエリReferenceに複数の select ステートメントがある場合に機能します。
テーブルには select ステートメントが 1 つしかありません。

cmd.CommandText = "select * from emptable";

したがって、複数の選択ステートメントを使用する必要がある場合は、コマンドテキストで次のように複数の選択ステートメントを使用する必要があります

cmd.CommandText = "select * from emptable;select * from table1";
于 2013-03-28T15:20:54.963 に答える
0

SQLサーバーでストアドプロシージャを作成する必要があります

BEGIN BEGIN TRANSACTION としてプロシージャ selectFromTwoTables を作成します。

SELECT * FROM 空のテーブル

SELECT * FROM table1

IF(@@error = 0) -- エラーが発生した場合、トランザクションはロールバックされます。それ以外の場合は commit COMMIT TRANSACTION ELSE ROLLBACK TRANSACTION END

C# で SqlCommand cmd = new SqlCommand("selectFromTwoTables", conn); cmd.CommandType = CommandType.StoredProcedure;

于 2013-03-28T16:12:29.630 に答える