服务上的AccessViolationException

时间:2013-10-22 11:30:10

标签: c# service

我有一个正在运行的服务,它连接到一些客户端。它已经启动并运行了几个星期,这个函数每分钟被调用很多次,我在不同的函数中有几个捕获,但这个异常使它一直崩溃。我以前从未见过这个问题。 Whan可以发生这种情况吗?

堆栈:

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
   at System.Data.OleDb.OleDbServicesWrapper.GetDataSource(System.Data.OleDb.OleDbConnectionString, System.Data.OleDb.DataSourceWrapper ByRef)
   at System.Data.OleDb.OleDbConnectionInternal..ctor(System.Data.OleDb.OleDbConnectionString, System.Data.OleDb.OleDbConnection)
   at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(System.Data.Common.DbConnectionOptions, System.Object, System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionPoolGroup)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(System.Data.Common.DbConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory)
   at System.Data.OleDb.OleDbConnection.Open()
   at EServer.Database.DBManager.DoesObjectExsist(System.String)
   at EServer.Database.DBManager.setObjectOnline(System.String, Boolean, System.String, System.String)
   at EServer.Network.SocketListener.handleToDo()
   at EServer.Network.Token.ProcessData(System.Net.Sockets.SocketAsyncEventArgs)
   at EServer.Network.SocketListener.ProcessReceive(System.Net.Sockets.SocketAsyncEventArgs)
   at EServer.Network.SocketListener.OnIOCompleted(System.Object, System.Net.Sockets.SocketAsyncEventArgs)
   at System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(System.Net.Sockets.SocketAsyncEventArgs)
   at System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(System.Object)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(System.Net.Sockets.SocketError, Int32, System.Net.Sockets.SocketFlags)
   at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

代码:

public bool DoesObjectExsist(String ID)
        {
            try
            {    
                String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + dbPath + "'";
                string mySelectQuery = "SELECT * FROM Object WHERE ID = \"" + ID + "\"";

                OleDbConnection myConnection = new OleDbConnection(connectionString);
                OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
                myConnection.Open();
                OleDbDataReader myReader = myCommand.ExecuteReader();
                try
                {
                    while (myReader.Read())
                    {
                        return true;
                    }
                }
                finally
                {
                    myReader.Close();
                    myConnection.Close();
                }
                return false;
            }
            catch (Exception e)
            {
                return false;
            }
        }

2 个答案:

答案 0 :(得分:0)

为什么不用这个让它变得更加丰富。如果将using语句块中的连接,命令和读取器对象包装起来,那么会更好。 See usage of using.

更新

对不起,我在几分钟前看到,你正在使用Access db for Services,我认为这完全是疯了。由于服务一次被各种客户端使用,因此可能导致不一致。因此,正如Hans Passant在他的评论中所建议的那样,请注意Sql Server ExpressMySql类似于面向服务器的数据库。

public bool DoesObjectExsist(String ID)
        {
         bool result=false;
            try
            {    
                String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + dbPath + "'";
                string mySelectQuery = "SELECT Count(*) FROM Object WHERE ID = ?";

                OleDbConnection myConnection = new OleDbConnection(connectionString);

                OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
                command.Parameters.AddWithValue("@id",ID);
                myConnection.Open();
                OleDbDataReader myReader = myCommand.ExecuteReader();
                try
                {
                   if(reader.HasRows)
                        result=true;

                }
                finally
                {
                    myReader.Close();
                    myConnection.Close();
                }

            }
            catch (Exception e)
            {
               //log exception
            }
            return result;
        }

答案 1 :(得分:0)

AccessViolationException

此问题是ACE 2010引擎中的错误。可以在original bug report on microsoft connect中找到解决方法(参见FranzT):

  

在我的应用程序中,我遇到了同样的问题。 MS Access DB是此应用程序的后端(C#,. NET 2.0,VS 2005)。

     

当使用连接字符串作为提供者OLEDB.4.0时,它工作正常。当数据访问提供程序是ACE.OLEDB.12时,如果使用OpenFileDialog,则会出现异常。

     

在连接字符串中可以设置许多参数,OLE DB服务也是如此。

     

当OLE DB服务=默认(-13,池已禁用)时,我得到了   例外。当OLE DB Services = EnableAll(-1,池启用)时   工作正常。

     

如果我设置OLE DB Services = -2(EnableAll没有合并),我会得到异常。

     

我的解决方法是:设置OLE DB服务= -1(EnableAll)。

该解决方法基于一个名为Elmar Boye的微软论坛用户的研究,他详细介绍了该问题的性质(尽管用德语):

https://social.msdn.microsoft.com/Forums/de-DE/500055e5-6189-418c-b119-fdc0367e0969/accessviolationexception-bei-openfiledialog-nach-ffnen-und-schlieen-einer-2-form?forum=dotnetframeworkde

基本上,ACE 2010引擎正在访问它不拥有的内存。如果在引擎访问内存时数据库已经卸载,则抛出异常。要解决此问题,可以使用连接池,因为它可以使数据库连接保持打开状态,从而使数据库保持在内存中。可以使用OLE DB Services标志的不同组合启用它。

一个好的标志值是原始默认值,它启用所有服务(虽然这个默认值似乎被注册表项覆盖,这就是为什么在连接字符串中手动提供值是有意义的):

OLE DB Services=-1

虽然错误报告解决了打开文件对话框中的问题,但根本原因与使用ACE 2010提供程序进行Access的其他AccessViolationException情况相同。

还有Hotfix的链接可以解决问题。

顺便说一句,使用Microsoft.Jet.OLEDB.4.0提供程序不会发生此异常。

JetEntityFrameworkProvider

对于像我这样使用JetEntityFrameworkProvider by bubibubi的人,请确保您在生产连接字符串中使用变通方法,而不是在用于应用数据库迁移的连接字符串中,因为它会抛出{{}尝试打开数据库时,在第二个Update-Database命令上运行,并在此后的每个命令执行时锁定Package Manager控制台(直到重新启动Visual Studio)。

访问和多用户场景

构建访问权限,以便通过网络共享同时进行多用户访问。所以这是一个明确支持的场景。 @Hans Passant和@ user2905764