Asp.Net:从一个类中返回一个读者

时间:2009-12-30 14:13:54

标签: asp.net ado.net class data-access-layer encapsulation

我只是想知道从班级回来读者的正确方法吗?

我的代码可以使用,但我不确定这是否正确。

另外。我无法关闭我的类方法中的连接,仍然可以从我的ascx页面访问它,是

好吗?

//在我的课程中,我有以下方法来返回记录/阅读器 - 在这种情况下它是一条记录。

public SqlDataReader GetPost()
    {
        SqlConnection conn = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand("con_spPost", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@blogid", blogid);
        try
        {
            conn.Open();
            return cmd.ExecuteReader();
        }
        finally
        {
          //  conn.Close();
        }
    }

//然后我在我的ascx页面中调用GetPost方法,如下所示:

protected void Page_Load(object sender, EventArgs e)
{

    //instantiate our class
    MyClass DB = new MyClass();

    //pass in the id of the post we want to view
    DB.PostID = Int32.Parse(Request.QueryString["p"]);

    ///call our GetPost method
    SqlDataReader reader = DB.GetPost();

   //output the result
    reader.Read();
    this.viewpost.InnerHtml = "<span id='post1_CreatedDate'>" + reader["CreatedDate"].ToString() + "</span><br>";
    this.viewpost.InnerHtml += "<span class='blogheads'>" + reader["BlogTitle"].ToString() + "</span><p><p>";
    this.viewpost.InnerHtml += reader["BlogText"].ToString();
    reader.Close();
}

感谢您对我的代码或提示提出任何意见,谢谢。

熔体

8 个答案:

答案 0 :(得分:6)

一般来说,从一个方法返回一个读者是可以的,但读者的消费者需要控制所有将在读者一生中使用的一次性对象。

要执行此操作,您需要将IDbConnection传递给GetPost方法,然后确保您的调用者同时处理连接和阅读器。 using关键字是执行此操作的最便捷方式:

protected void Page_Load(object sender, EventArgs e) {

    // Create the DB, get the id, etc.    

    using (IDbConnection connection = new SqlConnection(connectionString))
    using (IDataReader reader = DB.GetPost(connection)) {
        reader.Read();
        this.viewpost.InnerHtml = reader["BlogText"].ToString();
        // finishing doing stuff with the reader  
    }
}

正如其他人所指出的那样,这开始使用过多的数据访问基础设施使应用程序的表示层变得混乱 - 所以这里不适合。在您发现自己遇到性能问题或需要显示不合理数据量之前,您不应该在表示层中处理数据读取器。只需让DB.GetPost返回一个字符串,并将所有数据访问代码封装在那里。

答案 1 :(得分:5)

要确保连接已关闭,请使用以下内容替换ExecuteReader来电:

return cmd.ExecuteReader(CommandBehavior.CloseConnection);

您还应该删除te try / finally阻止。

此外,在Page_Load处理程序中,您应该使用using语句,如下所示:

using (SqlDataReader reader = DB.GetPost()) {

    //output the result
    reader.Read();
    this.viewpost.InnerHtml = "<span id='post1_CreatedDate'>" + reader["CreatedDate"].ToString() + "</span><br>"
        + "<span class='blogheads'>" + reader["BlogTitle"].ToString() + "</span><p><p>"
        +  reader["BlogText"].ToString();
}

此外,您应该检查SQL查询是否实际返回了一些内容,如下所示:

if (!reader.Read()) {
    Something's wrong
}

最后,到目前为止最重要的,您应该通过调用Server.HtmlEncode来转义HTML以防止XSS漏洞。

例如:

    this.viewpost.InnerHtml = "<span id='post1_CreatedDate'>" + reader["CreatedDate"].ToString() + "</span><br>"
        + "<span class='blogheads'>" + Server.HtmlEncode(reader["BlogTitle"].ToString()) + "</span><p><p>"
        + Server.HtmlEncode(reader["BlogText"].ToString());

答案 2 :(得分:3)

你真的不应该将数据访问与表示层混合在一起。

考虑返回一个类型化的DataSet,或构建业务对象并将其返回给您的控件。

这是一个教程: http://www.asp.net/learn/data-access/tutorial-01-cs.aspx

答案 3 :(得分:2)

有一个问题。您的连接未被关闭。如您所知,您无法在GetPost中关闭它,因为由于DataReader的性质,您将不再拥有数据。解决此问题的一种方法是在ExecuteReader方法中包含一个参数,如下所示:

cmd.ExecuteReader(CommandBehavior.CloseConnection)

然后,当您的阅读器关闭时,连接将关闭。

使用封装代码返回的datareader存在一个根本问题,因为连接必须通过所有这些打开,使得错误处理变得棘手。请考虑使用数据表 A ),这对于小型数据集几乎同样有效。通过这种方式,您可以立即关闭GetPost方法中的连接,而不用担心它,只需非常简单的错误处理。或者( B )将连接传递给GetPost,因此连接的所有Using / Dispose语法和错误处理都在一个地方显式。我建议选择A。

答案 4 :(得分:0)

为什么要让网页了解数据库呢?为什么不抽象出数据库知识,只返回包含数据库数据的列表或对象?只是看起来很多责任混合在一起,你可以让自己更轻松。

答案 5 :(得分:0)

这是一个非常简单的架构。正如CSharpAtl所建议的那样,你可以让它更复杂。但是,这似乎对你有用。

我要做的一个重要补充是使用try-finally块。将Close放在finally中将确保即使在处理过程中发生异常也会释放连接。

SqlDataReader reader;
try
{
///call our GetPost method
    reader = DB.GetPost();

   //output the result
    reader.Read();
    this.viewpost.InnerHtml = "<span id='post1_CreatedDate'>" + reader["CreatedDate"].ToString() + "</span><br>";
    this.viewpost.InnerHtml += "<span class='blogheads'>" + reader["BlogTitle"].ToString() + "</span><p><p>";
    this.viewpost.InnerHtml += reader["BlogText"].ToString();
}
finally
{
    reader.Close();
}

答案 6 :(得分:0)

感谢所有好的提示,我决定在这里稍微不同但相关的主题继续这个主题: Asp.Net: Returning a DataSet from a Class

此致 熔体

答案 7 :(得分:0)

Dan Whalin的

This article可能是您阅读的好资源。它显示了创建n层应用程序的基础知识。您可以创建数据访问组件,实体对象,业务层和表示层。他还使用像你所问的sql数据读取器,并且他展示了一种使用对象构建辅助方法的好方法。

如果您不喜欢阅读文章,那么他对同一主题也有一个pretty good videocode example您可以下载并查看这种创建数据驱动应用程序的方法的不同变体。

祝你好运,希望这有助于一些人。