简体   繁体   English

SQL Server Compact Edition 4 - AccessViolationException

[英]SQL Server Compact Edition 4 - AccessViolationException

I'm building a .NET 4 WPF application using Entity Framework code first and SQL Server Compact 4.0. 我正在使用Entity Framework代码和SQL Server Compact 4.0构建.NET 4 WPF应用程序。 I'm trying to call DbContext.SaveChanges() on a background thread to avoid blocking the UI, but I'm occasionally getting the following exception: 我试图在后台线程上调用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)

Here's the code that calls SaveChanges() : 这是调用SaveChanges()的代码:

internal static readonly object DbSaveLockObject = new object();
public static void SaveChanges()
{
    Task.Factory.StartNew(() =>
    {
        lock (DbSaveLockObject)
        {
            Debug.WriteLine(DateTime.Now + ": SaveChanges in lock");
            Db.SaveChanges();
        }
    });
}

The issue here is not serializing access to the DbContext object, it's avoiding access to the same object from different threads. 这里的问题不是序列化对DbContext对象的访问,而是避免从不同的线程访问同一个对象。 So the solution is to ensure you create a new DbContext object every time you need to interact with the database. 因此,解决方案是确保每次需要与数据库交互时都创建新的DbContext对象。

using (var db = new SourceLogContext())
{
    db.LogSubscriptions.First(s => s.LogSubscriptionId == LogSubscriptionId)
        .Log.Add((LogEntry)e.LogEntry);
    db.SaveChanges();
}

What I'm not quite sure about is how you deal with updating the UI. 我不太确定你是如何处理更新UI的。 If the code above is running in a background thread and the UI has previously been bound to the LogSubscription.Log collection, then the UI thread is referencing a different instance of the collection and you have to add the new entry to this collection as well. 如果上面的代码在后台线程中运行并且UI先前已绑定到LogSubscription.Log集合,则UI线程引用该集合的不同实例,您还必须将新条目添加到此集合中。

_uiThread.Post(entry => Log.Add((LogEntry)entry), e.LogEntry);

A further complication is lazy loading where entities might not be loaded from the database until the user has access them through the UI. 进一步的复杂是延迟加载,其中实体可能无法从数据库加载,直到用户通过UI访问它们。 To handle this it seems you have to maintain at least one reference to the DbContext for the life of the UI thread.. 为了处理这个问题,你似乎必须在UI线程的生命周期中至少保留一个对DbContext的引用。

private static readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext();

I'd welcome comments on these points.. 我欢迎就这些问题发表评论。

An AccessViolationException occurs only when verifiable managed code interacts with unmanaged code or with unsafe managed code. 仅当可验证的托管代码与非托管代码或不安全的托管代码交互时,才会发生AccessViolationException。

You should go through this blog my MS on how to troubleshoot access voilation error: http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while-using-sql-server-compact-database-with-ado-net-provider.aspx 你应该通过这个博客我的MS如何解决访问voilation 错误:http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while-using- SQL服务器紧凑的数据库与- ADO净provider.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM