我们有一个.NET Windows服务,它将WCF服务暴露给用户界面和系统的其他部分。它以 .NET Framework 4.5 为目标,并使用 SQLite 1.0.92 二进制文件与底层SQLite数据库进行通信。但是,在SQLite.Interop.dll中使用AccessViolationException(通过Windows事件查看器找到)运行一段时间后,Windows服务崩溃(自动停止)。我在Connection close中遇到过关于此异常的文章,但在我们所有情况下,我们在使用WCF服务公开的方法查询或写入数据库时遇到此异常。堆栈跟踪如下:
Application: OurServer.exe
Framework Version: **v4.0.30319**
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at System.Data.SQLite.UnsafeNativeMethods.sqlite3_bind_int(IntPtr, Int32, Int32)
at System.Data.SQLite.UnsafeNativeMethods.sqlite3_bind_int(IntPtr, Int32, Int32)
at System.Data.SQLite.SQLite3.Bind_Int32(System.Data.SQLite.SQLiteStatement, System.Data.SQLite.SQLiteConnectionFlags, Int32, Int32)
at System.Data.SQLite.SQLiteStatement.BindParameter(Int32, System.Data.SQLite.SQLiteParameter)
at System.Data.SQLite.SQLiteStatement.BindParameters()
at System.Data.SQLite.SQLiteCommand.GetStatement(Int32)
at System.Data.SQLite.SQLiteDataReader.NextResult()
at System.Data.SQLite.SQLiteDataReader..ctor(System.Data.SQLite.SQLiteCommand, System.Data.CommandBehavior)
at System.Data.SQLite.SQLiteCommand.ExecuteReader(System.Data.CommandBehavior)
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(System.Data.CommandBehavior)
at DataAccess.Sqlite.ExecuteCommand(System.Collections.ObjectModel.Collection`1<System.String>, System.Collections.ObjectModel.Collection`1<System.Data.Common.DbParameter[]>)
at Data.Settings.Save(System.Collections.ObjectModel.Collection`1<Common.Operation>)
at DynamicClass.SyncInvokeSaveOperation(System.Object, System.Object[], System.Object[])
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)
at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)
at System.Runtime.AsyncResult.Complete(Boolean)
at System.Runtime.InputQueue`1+AsyncQueueReader[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Set(Item<System.__Canon>)
at System.Runtime.InputQueue`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].EnqueueAndDispatch(Item<System.__Canon>, Boolean)
at System.Runtime.InputQueue`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].EnqueueAndDispatch(System.__Canon, System.Action, Boolean)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Enqueue(System.__Canon, System.Action, Boolean)
at System.ServiceModel.Channels.ConnectionDemuxer+CompleteSingletonPreambleAndDispatchRequestAsyncResult.OnPreambleComplete(System.IAsyncResult)
at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)
at System.Runtime.AsyncResult.Complete(Boolean)
at System.ServiceModel.Channels.ServerSingletonPreambleConnectionReader+CompletePreambleAsyncResult.OnWriteCompleted(System.Object)
at System.ServiceModel.Channels.SocketConnection.OnSendAsync(System.Object, System.Net.Sockets.SocketAsyncEventArgs)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
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*)
我们正在使用来自&#34; sqlite-netFx45-binary-bundle-Win32-2012-1.0.92.0&#34;的SQLite程序集。 (从http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki下载)。程序集作为Windows服务的一部分捆绑在一起,不在GAC中。这种行为在32位和64位计算机中都是一致的。仅供参考,我们不使用混合模式组件。
我们的连接字符串:
Data Source=ourapp.db;Version=3;New=False;Compress=True;PRAGMA cache_size=20000; PRAGMA page_size=32768; PRAGMA synchronous=off"
和SQLite数据库文件是Windows&#34; ProgramData&#34;文件夹中。
stacktrace将框架版本显示为&#34; v4.0.30319&#34;我们在服务的应用程序配置中明确将目标版本设置为4.5。但是,该机器已安装两个版本。
此外,我编写了一个简单的控制台应用程序,它从多个线程调用相同的WCF服务方法,但无法模拟相同的AccessViolationException。因此,我不认为它可能是一个负载或并发访问相关的问题。异常似乎是随机的,除了运行服务并等待它发生之外,我们无法一致地重新产生问题。
非常感谢任何可能导致此问题的指示。
更新:
正在使用的ExecuteCommand的两个变体的代码:
public int ExecuteCommand(string query, params DbParameter[] parameters)
{
try
{
this.result = -1;
this.OpenConnection();
this.command = new SQLiteCommand(query, this.connnection);
this.HandleParameters(parameters);
this.result = this.command.ExecuteNonQuery();
}
catch (Exception ex)
{
this.result = -1;
}
finally
{
if (this.command != null)
{
this.command.Dispose();
}
this.CloseConnection();
}
return this.result;
}
public int ExecuteCommand(Collection<string> queries, Collection<DbParameter[]> parameters)
{
try
{
this.result = -1;
this.OpenConnection();
this.command = new SQLiteCommand();
this.command.Connection = this.connnection;
this.transaction = this.connnection.BeginTransaction();
for (int i = 0; i < queries.Count; i++)
{
this.command.Parameters.Clear();
this.command.CommandText = queries[i];
this.command.CommandTimeout = this.timeOut;
this.command.Transaction = this.transaction;
DbParameter[] cmdParams = new DbParameter[] { };
if (parameters != null)
{
cmdParams = parameters[i];
}
this.HandleParameters(cmdParams);
this.result += this.command.ExecuteNonQuery();
}
this.transaction.Commit();
}
catch (Exception ex)
{
if (this.transaction != null)
{
this.transaction.Rollback();
}
this.result = -1;
}
finally
{
if (this.command != null)
{
this.command.Dispose();
}
this.CloseConnection();
}
return this.result;
}
更新2:保存方法的代码
Collection<DbParameter[]> dbparameters = new Collection<DbParameter[]>();
DbParameter[] dbparams;
SQLiteParameter sqlparams;
Collection<string> queries = new Collection<string>();
int icount = 0;
foreach (Operation operation in operations)
{
icount = 0;
dbparams = new DbParameter[4];
queries.Add("UPDATE table1 SET col1 = @Col1, col2 = @col2, " +
"Timestamp = @Timestamp WHERE Id = @Id");
sqlparams = new SQLiteParameter();
sqlparams.DbType = DbType.String;
sqlparams.ParameterName = "@Timestamp";
sqlparams.Value = string.Format(CultureInfo.InvariantCulture, "{0:yyyy-MM-dd HH:mm:ss}", operation.Timestamp);
dbparams[icount++] = sqlparams;
sqlparams = new SQLiteParameter();
sqlparams.DbType = DbType.String;
sqlparams.ParameterName = "@Id";
sqlparams.Value = operation.Id;
dbparams[icount++] = sqlparams;
sqlparams = new SQLiteParameter();
sqlparams.DbType = DbType.String;
sqlparams.ParameterName = "@Col1";
sqlparams.Value = operation.Col1;
dbparams[icount++] = sqlparams;
sqlparams = new SQLiteParameter();
sqlparams.DbType = DbType.String;
sqlparams.ParameterName = "@Col2";
sqlparams.Value = operation.Col2;
dbparams[icount++] = sqlparams;
dbparameters.Add(dbparams);
}
return (DataAccess.Sqlite.ExecuteCommand(queries, dbparameters) > -1);
答案 0 :(得分:1)
错误与提供商失去跟踪哪些连接已打开一致:
该错误看起来像连接池有问题,但您的连接字符串不使用连接池,默认情况下它处于关闭状态。
是否有其他内容访问同一数据库已启用连接池?
您必须做的第一件事就是记录异常。
答案 1 :(得分:1)
您的课程可能不是线程安全的。检查多个线程是否同时调用Save方法。
如果它是您的类的私有成员,还要确保实现IDisposable以处置您的SQLiteConnection对象。