Tom*_*ter 5 c# multithreading entity-framework sql-server-ce sql-server-ce-4
我正在使用Entity Framework代码和SQL Server Compact 4.0构建.NET 4 WPF应用程序.我正在尝试调用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)
Run Code Online (Sandbox Code Playgroud)
这是调用的代码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();
}
});
}
Run Code Online (Sandbox Code Playgroud)
这里的问题不是序列化对 DbContext 对象的访问,而是避免从不同线程访问同一对象。因此,解决方案是确保每次需要与数据库交互时都创建一个新的 DbContext 对象。
using (var db = new SourceLogContext())
{
db.LogSubscriptions.First(s => s.LogSubscriptionId == LogSubscriptionId)
.Log.Add((LogEntry)e.LogEntry);
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
我不太确定你如何处理更新用户界面。如果上面的代码在后台线程中运行,并且 UI 先前已绑定到 LogSubscription.Log 集合,则 UI 线程正在引用该集合的不同实例,并且您也必须将新条目添加到该集合中。
_uiThread.Post(entry => Log.Add((LogEntry)entry), e.LogEntry);
Run Code Online (Sandbox Code Playgroud)
更复杂的是延迟加载,在用户通过 UI 访问实体之前,可能不会从数据库加载实体。要处理这个问题,您似乎必须在 UI 线程的生命周期中至少维护一个对 DbContext 的引用。
private static readonly SourceLogContext DbUILazyLoadContext = new SourceLogContext();
Run Code Online (Sandbox Code Playgroud)
我欢迎对这些观点发表评论。
归档时间: |
|
查看次数: |
3360 次 |
最近记录: |