Ted*_*ddy 6 c# wpf asynchronous entity-framework
我DbContext在 WPF 应用程序中使用实体框架 6 ( ),并且我想找到一种方法来正确取消async数据加载方法 ( ToListAsync& FirstOrDefaultAsync),以便我可以立即启动另一个请求。
我一直在尝试坚持每个表单的单一上下文(在我的例子中为选项卡)标准,到目前为止,我一直在通过确保在请求期间禁用 UI 来处理这些调用的非线程安全性质,因此用户在处理过程中无法启动任何新请求。然而,我现在遇到了一个用例,这是不可能的。我需要在一些长时间运行的请求期间保持 UI 响应,为了做到这一点,我需要一种方法来取消当前请求并立即启动另一个请求。
我尝试利用CancellationToken添加到Async方法中的支持,但我发现当我取消请求时,它实际上并没有取消任何内容。它会正确抛出OperationCanceledException,但请求仍在进行中,当我尝试在此之后发出另一个请求时,我仍然得到NotSupportedException (A second operation started on this context...)
我正在使用更改跟踪,因此更改应用程序以对每个请求使用新的上下文是不现实的。
另外,我通过处理当前上下文并在每次该特定视图模型在已经进行的请求时创建一个新上下文来暂时解决了这个问题。这从技术上解决了我的问题,但我想知道是否有办法在保持相同上下文的情况下做到这一点。
那么,有人有这方面的经验吗?我发现很难相信我是第一个遇到这个问题的人,但是我在这里找到的类似问题的所有其他答案要么建议我使用(CancellationToken它不能正常工作)要么有点旧并且不适用于方法Async。
编辑1:
由于还没有人回答这个问题,我真的开始想知道我的选择是什么。一点背景知识。我正在将 Silverlight 应用程序转换为 WPF。Silverlight 应用程序使用带有 EF 4.1 的 WCF RIA 服务,但对于 WPF 应用程序,我们决定仅使用 EF6.1。
使用 Silverlight 和 WCF,您一次可以进行的异步调用数量没有限制,而且我们实际上为整个应用程序提供了一个上下文(我知道这很糟糕,但很简单,我们从未遇到过任何问题)。我们只是直接绑定到实体,并使用更改跟踪来保存用户所做的更改。
在 WPF 中是否没有办法使用 EF 6.1 和Async方法在现实世界的应用程序中执行此操作,有时,您只需要取消应用程序正在进行的操作并执行用户想要的操作,而不会崩溃和燃烧?
现在发布我的解决方案。我不是一个超级粉丝,但这就是我能够开始工作的全部内容,不需要从头开始完全重写这个应用程序。
我现在在访问或保存跟踪实体的存储库方法中使用AsyncExAsyncLock中的类。每个 DbContext 对象都使用自己的锁,因此我不会阻止来自其他上下文或未跟踪实体的其他调用。
例如,我的存储库中的 GetListAsync 方法:
public async virtual Task<IList<T>> GetListAsync(IDbContext context,
Expression<Func<T, bool>> where,
IOrderByClause<T>[] orderBy = null,
params Expression<Func<T, object>>[] navigationProperties)
{
using (await context.ContextLock.LockAsync())
{
IList<T> list = await GetListQuery(context, where, orderBy, navigationProperties).ToListAsync();
return list;
}
}
Run Code Online (Sandbox Code Playgroud)
GetListQuery 使用 nav 属性以及 where 和 order by 子句创建查询。
我可能还会使用 CancellationToken 添加超时。