0

我开发的一个应用程序每周大约崩溃 2 次。当它崩溃时,它会关闭整个应用程序,直到应用程序池被回收。我无法在开发环境中重现该错误。

下面我粘贴了导致崩溃的代码和来自应用程序事件查看器的错误消息。使应用程序崩溃的行以 ~~~~ 开头。该消息指出我有一个打开的 DataReader,但我检查了我的代码并且我总是关闭我的数据读取器和连接。

我不知道我应该采取什么步骤来解决这个错误。任何帮助将不胜感激。谢谢你!

 public bool open() {
        //-- check if connection is closed
        if (this.dbconn.State == System.Data.ConnectionState.Closed) {
            try {
                this.dbconn.Open();
            }
            catch (Exception ex) {
                this.errorCode = (int)DatabaseErrorType.DBOpenFailed;
                this.errorMessage = System.Web.HttpUtility.HtmlEncode(ex.Message);
                throw ex;
            }
        }
        return true;
    }

/// <summary> closes connection object</summary>
    public bool close() {
        if (!(this.dbconn == null)) {
            if (!(this.dbconn.State == System.Data.ConnectionState.Closed)) {
                try {
                    this.dbconn.Close();
                }
                catch (Exception ex) {
                    this.errorCode = (int)DatabaseErrorType.DBCloseFailed;
                    this.errorMessage = System.Web.HttpUtility.HtmlEncode(ex.Message);
                    return false;
                }

            }
        }
        return true;
    }
        // GET MULTI Accounts
    public List<DTO.DTOAccount> GetAccounts(DTO.DTOAccount objAcc) {
        //-- reset error variables
        resetError();

        // make sure the connection is open
        if (this.open()) {

            SqlDataReader sqlReader = null;

            try {

                SqlCommand sqlProcedure = new SqlCommand("[dbo].[sp_Select_ONECARD_ACCOUNTS]", this.dbconn);
                sqlProcedure.CommandType = System.Data.CommandType.StoredProcedure;
                sqlProcedure.Parameters.Add(new SqlParameter("@ACCOUNT"             , objAcc.AccountId));
                sqlProcedure.Parameters.Add(new SqlParameter("@UDEF_4"              , objAcc.UDEF_4));

                ~~~~sqlReader = sqlProcedure.ExecuteReader();

                List<DTO.DTOAccount> Accounts = new List<DTO.DTOAccount>();
                // iterate through all values returned
                while (sqlReader.Read()) {
                    DTO.DTOAccount tmpAccount               = new ca.eyecode.onecard.DTO.DTOAccount();
                    tmpAccount.AccountId                    = (String)sqlReader["ACCOUNT"];
                    tmpAccount.Category                     = (String)sqlReader["CATEGORY"];
                    tmpAccount.Groups                       = (String)sqlReader["GROUPS"];
                    tmpAccount.Suffix                       = (String)sqlReader["SUFFIX"];
                    tmpAccount.UDEF_1                       = ((String)sqlReader["UDEF_1"]).Trim();
                    tmpAccount.UDEF_4                       = ((String)sqlReader["UDEF_4"]).Trim();
                    tmpAccount.FirstName                    = ((String)sqlReader["FNAME"]).Trim();
                    tmpAccount.LastName                     = ((String)sqlReader["LNAME"]).Trim();
                    tmpAccount.Picture                      = (sqlReader["PICTURE"] == DBNull.Value ? String.Empty : (String)sqlReader["PICTURE"]).Trim();
                    // add account items
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.ONEcardCash, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_1"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.Department, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_2"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.BookStore, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_3"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.TechBalance, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_4"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.Bonus1, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_5"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.MealPlanExtra, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_6"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.MealPlanDollars, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_7"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.AramarkCredit, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_8"])});
                    tmpAccount.AccountItems.Add (new DTO.DTOAccountItem() { Account= AccountType.AramarkEmployees, Balance= Convert.ToDouble((Decimal)sqlReader["BALANCE_9"])});
                    // Combine Totals to One Meal PLAN
                    tmpAccount.AccountItems[5].Balance += tmpAccount.AccountItems[6].Balance;
                    tmpAccount.AccountItems[5].Balance += tmpAccount.AccountItems[8].Balance;
                    tmpAccount.AccountItems[6].Balance = 0;
                    tmpAccount.AccountItems[8].Balance = 0;

                    Accounts.Add(tmpAccount);
                }
                return Accounts;
            }
            finally {
                try {
                if (sqlReader != null)  {
                    sqlReader.Close();
                }
                }
                catch {}
                this.close();
            }

        }
        return null;
    }

错误

 Event code: 3005 
Event message: An unhandled exception has occurred. 
Event time: 4/19/2012 11:30:39 AM 
Event time (UTC): 4/19/2012 5:30:39 PM 
Event ID: 7715c17b872240829c3dfb562268998e 
Event sequence: 1253 
Event occurrence: 1 
Event detail code: 0 

Application information: 
    Application domain: /LM/W3SVC/997719702/Root-1-129793277036652335 
    Trust level: Full 
    Application Virtual Path: / 
    Application Path: 
    Machine name: 

Process information: 
    Process ID: 820 
    Process name: w3wp.exe 
    Account name: 

Exception information: 
    Exception type: InvalidOperationException 
    Exception message: There is already an open DataReader associated with this Command which must be closed first.
   at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader()
   at ca.eyecode.onecard.DAO.DAOAccount.GetAccounts(DTOAccount objAcc) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\DAO\DAOAccount.cs:line 47
   at ca.eyecode.onecard.BL.BLAccount.AccountsGet(DTOAccount objAcc) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLAccount.cs:line 228
   at ca.eyecode.onecard.BL.BLAccount.AccountLogin(String CCID, String Password) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLAccount.cs:line 171
   at ca.eyecode.onecard.BL.BLFacade.AccountLogin(String CCID, String Password) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLFacade.cs:line 36
   at ca.eyecode.onecard.Controllers.HomeController.Index(String inpCCID, String inpPASS) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Controllers\HomeController.cs:line 77
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__4()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)



Request information: 
    Request URL: 
    Request path: / 
    User host address: 
    User:  
    Is authenticated: False 
    Authentication Type:  
    Thread account name: 

Thread information: 
    Thread ID: 9 
    Thread account name:  
    Is impersonating: False 
    Stack trace:    at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader()
   at ca.eyecode.onecard.DAO.DAOAccount.GetAccounts(DTOAccount objAcc) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\DAO\DAOAccount.cs:line 47
   at ca.eyecode.onecard.BL.BLAccount.AccountsGet(DTOAccount objAcc) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLAccount.cs:line 228
   at ca.eyecode.onecard.BL.BLAccount.AccountLogin(String CCID, String Password) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLAccount.cs:line 171
   at ca.eyecode.onecard.BL.BLFacade.AccountLogin(String CCID, String Password) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Models\ca.eyecode\onecard\BL\BLFacade.cs:line 36
   at ca.eyecode.onecard.Controllers.HomeController.Index(String inpCCID, String inpPASS) in C:\inetpub\wwwroot\ONEcard\OneAccount\OneAccount\Controllers\HomeController.cs:line 77
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__4()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
4

3 回答 3

1

To be sure, you can just start using a using statement around your SqlDataReader. Do the same for the other elements. That way you're sure they're always being disposed and closed.

Next to that, make sure you don't nest SqlDataReaders. Close them as soon as you can, and do your data access sequential. That should fix the issue.

于 2012-04-19T19:58:00.997 回答
1

The issue was that I had a try finally block in my code. Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

To make sure the finally block is executed every time you can not omit the catch block. http://msdn.microsoft.com/en-us/library/zwc8s4fz(v=vs.100).aspx

于 2012-04-26T18:51:12.027 回答
0

除非您真的需要其他地方的连接对象,否则我会将方法重构为:

public List<DTO.DTOAccount> GetAccounts(DTO.DTOAccount objAcc)
{
    //-- reset error variables
    resetError();

    List<DTO.DTOAccount> Accounts = new List<DTO.DTOAccount>();

    try
    {
        using (SqlConnection dbconn = new SqlConnection("your-connection-string"))
        {
            using (SqlCommand sqlProcedure = new SqlCommand("[dbo].[sp_Select_ONECARD_ACCOUNTS]", dbconn))
            {
                sqlProcedure.CommandType = System.Data.CommandType.StoredProcedure;
                sqlProcedure.Parameters.Add(new SqlParameter("@ACCOUNT", objAcc.AccountId));
                sqlProcedure.Parameters.Add(new SqlParameter("@UDEF_4", objAcc.UDEF_4));
                dbconn.Open();
                using (SqlDataReader sqlReader = sqlProcedure.ExecuteReader())
                {
                    while (sqlReader.Read())
                    {
                        DTO.DTOAccount tmpAccount = new ca.eyecode.onecard.DTO.DTOAccount();
                        tmpAccount.AccountId = (String)sqlReader["ACCOUNT"];
                        tmpAccount.Category = (String)sqlReader["CATEGORY"];
                        tmpAccount.Groups = (String)sqlReader["GROUPS"];
                        tmpAccount.Suffix = (String)sqlReader["SUFFIX"];
                        tmpAccount.UDEF_1 = ((String)sqlReader["UDEF_1"]).Trim();
                        tmpAccount.UDEF_4 = ((String)sqlReader["UDEF_4"]).Trim();
                        tmpAccount.FirstName = ((String)sqlReader["FNAME"]).Trim();
                        tmpAccount.LastName = ((String)sqlReader["LNAME"]).Trim();
                        tmpAccount.Picture = (sqlReader["PICTURE"] == DBNull.Value ? String.Empty : (String)sqlReader["PICTURE"]).Trim();
                        // add account items
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.ONEcardCash, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_1"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.Department, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_2"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.BookStore, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_3"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.TechBalance, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_4"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.Bonus1, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_5"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.MealPlanExtra, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_6"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.MealPlanDollars, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_7"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.AramarkCredit, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_8"]) });
                        tmpAccount.AccountItems.Add(new DTO.DTOAccountItem() { Account = AccountType.AramarkEmployees, Balance = Convert.ToDouble((Decimal)sqlReader["BALANCE_9"]) });
                        // Combine Totals to One Meal PLAN
                        tmpAccount.AccountItems[5].Balance += tmpAccount.AccountItems[6].Balance;
                        tmpAccount.AccountItems[5].Balance += tmpAccount.AccountItems[8].Balance;
                        tmpAccount.AccountItems[6].Balance = 0;
                        tmpAccount.AccountItems[8].Balance = 0;

                        Accounts.Add(tmpAccount);
                    }
                }
            }
        }
    }
    catch
    {
        // do some error handling.
    }

    return Accounts;
}
于 2012-04-19T19:52:55.273 回答