2013-02-14 16 views
12

コンテキスト:私はしばしば私たちのASP.NETページはGridViewの上のユーザーにデータを表示しなければならない状況にしてきたASP.NETのポストバック間でデータの永続化

、彼は喜ばとして彼はそれを変更してみましょう(セル上のテキストボックス)、実際に「保存ボタン」に当たったときにのみデータベースに保存します。このデータは、通常、ページ上の情報の仮想状態です。つまり、ユーザーが「保存ボタン」を押すまで、実際に保存せずにすべてを変更できます。 このような場合、常にASP.NETポストバック間で永続化する必要があるデータのリストがあります。このデータは、DataTableのインスタンスか、またはわずかにList<Someclass>のインスタンスです。

これを実装し、データをSessionに保存している人がよく見受けられます。そのような場合、私は通常、複数のタブを開いてナビゲートするユーザーが同じページで何度か開いてしまうという問題を抱えています。 2つの異なるタブのデータがマージされ、情報がスクランブルされるという問題を引き起こします。セッションが頻繁に使用される方法の

例:二つのタブがすでにロードされ、ユーザーされている場合について

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!IsPostBack) 
    { 
     DataList = null 
    } 
    else 
    { 
     FillGridView(DataList); 
    } 
} 

しかし、どのような:

private List<SomeClass> DataList 
{ 
    get 
    { 
     return Session["SomeKey"] as List<SomeClass>; 
    } 
    set 
    { 
     Session["SomeKey"] = value; 
    } 
} 

人々頻繁にこのような何かをすることによってそれを解決しようとしますGridViewの値が変更されていて、別のページの[保存]ボタンを押してデータを保存しようとすると、何か不思議な理由がありますか?私は個人的にこのオプションを嫌っています。

これを行う他の方法は、データをViewStateに入れることです。しかし、大幅に大きなリストを保持する場合は、ページに格納されているときにページに重大な影響を与える可能性があります(HiddenField)。

しかし、それを実現する最も良い方法は何ですか?一度、私はViewStateと一緒にSessionを使用して、ViewStateSessionセーブしたデータをインデックスするユニークな識別子を保持すると考えました。それは、ブラウザのタブの間でデータを共有妨げる:

private List<SomeClass> DataList 
{ 
    get 
    { 
     if (ViewState["SomeKey"] == null) 
     { 
      ViewState["SomeKey"] = Guid.NewGuid().ToString(); 
     } 

     return Session[ViewState["SomeKey"].ToString()] as List<SomeClass>; 
    } 
    set { 

     if (ViewState["SomeKey"] == null) 
     { 
      ViewState["SomeKey"] = Guid.NewGuid().ToString(); 
     } 

     Session[ViewState["SomeKey"].ToString()] = value; 
    } 
} 

一方、それがセッションにユーザーがページを入力するたびに、データの新しいリストを格納します。これはサーバーのメモリに影響を与えます。たぶん何らかの方法で消去することができるかもしれません。

質問:

サーバーへと保守コーディングチームに少ないコストで、ブラウザ上で複数のタブのコンテキストを考慮すると、ポストバック間でのデータのようなものを永続化する最良の方法は何だろう?

更新:きれいに掲載@nunespascalとして

、一つの選択肢はSessionPageStatePersisterを使用してSessionViewStateを保存することです。しかし残念ながらそれは私の場合の選択肢ではありません。しかし、ViewStateに保存されたUniqueIdによってインデックスされたセッションにデータを保存することは、私の最後の例とあまり変わりません。

その他のオプションはありますか?

+0

2つ目のアプローチは、いくつかの調整が可能です:1)ViewStateではなく隠しフィールドを使用する。 ViewStateがページ上で利用可能になる前にアクセスすることができます(時には便利です)。 2)一度に保管できるアイテムの数を制限し、最も古いアイテムを廃棄するマネージャーとのセッションをラップします。もちろん、これはメモリの問題を完全に解決するわけではありませんが、ビジー状態のユーザーが何百もの大きなオブジェクト/セットをメモリに持つことを心配することなく、ユーザーがアプリケーション内で有機的に作業できるようにするためには長い道のりがあります。 –

答えて

2

この問題を解決する簡単な方法があります。ViewStateをセッションに格納します。あなたが使用する必要があることについては

SessionPageStatePersister

参照してください:Page State Persister

あなたがPageStatePersisterをオーバーライドして、それは代わりにデフォルトHiddenFieldPageStatePersister

protected override PageStatePersister PageStatePersister 
{ 
    get 
    { 
     return new SessionPageStatePersister(this); 
    } 
} 

これをのSessionPageStatePersisterを使用して作るするだけです独自のキーを維持するという頭痛を軽減します。隠しフィールドは、ページのインスタンスごとに一意のキーを保持するために自動的に使用されます。

+0

はい、それは間違いなくそれを解決するでしょう。残念ながら私の場合はオプションではありませんが、すばやい回答に感謝します。 –

+0

viewstateに保存してセッションにviewstateを格納すると、投稿された最後の例とはどのように違いますか?つまり、ユーザーがページをリフレッシュして毎回新しいデータをセッションに格納すると、サーバーのメモリに影響を及ぼしたり、管理されたりすることはありませんか? –

+0

はい、サーバーのメモリに影響します。しかし、これはセッションに直接データを格納していても負担になります。繰り返されるリフレッシュに関しては、それらはセッションスペースを奪います。しかし、このような問題に直面した場合、セッションでは常にデータベースに移動するオプションがあります。セッションは最終的にパージされます。 – nunespascal

0

私は同様の状況に遭遇しました。グリッドビューを変更するために各ユーザーの長いセッションを許可すると、最終的にデータの最後の変更セットが1つしか受け入れられないため、並行性の問題も発生します。

私の解決策は、データベースを変更できるようにすることですが、すべてのユーザーがSignalRで同じ状態を確認するようにしました。

ここでは、並行性の問題は解消されましたが、その場で変更を行う必要があります。あなたは結局変更を保存したくないかもしれません。私はコマンドデザインパターンを適用してこの問題を解決しました。変更のセットは、承認または破棄することができます。インデックスを確認するたびに、最後に承認されたグリッドビューが表示されます。更新ページに移動すると、ライブ更新されたグリッドビューが表示されます。また、古い承認グリッドビューを見るためにリビジョンに行く - コマンドデザインパターンの他の利点 -

関連する問題