2017-03-29 6 views
0

ReactiveX(より正確にはRx.Net)とSQLite.Netでデータアクセスレイヤーを構築しようとしています。ReactiveX:Observable.Create()を1回だけ呼び出すようにする

ジョブの一部が、データベース接続を返すオブザーバブルを作成しているため、必要な場合にのみ遅延して開くことができます。これは私がこれまでに思い付いたものです:

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のものであることはわかりません。

このデータベース接続をシングルトンにするにはどうすればよいですか?

答えて

0

は等価である、このコードを見てみましたが、DB接続を開きません:

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. OnCompletedを追加しても、sub2.Dispose()コールの後などの未処理のサブスクリプションがない場合でも、処分(DB-Closedを意味する)の動作が発生します。
  4. サブスクリプションをusing(var sub = connection.SelectMany(...))または明示的にsub.Dispose()で処理しないと、このObservableは終了の仕方がないため、決してサブスクリプションを解除できません。言い換えれば、3の反対の問題、あなたのCloseコードは決して起こりません。

私はあなたが画像を得ることを願っています:これはかなり誤りがちなことです。とにかくDBコールの方がうまくいく傾向があるので、私は単純な反復呼び出しをお勧めします。あなたがRXを主張するならば、私はObservable.UsingをあなたのDB接続初期化のために見るでしょう。

関連する問題