C# 在哪里关闭SqlDataReader对象和SqlConnection对象?

C# 在哪里关闭SqlDataReader对象和SqlConnection对象?,c#,asp.net,sql-server,C#,Asp.net,Sql Server,我调用一个函数,该函数将SqlDataReader对象返回给调用语句。我不知道应该在哪里关闭SqlDataReader对象和SqlConnection对象?在函数中还是在调用它之后 这是函数调用: SqlDataReader dr2= RetrieveSearcher(); pid = dr2[0].ToString(); 这就是功能: protected SqlDataReader RetrieveSearcher() { String Q = "select price from

我调用一个函数,该函数将
SqlDataReader
对象返回给调用语句。我不知道应该在哪里关闭
SqlDataReader
对象和
SqlConnection
对象?在函数中还是在调用它之后

这是函数调用:

SqlDataReader dr2= RetrieveSearcher();
pid = dr2[0].ToString();
这就是功能:

protected SqlDataReader RetrieveSearcher()
{
    String Q = "select price from tb3 where pid='12';
    cn = new SqlConnection("data source=.\\sqlexpress; integrated security=true; initial catalog=singh");
    cn.Open();

    cmd = new SqlCommand(Q,cn);
    dr1 = cmd.ExecuteReader();
    dr1.Read();

    return dr1;
}
  • 是否每次调用此函数时都要打开连接?让一个线程处理多个连接肯定会导致死锁

  • 如果您仍然想执行#1,我建议让您的
    RetrieveSearcher
    列表中返回它所需的数据,或者检查一下,只需返回一个
    数据表
    就可以了。这样函数就可以关闭它打开的连接

  • 如果仍然希望返回
    SqlDataReader
    ,则需要确保可以关闭打开的连接
    SqlDataReader
    不会直接公开
    SqlConnection
    ,因此在退出
    RetrieveSearcher
    方法后,您不能直接关闭连接。但是,您可以这样做:

    dr1 = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    
    这将在读卡器关闭时关闭连接。那么,你可以做:

    using (SqlDataReader dr2 = RetrieveSearcher()) {
        pid=dr2[0].ToString();
    }
    
  • 当然,我假设您真的需要不止一个字符串。:)如果您确实只需要一个字符串,那么只需返回该字符串并调用
    cmd.ExecuteScalar()

  • 始终使用参数化查询以避免sql注入攻击并提高性能(大多数db服务器可以通过适当的查询重用执行计划)
  • 不要让连接保持打开状态超过必要的时间
  • 不要共享数据库连接!创造它,使用它,摧毁它
  • 使用连接、命令、数据读取器等,将实现IDisposable的所有内容包装在
    块中。这样可以确保即使发生异常,也不会有任何资源保持打开状态
  • 在数据库模式中使用正确的类型并读取这些类型,不要将所有内容转换为字符串或从字符串转换为字符串!示例
    price
    看起来它实际上应该是十进制或数字值,而不是字符串,所以不要将其存储为字符串,也不要将其作为字符串读回
  • 从app.config或web.config中按名称检索连接字符串(取决于应用程序类型),不要将字符串硬编码到您的连接或其他任何地方
  • 关于你的逻辑 更改方法以返回自定义类型,如数据块。这确保了适当的SoS(关注点分离)。不要返回数据读取器!这将从调用者那里抽象出整个数据库调用,这是您应该努力实现的

    protected SomeType RetrieveSearcherData(string pid)
    {
        const string Q = "SELECT price FROM tb3 WHERE pid = @pid";
        using(var cn=new SqlConnection())
        using(var cmd=new SqlCommand(Q,cn))
        {
            // I do not know what pid is but use tho correct type here as well and specify that type using SqlDbType
            cmd.Parameters.Add(new SqlParameter("@pid", SqlDbType.VarChar, 100) { Value = pid});
            cn.Open();
            using(var dr1= cmd.ExecuteReader())
            {
                if(dr1.Read())
                {
                   var result = dr1.GetDecimal(0);
                   // read something and return it either in raw format or in some object (use a custom type)
                }
                else
                  return null; // return something else that indicates nothing was found
            }
        }
    }
    

    您需要返回SqlDataReader而不是返回它读取的字符串,这有什么原因吗?您知道可以通过执行
    pid=cmd.ExecuteScalar().ToString()
    来获得相同的值吗?