简体   繁体   English

如何从多个DBContext创建可观察的热RX

[英]How do I create a hot RX observable from multiple DBContexts

DBContexts are short lived, created and destroyed with every request. DBContexts对于每个请求都是短暂的,创建和销毁的。 I have a number of tasks that I'd like to perform prior to and post save and I'd like to handle these with some sort of eventing model. 在保存之前和之后,我有许多任务要执行,我想用某种事件模型来处理这些任务。 I'm wondering in RX is the right route. 我想知道RX是正确的路线。

Is there some way of creating a singleton "hub" then causing my DBContext to raise BeforeChange (SavingChanges event) and post save (no applicable event) Observables and "push" them into the long lived hub. 有什么方法可以创建单例“集线器”,然后使我的DBContext引发BeforeChange(SavingChanges事件)并发布保存(无适用事件)Observables,然后将它们“推入”寿命长的集线器中。

In effect I'd like to do this in my "hub" singleton 实际上,我想在“集线器”单例中执行此操作

    public IObservable<EventPattern<EventArgs>> Saves = new Subject<EventPattern<EventArgs>>();

    public void AttachContext(DbContext context)
    {
        Saves = Observable.FromEventPattern<EventArgs>(((IObjectContextAdapter)context).ObjectContext, "SavingChanges");
    }

but in such a way that AttachContext simply feed its generated observable into the exisitng Saves observabe, rather than replacing it (and all of its subscriptions)? 但是以这样的方式,AttachContext只是将其生成的可观察对象喂入到现有的Saves观察对象中,而不是替换它(及其所有订阅)?

Yes. 是。 Use a nested 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"));
}

The only problem with this is that the list of contexts being observed will grow unbounded since the Observable.FromEventPattern never completes. 唯一的问题是,由于Observable.FromEventPattern永远不会完成,因此要观察的上下文列表将变得不受限制。 So this is effectively a memory leak as coded. 因此,按编码,这实际上是内存泄漏。

If you know that the db context will be used for a single save, then you could add a .FirstAsync() to the end of the call to Observable.FromEventPattern . 如果知道 db上下文将用于一次保存,则可以在对Observable.FromEventPattern的调用的末尾添加.FirstAsync() This will cause your subject to stop watching the context once it has seen an event from it. 一旦看到主题事件,这将导致您的主题停止观看上下文。

This still suffers from the problem that maybe a context is attached but its Save is never performed (due to logic, or an error or whatever). 这仍然遭受以下问题的困扰:可能附加了上下文,但从未执行过“保存”操作(由于逻辑,错误或其他原因)。

The only way I know to resolve the problem is to change AttachContext to return an IDisposable that the caller must use when they want to detach the context: 我知道解决此问题的唯一方法是更改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;
}

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

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