C# SQL Server Compact Edition 4-AccessViolationException
我正在首先使用实体框架代码和SQLServerCompact4.0构建一个.NET4WPF应用程序。我试图在后台线程上调用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
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();