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

本文关键字:观察 RX 创建 DBContexts | 更新日期: 2023-09-27 18:21:25

DBContexts寿命很短,每次请求都会创建和销毁。我有很多任务想在保存之前和之后执行,我想用某种事件模型来处理这些任务。我想知道在RX是正确的路线。

有没有办法创建一个单独的"集线器",然后让我的DBContext引发BeforeChange(SavingChanges事件)和postsave(没有适用的事件)Observables,并将它们"推送"到长寿命的集线器中。

实际上,我想在我的"中枢"单例中这样做

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

但是,AttachContext只是将其生成的可观察对象馈送到exisitng Saves observable中,而不是替换它(及其所有订阅)?

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

是。使用嵌套的可观察+合并:

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永远不会完成,因此观察到的上下文列表将变得无限。因此,这实际上是一个编码的内存泄漏。

如果知道数据库上下文将用于单个保存,则可以在对Observable.FromEventPattern的调用末尾添加一个.FirstAsync()。这将导致你的受试者在看到事件后停止观看上下文。

这仍然存在这样的问题,即可能附加了上下文,但从未执行其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;
}