C# SQL Server Compact Edition 4-AccessViolationException

C# SQL Server Compact Edition 4-AccessViolationException,c#,multithreading,entity-framework,sql-server-ce,sql-server-ce-4,C#,Multithreading,Entity Framework,Sql Server Ce,Sql Server Ce 4,我正在首先使用实体框架代码和SQLServerCompact4.0构建一个.NET4WPF应用程序。我试图在后台线程上调用DbContext.SaveChanges(),以避免阻塞UI,但偶尔会出现以下异常: System.AccessViolationException occurred Message=Attempted to read or write protected memory. This is often an indication that other memory is

我正在首先使用实体框架代码和SQLServerCompact4.0构建一个.NET4WPF应用程序。我试图在后台线程上调用
DbContext.SaveChanges()
,以避免阻塞UI,但偶尔会出现以下异常:

System.AccessViolationException occurred
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=System.Data.SqlServerCe
  StackTrace:
       at System.Data.SqlServerCe.NativeMethodsHelper.OpenStore(IntPtr pOpenInfo, IntPtr pfnOnFlushFailure, IntPtr& pStoreService, IntPtr& pStoreServer, IntPtr& pQpServices, IntPtr& pSeStore, IntPtr& pTx, IntPtr& pQpDatabase, IntPtr& pQpSession, IntPtr& pStoreEvents, IntPtr& pError)
       at System.Data.SqlServerCe.NativeMethods.OpenStore(IntPtr pOpenInfo, IntPtr pfnOnFlushFailure, IntPtr& pStoreService, IntPtr& pStoreServer, IntPtr& pQpServices, IntPtr& pSeStore, IntPtr& pTx, IntPtr& pQpDatabase, IntPtr& pQpSession, IntPtr& pStoreEvents, IntPtr& pError)
       at System.Data.SqlServerCe.SqlCeConnection.Open(Boolean silent)
       at System.Data.SqlServerCe.SqlCeConnection.Open()
       at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
       at System.Data.EntityClient.EntityConnection.Open()
       at System.Data.Objects.ObjectContext.EnsureConnection()
       at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
       at System.Data.Entity.Internal.InternalContext.SaveChanges()
       at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
       at System.Data.Entity.DbContext.SaveChanges()
       at SourceLog.Model.LogSubscriptionManager.<SaveChanges>b__2() in C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\LogSubscriptionManager.cs:line 51
  InnerException: (null)

只有当可验证托管代码与非托管代码或不安全托管代码交互时,才会发生AccessViolationException


您应该浏览这个博客my MS,了解如何解决访问问题。这里的问题不是序列化对DbContext对象的访问,而是避免从不同线程访问同一对象。因此,解决方案是确保每次需要与数据库交互时都创建一个新的DbContext对象

using (var db = new SourceLogContext())
{
    db.LogSubscriptions.First(s => s.LogSubscriptionId == LogSubscriptionId)
        .Log.Add((LogEntry)e.LogEntry);
    db.SaveChanges();
}
我不太确定的是如何处理UI的更新。如果上面的代码在后台线程中运行,并且UI以前已绑定到LogSubscription.Log集合,则UI线程正在引用集合的另一个实例,您还必须将新条目添加到此集合

_uiThread.Post(entry => Log.Add((LogEntry)entry), e.LogEntry);
另一个复杂因素是延迟加载,在用户通过UI访问实体之前,可能无法从数据库加载实体。要处理这个问题,您似乎必须在UI线程的生命周期中至少维护一个对DbContext的引用

private static readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext();

我欢迎对这些观点发表评论。

谢谢,我已经读过那篇文章了。我使用的是SQL CE 4.0,正如文章中所说的“应用程序应该序列化对这些对象的访问”,我使用了
lock
来序列化对
SaveChanges()
的调用。我没有比我在回答中得到的更好的理解。您可以看到该项被添加到方法中的两个集合中,一个添加到上下文集合,另一个添加到“UI集合”。我遇到了同样的问题,它最终成为一个backgroundworker,试图在其他进程使用它时访问上下文。我在其他流程完成后移动了该呼叫,解决了问题。我想追问他们也会有用。据我所知,EF应该管理线程,在创建后台调用之前,我从未遇到过这样的问题。
private static readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext();