SQL Server Compact Edition 4 - AccessViolationException [英] SQL Server Compact Edition 4 - AccessViolationException

查看:176
本文介绍了SQL Server Compact Edition 4 - AccessViolationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Entity Framework代码和SQL Server Compact 4.0构建一个.NET 4 WPF应用程序。我试图在后台线程上调用 DbContext.SaveChanges()以避免阻止UI,但是我偶尔得到以下异常:

 发生System.AccessViolationException 
消息=尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
Source = System.Data.SqlServerCe
StackTrace:
在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)
在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)
在System.Data.SqlServerCe.SqlCeConnection.Open(Boolean silent)
在System.Data.SqlServerCe.SqlCeConnection.Open()
在System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition,DbConnection storeConnectionToOpen,DbConnection originalCo nnection,String exceptionCode,String attemptsOperation,Boolean&在System.Data.Object.ObjectContext.EnsureConnection()
System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)
在System.Data.Entity.Internal.InternalContext.SaveChanges()
在System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
在System.Data.Entity.DbContext .SaveChanges()
在SourceLog.Model.LogSubscriptionManager。< SaveChanges> b__2()在C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\LogSubscriptionManager.cs:line 51
InnerException:(null)

这里是调用 SaveChanges()

 内部静态只读对象DbSaveLockObject = new object(); 
public static void SaveChanges()
{
Task.Factory.StartNew(()=>
{
lock(DbSaveLockObject)
{
Debug.WriteLine(DateTime.Now +:SaveChanges in lock);
Db.SaveChanges();
}
});
}


解决方案

访问DbContext对象,它避免从不同的线程访问同一个对象。所以解决方案是确保您每次需要与数据库进行交互时创建一个新的DbContext对象。

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

我不太确定的是如何处理更新UI 。如果上面的代码在后台线程中运行,并且UI先前已被绑定到LogSubscription.Log集合,那么UI线程将引用该集合的另一个实例,并且必须将新条目添加到该集合中。

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

进一步的复杂性是延迟加载,在用户访问它们之前,实体可能无法从数据库加载通过UI。为了处理这个问题,您似乎必须至少保留一个对UI线程的使用DbContext的引用。

  private静态readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext(); 

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


I'm building a .NET 4 WPF application using Entity Framework code first and SQL Server Compact 4.0. I'm trying to call DbContext.SaveChanges() on a background thread to avoid blocking the UI, but I'm occasionally getting the following exception:

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():

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. So the solution is to ensure you create a new DbContext object every time you need to interact with the database.

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. 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.

_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. To handle this it seems you have to maintain at least one reference to the DbContext for the life of the UI thread..

private static readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext();

I'd welcome comments on these points..

这篇关于SQL Server Compact Edition 4 - AccessViolationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆