簡體   English   中英

ReactiveX:使Observable.Create()僅被調用一次

[英]ReactiveX: Make Observable.Create() be called only once

我正在嘗試使用ReactiveX(更確切地說是Rx.Net)和SQLite.Net構建數據訪問層。

一部分工作是使可觀察對象返回數據庫連接,以便僅當需要時才可以延遲打開數據庫連接。 到目前為止,這是我想出的:

var connection = Observable.Create<SQLiteConnection>(observer =>
{
    Debug.WriteLine("CheckInStore: Opening database connection");
    var database = new SQLiteConnection(configuration.ConnectionString.DatabasePath);

    observer.OnNext(database);
    observer.OnCompleted();

    return Disposable.Create(() =>
    {
        Debug.WriteLine("CheckInStore: Closing database connection");
        database.Close();
    });
});


// Further down the line, a query would look like this:
var objects = connection.SelectMany(db => db.Query<>("select * from MyTable"));

不幸的是,每當有人訂閱該可觀察對象時,都會創建一個新的連接。 並且一旦訂閱被處理,它也將關閉。

我嘗試使用.Replay(1).RefCount() ,但是它沒有任何改變。 無論如何,我不確定是否了解整個RefCount

如何使該數據庫連接成為單例?

看一下這段代碼,它是等效的,但是沒有打開數據庫連接:

var conn = Observable.Create<int>(o =>
    {
        Debug.WriteLine("Opening");
        o.OnNext(1);
        o.OnCompleted(); //This forces closing code to be called. Comment me out.
        return Disposable.Create(() =>
        {
            Debug.WriteLine("Closing");
        });
    })
    //.Replay(1)
    //.RefCount() //.Replay(1).RefCount is necessary if you want to cache the result
    ;

var sub1 = conn.SelectMany(i => Observable.Return(i)).Subscribe(i => Debug.WriteLine($"1: {i}"));
var sub2 = conn.SelectMany(i => Observable.Return(i)).Subscribe(i => Debug.WriteLine($"2: {i}"));
sub1.Dispose();
sub2.Dispose();
var sub3 = conn.SelectMany(i => Observable.Return(i)).Subscribe(i => Debug.WriteLine($"3: {i}"));
sub3.Dispose();

這里有很多問題:

  1. 每當您取消訂閱或完成可觀察項目時,您的處置/取消訂閱代碼都會被調用。 由於您正在調用OnCompleted ,因此每次都會打開/關閉它。
  2. 如果要重新使用同一連接,則需要使用.Replay(1).RefCount() 每次訂閱者連接時, Observable.Create都會運行整個功能,沒有任何東西( .Replay(1).Refcount()除外)會為您緩存它。
  3. 即使添加.Replay(1).Refcount()並刪除OnCompleted ,如果沒有未完成的訂閱(例如在sub2.Dispose()調用之后),您仍然會得到處置(意味着DB-Closed)行為。
  4. 如果您不通過using(var sub = connection.SelectMany(...))或通過sub.Dispose()顯式地處理預訂,則永遠不會取消訂閱,因為此Observable無法終止。 換句話說,與問題3相反,您的Close代碼將永遠不會發生。

我希望您能理解:這是一種非常容易出錯的處理方式。 我建議您進行一次簡單的迭代調用,因為無論如何它對於DB調用來說都更有效。 如果您堅持使用RX,那么我會看一下Observable.Using用於您的數據庫連接初始化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM