2015-09-21 12 views
5

ステートフルなアプリケーションに適したORMが必要です。私は、持続的なクライアント接続を持つ低レイテンシのリアルタイムゲームサーバーの要求の間にエンティティを保つつもりです。データベースには1つのサーバーインスタンスしか接続されていないため、「外部」からデータを変更することはできず、サーバーはそのキャッシュに頼ることができます。ステートフルアプリケーション用のORM。 EFは適合していますか?または何か?

ユーザがリモートでサーバにログインすると、そのプロファイル全体がサーバメモリにロードされます。プロファイルデータを操作して機能を提供するために、各ユーザーごとに複数の上位レベルのサービスも作成されます。また、一時的なデータを格納する内部フィールド(状態)を持つこともできます。ユーザーは自分の署名を変更したいとき、対応するサービスにそうするように頼む。このサービスは、ユーザーが自分の署名を変更する頻度を追跡し、10分に1回(たとえば)許可します。このような短い間隔はdbで追跡されません。これは一時的な状態です。この変更は、1つのクエリ:UPDATE users SET signature = ... WHERE user_id = ...を実行しているdbに格納する必要があります。ユーザーがログオフすると、数分または数時間休止した後にサーバーメモリからアンロードされます。ここのDbはストレージだけです。これは私がステートフルと呼ぶものです。

  1. 一部のエンティティは「静的データ」とみなされ、アプリケーションの開始時に1回だけロードされます。それらは他の「動的」エンティティから参照することができます。 「動的」エンティティの読み込みは、参照された「静的データ」エンティティの再ロードを必要とすべきではありません。
  2. /Insert/Deleteは、 "detached"エンティティであっても、変更されたプロパティ/エンティティのみを設定/挿入/削除する必要があります。
  3. 書き込み操作では、変更を検出するために暫定的にデータベースからデータをロードしないでください(Selectを実行してください)。 (状態は動的に生成された継承元で追跡できます)。私はローカルに状態を持っていますが、何もロードする意味がありません。 接続スコープの外でも変更を追跡し、必要に応じて「アップロード」を変更したいと考えています。
  4. 永続オブジェクトの操作参照は変更しないでください。
  5. DBConnection-per-userは動作しません。予想されるオンラインは数千人のユーザーです。
  6. "静的データ"からのエンティティは "動的"エンティティプロパティ(外部キーを表す)に割り当てられ、Updateはそれを正しく処理する必要があります。

ステートレスアプリケーション用に設計されていますが、NHibernateを使用しています。それはセッションへの再接続をサポートしていますが、それは非常に珍しい使用法のように見え、私には文書化されていない動作を使用する必要があり、すべてを解決するものではありません。

私はEntity Frameworkについてよく分かりません。私はそのように使用できますか?または、別のORMを提案できますか?

ユーザがボタンを押すたびにサーバを再作成(または特にリロード)すると、CPUが非常に早く食べられます。 CPUは垂直に高価にスケールされますが、効果はわずかです。逆に、RAMが足りない場合は、横方向のスケーリングと同じようにコードを書くことができます。ここで別のアプローチを使うべきだと思うなら、私はそれについて議論する準備ができています。

+0

Nhibernateがステートレスアプリケーション用に設計された理由がわかりません。 NHのセッションはかなりステートフルなようです。 –

+3

2つのwrt適用アーキテクチャの違いはあまりありません。しかし、この質問は広すぎると意見に基づいている、賞金はそれを修正しません。そして、session.Merge、SaveOrUpdateなどについては、珍しく、文書化されていないものは何ですか? –

+0

@ GertArnoldこれらのメソッドはSelectを使用します。#3を参照してください。 Session.Lock(再接続、変更、コミット)をいくつかの文書化されていない振る舞いを持って使用する必要があります(それは2回呼び出すといくつかのチェックを無視できます - 最初のスローのみ)。 – Vlad

答えて

1

はい、この種のアプリケーションにEFを使用できます。重い負荷では、いくつかのdbエラーが随時発生することに注意してください。また、通常は、アプリケーションがEFではなく変更を追跡するときに、エラーが発生した後に回復する方が迅速です。ちなみに、この方法でもNHibernateを使うことができます。

+0

NHibernateを正確にどのように使うことができるでしょうか?そして、EFの場合 - そのような使用の例はありますか?私は、EFには、NHと同じように、自分のDbContextにエンティティが厳密に付けられていると思っていました。 – Vlad

+0

デフォルトでは、EFはエンティティをセッションに接続します。この動作を無効にするには、.AsNoTracking()を使用できます。 NHibernateの場合、session.Evict(yourObj)になります。 – Sandre

+0

しかし、私は 'UPDATE'する必要があるときにどのように変化を検出しますか?別の 'SELECT'をしていますか?これは私が避けたいものです。 – Vlad

1

非常に長いセッションを持つステートフルなデスクトップアプリケーションでhibernateを使用しました。セッションは、アプリケーションの起動時に開始され、アプリケーションの実行中は開いたままです。私はそれに問題はなかった。私は、取り付け、取り外し、再取り付けなどを絶対に使用しません。私はそれが標準的な習慣ではないことを知っていますが、それは実行不可能であるということを意味するものでも、落とし穴もありません。 編集:

私は自分の変更通知メカニズムも実装しています(別のスレッドがDBを直接ポーリングし、休止状態をバイパスしています)休止状態が実行されている間に外部エージェントにデータベースを変更させ、アプリケーションにこれらの変更を通知させることさえ可能です。

すでに休止状態で作業しているものがたくさんある場合は、休止状態が達成したいことを絶対に行わないことが確実でない限り、すでに持っているものを放棄して書き直すことはお勧めできません。

+1

"DBConnection-per-userは動作しません。予想されるオンラインは数千人のユーザーです。"また、私はマルチスレッドアプリケーション全体に対して単一セッションを使用することはできません。キャッシュ時間が切れると、メモリからユーザーをすべてアンロードする必要があります。 – Vlad

+0

ユーザごとに1つのdb接続を使用する必要はありません。実際には、あなたができるとは思っていません。それは、アクティブなユーザごとに1つの 'SessionManager'をインスタンス化することを意味するからです。すべてのユーザが 'SessionManager'の同じインスタンスにアクセスできるように、アプリケーションと休止状態の間にレイヤーを実装するだけです。それがオプションでない場合は、必要に応じてセッションマネージャをインスタンス化する必要があり、多くの接続や切り離しを行う必要がありますが、私が知る限り、これも完全に休止状態で実行できます。それが、なぜそれが着脱をサポートするのかということです。 –

+0

SessionManagerによってあなたはISessionFactoryを意味しますか?各セッション(少なくとも何かを照会するために使用されると)は、別々のデータベース接続を使用することを知っていますか? – Vlad