DBContexts是短暂的,每次请求都会创建和销毁。我有许多任务,我想在保存之前和之后执行,我想用某种事件模型来处理这些任务。我想知道RX是正确的路线。
是否有某种方法可以创建单例“hub”,然后导致我的DBContext引发BeforeChange(SavingChanges事件)并发布save(无适用事件)Observables并将它们“推”到长期存在的集线器中。
实际上我想在我的“hub”单身人士
中这样做 public IObservable<EventPattern<EventArgs>> Saves = new Subject<EventPattern<EventArgs>>();
public void AttachContext(DbContext context)
{
Saves = Observable.FromEventPattern<EventArgs>(((IObjectContextAdapter)context).ObjectContext, "SavingChanges");
}
但是这样的方式,AttachContext只是将生成的observable提供给exisitng保存observabe,而不是替换它(以及它的所有订阅)?
答案 0 :(得分:1)
是。使用嵌套的observable + merge:
private readonly Subject<IObservable<EventPattern<EventArgs>> _contexts = new Subject<IObservable<EventPattern<EventArgs>>();
private readonly IObservable<EventPattern<EventArgs>> _saves = _contexts.Merge();
public IObservable<EventPattern<EventArgs>> Saves { get { return _saves; } }
public void AttachContext(DbContext context)
{
_contexts.OnNext(Observable.FromEventPattern<EventArgs>(((IObjectContextAdapter)context).ObjectContext, "SavingChanges"));
}
唯一的问题是,由于Observable.FromEventPattern
永远不会完成,所观察的上下文列表将无限增长。所以这实际上是编码时的内存泄漏。
如果您知道数据库上下文将用于单个保存,那么您可以在.FirstAsync()
的调用结束时添加Observable.FromEventPattern
。这将导致您的主题在看到上下文中的事件后停止观看上下文。
这仍然存在一个问题,即可能附加了一个上下文,但它的Save从未执行过(由于逻辑或错误或其他原因)。
我知道解决问题的唯一方法是更改AttachContext
以返回调用者在想要分离上下文时必须使用的IDisposable
:
public IDisposable AttachContext(DbContext context)
{
var detachSignal = new AsyncSubject<Unit>();
var disposable = Disposable.Create(() =>
{
detachSignal.OnNext(Unit.Default);
detachSignal.OnCompleted();
});
var events = Observable.FromEventPattern<EventArgs>(((IObjectContextAdapter)context).ObjectContext, "SavingChanges");
_contexts.OnNext(events.TakeUntil(detachSignal));
return disposable;
}