4

我有一个服务正在运行,它连接到几个客户端。它已经运行了好几个星期,这个函数每分钟被调用很多次,我在不同的函数中有一些捕获,但是这个异常使它一直崩溃。我以前从未见过这个问题。谁能做到这一点?

堆:

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;
            }
        }
4

2 回答 2

4

EF 核心更新

以下部分有点过时,是关于 EF6 和 .NET Framework 4.x。如今,如果您使用的是 .NET (Core),请使用EntityFrameworkCore.Jet EF Core 提供程序。使用最新的prerelease,它引用了 5.0.0 OLE DB 库,其中包含一些主要的错误修复。

AccessViolationException

此问题是 ACE 2010 引擎中的错误。可以在 microsoft connect 的原始错误报告中找到解决方法(请参阅 FranzT):

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

当在连接字符串中使用提供者 OLEDB.4.0 时,它工作正常。当数据访问提供程序是 ACE.OLEDB.12 时,如果使用 OpenFileDialog,我会得到一个异常。

在连接字符串中可以设置很多参数,OLE DB Services 也是。

当 OLE DB Services=default (-13, pooling disabled) 我得到异常。当 OLE DB Services=EnableAll(-1,启用池)它工作正常。

如果我设置 OLE DB Services=-2 (EnableAll without pooling) 我得到异常。

我的解决方法是:设置 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 提供程序的其他 AccessViolationException 情况相同。

还有一个Hotfix的链接,据说可以解决这个问题。

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

JetEntityFrameworkProvider

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

访问和多用户场景

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

于 2017-11-06T21:03:48.183 回答
0

Why dont you make it more sumpler by using this. If would greate if you wrap connection, command and reader objects inside a using statement block. See usage of using.

Update

Sorry , I saw this couple of minutes ago that, you are using Access db for Services, which is, I think completely insane. Since services are consumed by various clients at a time so it might lead to inconsistency. So, as Hans Passant suggested in his comment, kindly go for Sql Server Express or MySql like Server-Oriented database for such scenarios.

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;
        }
于 2013-10-22T11:35:18.617 回答