0

リンクボタンをクリックすると、「リーダーが閉じているときに Read を呼び出そうとする試みが無効です」というエラーが表示されます dr を返す DAL メソッドは

private SqlDataReader getDownload(string sql)
{
SqlDataReader dr;
using (SqlConnection con = ConnectionManager.GetDatabaseConnection())
{
SqlCommand cmd = new SqlCommand("getInfo", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@query", SqlDbType.VarChar).Value = sql;
cmd.Connection = con;
dr = cmd.ExecuteReader();
}
return dr;
}

別のDALメソッドは

public SqlDataReader getDownload(int auto_id)
{
string sql = "select mfile_name,file_data from Viva_Notice where auto_id=" + auto_id;
SqlDataReader dr = getDownload(sql) ;
return dr;
}

私のBLLメソッドは

public SqlDataReader getDownload(int field)
{
GetPostAssign mGetPostAssign = new GetPostAssign();
SqlDataReader dr = mGetPostAssign.getDownload(field);
return dr;
}

私がそれを呼び出していると、「リーダーが閉じているときに読み取りを呼び出す無効な試みです」というメッセージが表示されます

protected void lnkDownload_Click(object sender, EventArgs e)
{
try
{
LinkButton lnkbtn = sender as LinkButton;
GridViewRow gvrow = lnkbtn.NamingContainer as GridViewRow;
if (gvrow.RowIndex < 0)
return;
int field = Convert.ToInt32(lnkbtn.Attributes["RowIndex"]);
SqlDataReader dr = MclsAssignment.getDownload(field);
if (dr.Read())
{
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + dr["mfile_name"] + "\"");
Response.BinaryWrite((byte[])dr["file_data"]);
Response.End();
}
}
catch (Exception)
{    
throw;
}
}
4

4 に答える 4

7

これは実際には設計上の問題です。接続を破棄するつもりであれば、実際には「ライブ」データ リーダーを返すことはできません。SqlDataReaderつまり、接続に依存しています。

SqlDataReader dr;
using (SqlConnection con = ConnectionManager.GetDatabaseConnection())
{
    SqlCommand cmd = new SqlCommand("getInfo", con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@query", SqlDbType.VarChar).Value = sql;
    cmd.Connection = con;
    dr = cmd.ExecuteReader();
} // the SqlConnection is disposed here
return dr; // dr is now invalid

その上、 を返すことで、実装の詳細を BLL/UI レイヤーに漏らしていますSqlDataReader。接続がアクティブな間にデータを読み取り、代わりに実際のデータを返して、物事をきれいに保つ必要があります。

public class Download
{
     public string Name { get; set; }
     public byte[] Data { get; set; }
}
...
private Download getDownload(string sql)
{
    using (SqlConnection con = ConnectionManager.GetDatabaseConnection())
    using (SqlCommand cmd = new SqlCommand("getInfo", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@query", SqlDbType.VarChar).Value = sql;
        con.Open();
        Using (SqlDataReader dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                return new Download
                {
                    Name = (string)dr["mfile_name"],
                    Data = (byte[])dr["file_data"]
                };
            }
        }
    }
}
于 2013-08-12T10:34:28.547 に答える
1

これは、データ アクセス レイヤーの設計上の問題です。想定されているように、アプリケーションをデータベースから切り離していません。これは、SQL を使用する場合とはデータベースへのインターフェイスが異なるだけです。それらを完全に分離する必要があります。つまり、データ オブジェクトをアプリケーションに返す必要があります。これらのデータ オブジェクトは、リーダーを使用して DAL に入力する必要があります。

したがって、あなたの方法は次のようになります。

private MyFile getDownload(string sql)
{
    SqlDataReader dr;
    using (SqlConnection con = ConnectionManager.GetDatabaseConnection())
    {
        SqlCommand cmd = new SqlCommand("getInfo", con);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@query", SqlDbType.VarChar).Value = sql;
        cmd.Connection = con;
        dr = cmd.ExecuteReader();


        return new MyFile {
                  file_name = dr["mfile_name],
                  file_data = dr["file_data]
        }
    }
}
于 2013-08-12T10:43:12.883 に答える
0

メソッドを変更/追加する必要があります

public DataTable getDownload(string sql)
{
    using (SqlConnection con = new SqlConnection(yourconstring))
    {
        SqlDataAdapter dap = new SqlDataAdapter(sql,con);
        DataTable dt = new DataTable();
        dap.Fill(dt);
        return dt;
    }
}

次に、ダウンロードのクリック方法で

DataTable dt = MclsAssignment.getDownload(field);
        if (dt.Rows.Count> 0)
        {
            Response.AddHeader("Content-Disposition", "attachment;filename=\"" + (string)dt.Rows[0]["mfile_name"] + "\"");
            Response.BinaryWrite((byte[])dt.Rows[0]["file_data"]);
            Response.End();
        }
于 2013-08-12T10:44:50.843 に答える