C# 数据读取器在while循环中的连接上打开,尽管已明确关闭

C# 数据读取器在while循环中的连接上打开,尽管已明确关闭,c#,C#,已存在与此命令关联的打开的DataReader 必须先关闭它 好的。所以我们在这方面做了大量的数据库读取,足以证明一个通用函数可以简化它。我刚刚更改了它,这样当使用活动连接调用时,该函数不再关闭连接,因为无论哪种方式,它都是一行。在这样做的过程中,我发现了这个bug。在while循环的第二次迭代中,DBRead函数在尝试实际执行时将得到一个错误,并根据上述错误进行抱怨。 然而在每次迭代结束时,都有一个reader.Close()调用,没有任何条件 现在。。。我已经做了一些调查,发现了一些关于使用

已存在与此命令关联的打开的DataReader 必须先关闭它

好的。所以我们在这方面做了大量的数据库读取,足以证明一个通用函数可以简化它。我刚刚更改了它,这样当使用活动连接调用时,该函数不再关闭连接,因为无论哪种方式,它都是一行。在这样做的过程中,我发现了这个bug。在
while
循环的第二次迭代中,DBRead函数在尝试实际执行时将得到一个错误,并根据上述错误进行抱怨。 然而在每次迭代结束时,都有一个reader.Close()调用,没有任何条件

现在。。。我已经做了一些调查,发现了一些关于使用
的东西。。。老实说,我不知道我会怎么做(我想我可以很快找到答案),但我不知道它是否能解决问题

我读到的每一个问题实际上都没有结束。而在这种情况下,我想我是在读卡器上为每一个打开调用一个close,然后在之后重用连接。我错了多少

        // Find all the unprocessed gifts in the inhouse table.
        SQL = "SELECT * FROM ToREgift WHERE processed = 0";
        ReadCommand.Connection = ReadConnect;
        ReadCommand.CommandText = SQL;
        dbRERead = ReadCommand.ExecuteReader();
        while (dbRERead.Read())  // Loop through them.
        {
            RowId = Convert.ToInt32(dbRERead["id"].ToString());

            // Lookup the RE ConstituentId from the ToREConstituent table.
            string ToREConstituent_Id = dbRERead["ToREConstituent_id"].ToString();
            Reader = FunctionsClass.DBRead(vars.Catalog, "SELECT Constituent_Id FROM ToREConstituent WHERE ID = " + ToREConstituent_Id.ToString(), ref Connection);
            Reader.Read();
            string ConstituentId = Reader["Constituent_Id"].ToString();
            bool UseRG = false;
            try
            {
                UseRG = Convert.ToBoolean(dbRERead["Use_RG"]);
            }
            catch (Exception ex) { }
            ;

            if (!UseRG)
            {
                if (dbRERead["TypeOfGift"].ToString() == "RecGiftPC")
                {
                    UseRG = true;
                }
            }

            AddSingleGift(ConstituentId, UseRG, RowId);

            SQL = "SELECT Constituent_Id FROM ToREConstituent WHERE Id = " + ToREConstituent_Id;
            dbRECommand.CommandText = SQL;
            Reader = dbRECommand.ExecuteReader();
            while (Reader.Read())
            {
                ConstituentId = Reader["Constituent_Id"].ToString();
            }
            Reader.Close();

        }
        dbRERead.Close();

--

public static SqlDataReader DBRead(string DB, string SQL, ref SqlConnection Connection)
{
    SqlDataReader functionReturnValue = null;
    // !! IMPORTANT !!
    // This will initialise and open a connection as needed.
    // The caller is responsible for closing the connection
    if(Connection==null)
    {
        Connection = new SqlConnection();
    }
    if(Connection.ConnectionString=="")
    {
        Connection.ConnectionString = "Data Source = REDEV;Initial Catalog = " + DB + ";Integrated Security = True";
    }
    try
    {
        Connection.Open();
    }
    catch (Exception ex)
    {
        if(ex.Message!="The connection was not closed. The connection's current state is open.")
        {
            throw ex;
        }
        // Else continue, because if that's the error, doesn't matter, just move on.
    }
    SqlCommand dbCommand = new SqlCommand();

    dbCommand.Connection = Connection;
    dbCommand.CommandType = System.Data.CommandType.Text;
    dbCommand.CommandText = SQL;
    dbCommand.CommandTimeout = 0;

    try {
        functionReturnValue = dbCommand.ExecuteReader();
        return functionReturnValue;
    } catch (Exception ex) {
        //frmMain.BatchError = true;
        System.Windows.Forms.MessageBox.Show("Error reading Database. Can't Continue, sorry. Debug information below:" + vars.vbCrLf + vars.vbCrLf + ex.Message + vars.vbCrLf + SQL + vars.vbCrLf + vars.vbCrLf + Connection.ConnectionString);
        Connection.Close();
        System.Environment.Exit(0);
    }

    return functionReturnValue;
    // Cleanup
    //dbCommand = Nothing

}

请在那里做一个大的重构,每个问题都会消失。清空
catch
块,捕获
Exception
并检查精确的本地化消息(忽略所有其他内容)。根本不使用
。在一个方法中创建连接,并让它在另一个方法中关闭(没有任何使用块),当其他人阅读它时,可能会令人惊讶<代码>变量vbCrlf
?为什么不
Environment.NewLine
<代码>while(reader.Read())
当您只需要一条记录时。没有参数构建的SQL代码(SQL注入呢?)。顺便说一句,你们在哪里关闭连接?!您也没有在
DBRead
中处理
DBCommand
,我想仔细看看还会发现一些其他的东西,但我认为是时候重写这几行了。尝试一些简单的规则:1)当类实现了
IDisposable
时,您必须使用
using
。2) 不要捕捉异常(除非你有很好的理由),而是捕捉你所需要的。3) 尽量使您的功能尽可能小(只执行一项任务,每项任务)。4) 不要连接字符串以生成SQL命令:使用参数。我同意。当前状态下的代码坏了,坏了,坏了。扔掉它,重新开始。好的。无论如何,我现在采取了一种完全不同的方法,因为我们通过一种变通方法(将读取器传递到DBRead函数)修复了它,并回到了真正的问题,即temprecords由于某种原因总是空的。所以,抛开一切,做一些不同的事情。我还是会考虑你建议的东西。另外,
Environment
并不总是存在,而我们定义的
vars.VbCrLf
确实存在。(当然,它不是VB,但我们从转换的代码开始。还没有看到更改名称的理由。)