如何正确使用SqlDataReader?

3

我有以下两种方法:

internal static SqlDataReader SelectData(string sql)
{
    using (var sqlConnection = new SqlConnection(Constant.ConnectionString))
    {
        sqlConnection.Open();
        var sqlCommand = new SqlCommand(sql, sqlConnection);
        var dataReader = sqlCommand.ExecuteReader();
        return dataReader;
    }
}

使用以下方法:

var dataReader = SelectData(---some sql ---);

private void AddData(dataReader)
{
    while (dataReader.Read())
    {
        Employee e = new Employee();
        e.FirstNamei = dataReader["Name"].ToString();
    }

    dataReader.Close();
}

我知道我们可以合并这两种方法,但我正在寻找更好的方法来编写代码,或者这样做会引起一些问题吗?


2
你提到在第二种方法中使用了第一种方法,但这是不正确的。两种方法似乎互不相关,所以你的问题仍然不清楚。顺便说一下,永远不要使用空的 catch 块。 - Tim Schmelter
@TimSchmelter ..没错..我编辑了.. - Tech
为什么不使用企业库进行数据访问? - T.S.
@T.S. - 我很惊讶企业库仍在维护。它曾经是最棒的,但我已经很久没有听说过了。 - Greg
不仅仅是维护,它最近还有了新版本。它比EF更快,并且具有缓存功能。我认为,值得实现,而不是在每个页面上创建连接。 - T.S.
3个回答

6

实际上,您留下了一些漏洞。您真正想这样写:

using (SqlConnection cnn = new SqlConnection(cnnString))
using (SqlCommand cmd = new SqlCommand(sql, cnn))
{
    // use parameters in your SQL statement too, so you can do this
    // and protect yourself from SQL injection, so for example
    // SELECT * FROM table WHERE field1 = @parm1
    cmd.Parameters.AddWithValue("@parm1", val1);

    cnn.Open();
    using (SqlDataReader r = cmd.ExecuteReader())
    {

    }
}

因为你需要确保这些对象被处理。此外,通过采用这种方式,您不需要使用 dataReader.Close()。当它被 using 语句自动处理时,它将被调用。
现在,在一个 try...catch 块中包装这些语句就可以了。

我只是想重构一下它,这样我就可以在任何地方使用像SelectData这样的方法。你提供的代码非常好用。 - Tech
为了清晰起见,第一组大括号是不必要的。使用(SqlConnection cnn = n.....) 使用(SqlCommand cmd = n.....) { // 代码 }这样可以节省很多嵌套。Using语句可以连续使用。 - Hawxby
@Hawxby,我不确定我理解你的意思。 - Mike Perrenoud
我已经提交了一个编辑。你可以在每个using语句之间不使用大括号来使用它们,如下所示:using() using() using () {} - Hawxby
@Hawxby,不错的语法糖。感谢你的贡献。 - Mike Perrenoud

2

以下是需要翻译的内容:

一些事情

1)由于您在 SelectData 上关闭了连接,因此 AddData 在执行时应该会出错,因为它需要一个打开的连接。

2)AddData 不应该关闭 dataReader,因为他并没有打开它。

3)也许您隐藏了一些代码,但我没有看到您在 AddData 中使用创建的 Employee 实例。


这意味着当我在AddData方法中访问DataReader时,它是空的吗? - Tech
@Ratan:不应为空,因为连接不再活动,应该抛出错误。 - Claudio Redi
有没有什么地方可以看到编写此类方法的理想方式?因为对于每种类型的“Employee e = new Employee();”,我都需要一遍又一遍地编写整个过程。 - Tech

0

从技术上讲,如果您这样做,第一种方法是正确的。

    sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);

然后,您的客户端将关闭读取器,您的连接也将关闭。

第二个示例如果您没有在其中关闭读取器,那么也是正确的。仅仅将读取器传递给一个方法来迭代它并没有问题,但必须要控制好读取器从哪里创建。如何打开和处理它 - 这是不同的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接