2010-11-25 18 views
4

私たちは、このようにApp_Code内の中央HttpSessionState管理実装するWebサイトがあります。これはすべて私たちが必要な細かいultilを働いた別のスレッドやトリックからHttpSessionState(HttpContext.Current.Session)にアクセスしますか?

public class Funx 
{ 
    public DataTable QuerySQLDT(string SQLx) 
    { 
     try 
     { 
      CurrentSession.connection.Open(); 
     } 
     catch (Exception ex) 
     { 
      ServicioTecnico.EnviarMailError("Error openning connection", ex); 
      HttpContext.Current.Response.Redirect("SesionExpirada.aspx", true); 
     } 
     try 
     { 
      CurrentSession.command.CommandText = SQLx; 
      CurrentSession.dataadapter.SelectCommand = SessionActual.command; 

      CurrentSession.datatable.Clear(); 
      CurrentSession.datatable.Reset(); 
      CurrentSession.dataadapter.Fill(SessionActual.datatable); 

      CurrentSession.connection.Close(); 
     } 
     catch (Exception ex) 
     { 
      try 
      { 
       CurrentSession.connection.Close(); 
      } 
      catch { } 
      try 
      { 
       ex.Data.Add("SQLx", SQLx); 
       ServicioTecnico.EnviarMailError("Error closing connection", ex); 
      } 
      catch { } 
      throw; 
     } 

     return CurrentSession.datatable.Copy(); 
    } 
} 

:(例えば)それを使用しています

public static class CurrentSession 
{ 
    public static HttpSessionState Session 
    { 
     get 
     { 
      return HttpContext.Current.Session; 
     } 
    } 

    public static bool Exists 
    { 
     get 
     { 
      return Session != null ? true : false; 
     } 
    } 
    public static ControlUsu user 
    { 
     get 
     { 
      return (ControlUsu)Session["currentuser"]; 
     } 

     set 
     { 
      Session["currentuser"] = value; 
     } 
    } 
    public static OdbcConnection connection 
    { 
     get 
     { 
      return (OdbcConnection)Session["currentconnection"]; 
     } 
     set 
     { 
      Session["currentconnection"] = value; 
     } 
    } 
    public static OdbcCommand command 
    { 
     get 
     { 
      return (OdbcCommand)Session["currentcommand"]; 
     } 
     set 
     { 
      Session["currentcommand"] = value; 
     } 
    } 
    public static DataTable datatable 
    { 
     get 
     { 
      return (DataTable)Session["currentdatatable"]; 
     } 
     set 
     { 
      Session["currentdatatable"] = value; 
     } 
    } 
    public static OdbcDataAdapter dataadapter 
    { 
     get 
     { 
      return (OdbcDataAdapter)Session["currentdataadapter"]; 
     } 
     set 
     { 
      Session["currentdataadapter"] = value; 
     } 
    } 
    public static Table tablatemp 
    { 
     get 
     { 
      return (Table)Session["tablatemp"]; 
     } 
     set 
     { 
      Session["tablatemp"] = value; 
     } 
    } 

    public static void Init() 
    { 
     user= new ControlUsu(); 
     connection= new OdbcConnection(); 
     command= new OdbcCommand(); 
     datatable = new DataTable(); 
     dataadapter = new OdbcDataAdapter(); 
     tablatemp = new Table(); 
     //SessionActual.conexion.ConnectionTimeout = 0; 
    } 
} 

機能クラスを... 2番目のスレッドでは、HttpContext.Current.Sessionはnullです(現在のコンテキストはスレッド間で異なるため)。S

私たちは、あなたがこのような別のスレッドからのセッションを渡すことがわかっ調査0

using App_Code; 
public partial class Example: Page 
{ 
    private void startoperation 
    { 
     Session["savedsession"] = HttpContext.Current.Session; 
     ThreadStart operation = delegate { buscar(); }; 
     Thread thread = new Thread(operation); 
     thread.Start(); 
    } 
    private void longoperation 
    { 
     HttpSessionState mySession = ((HttpSessionState)Session["savedsession"]); 
     //what we would like to do 
     //CurrentSession.Session = mySession; 

     Funx fun=new Funx(); 
     DataTable resul=Funx.QuerySQLDT(select * from exampletable"); 
    } 
} 

私たちがやりたいことは、新しいスレッドにセッションasociateです(CurrentSession.Session = mySession;)ので、すべての関数はそれを変更することなくそのまま動作します(この最後の追加のためにアプリケーションのすべての構造を変更する必要はありません)が、HttpContext.Current.Sessionにはセッターはありません:S(セッターを追加する必要があることはわかっています私たちのCurrentSession.Sessionプロパティに)

だからあなたはそれをどうやって解決しますか?どんな素晴らしいトリックですか? 私たちが持っていたアイデアの1つは、CurrentSession.Sessionをdinamicポインタなどのように変換することです。そのため、2番目のスレッド内の関数を使用する場合、CurrentSession.Sessionのゲッターは、そのケースに対して渡されたtemp変数からセッションを返しますスレッドの...しかし、我々はそれを実装する方法を明確な考えを持っている...可能草案は次のようになりいけない:

public static class CurrentSession 
{ 
    public static HttpSessionState magicpointer; 

    public static HttpSessionState Session 
    { 
     get 
     { 
      //return HttpContext.Current.Session; 
      return magicpointer; 
     } 
     set 
     { 
      magicpointer=value; 
     } 
    } 
} 

public partial class Example : Page 
{ 
    bool completedtask=false; //we know this would be Session variable or so to work with threads 
    private void startoperation 
    { 
     Session["savedsession"] = HttpContext.Current.Session; 
     ThreadStart operation = delegate { buscar(); }; 
     Thread thread = new Thread(operation); 
     thread.Start(); 
    } 
    private void longoperation 
    { 
     HttpSessionState mySession = ((HttpSessionState)Session["savedsession"]); 

     CurrentSession.Session = mySession; 
     //or set the magicpointer...whatever works... 
     CurrentSession.magicpointer= mySession; 

     Funx fun=new Funx(); 
     DataTable resul=Funx.QuerySQLDT(select * from exampletable"); 

     //time consuming work... 

     completedtask=true; //change the flag so the page load checker knows it... 
    } 
    private void page_load_checker() 
    { //this combined with javascript that makes the page postback every 5 seconds or so... 
     if(completedtask) 
     { 
      //show results or something like that 
      //set the CurrentSession.magicpointer or CurrentSession.Session 
      //to point the HttpContext.Current.Session again... 
      CurrentSession.magicpointer=HttpContext.Current.Session; 
     } 
    } 
} 

するので、あまりにも長い間、このポストを作るについては申し訳ありません...歴史のthatsが、我々が望んでいました混乱や逸脱した回答を防ぐために状況を明確にする...ありがとう!

+0

アイデアは、データベースリクエスト、現在のユーザ変数などを処理する(私たちは、後でそれをどのWebプロジェクトでも簡単に使うための関数ライブラリを作った)集中的な関数を持つことです。メソッドからメソッドへ、ページからページへ、スレッドからスレッドへ... – VSP

+0

私たちはすべての構造を変更することができますが、objetiveは現在のようにその機能を使いやすくしています。悪くはありません。 – VSP

答えて

1

インターフェイスを作成できます。

public interface ISession 
{ 
    public ControlUsu user {get; set;} 
    public OdbcConnection connection {get; set;} 
    //Other properties and methods... 
} 

次に、それを実装する2つのクラスを設定できます。

//Use this class when you have HttpSessionState 
public class ProgramHttpSession : ISession 
{ 
    public ControlUsu user 
    { 
     get {return (ControlUsu)Session["currentuser"];} 
     set {Session["currentuser"] = value;} 
    } 
    public OdbcConnection connection 
    { 
     get {return (OdbcConnection)Session["currentconnection"];} 
     set {Session["currentconnection"] = value;} 
    } 
} 

//Use this class when you DON'T have HttpSessionState (like in threads) 
public class ProgramSession : ISession 
{ 
    private ControlUsu theUser; 
    public ControlUsu user 
    { 
     get {return theUser;} 
     set {theUser = value;} 
    } 

    private OdbcConnection theConnection; 
    public OdbcConnection connection 
    { 
     get {return theConnection;} 
     set {theConnection = value;} 
    } 

    public ProgramSession(ControlUsu aUser, OdbcConnection aConnection) 
    { 
     theUser = aUser; 
     theConnection = aConnection; 
    } 
} 

あなたのスレッドクラスがパラメータとしてISessionを取る持っています。スレッドを作成または開始するときにProgramHttpSessionProgramSessionに変換し(コンストラクタでこれをカバーする必要があります)、ProgramSessionオブジェクトをスレッドに渡します。このようにして、アプリケーションとスレッドは同じインタフェースに対して動作しますが、同じ実装では動作しません。

これは問題を解決するだけでなく、スレッドがHttpSessionStateに依存しなくなったため、テストがはるかに簡単になるはずです。今あなたのスレッドをテストするときには、そのISessionインターフェイスを実装する任意のクラスを渡すことができます。

+0

これはうまくいくが、依然として問題のすべてのメソッド/クラスをリファクタリングして 'Session 'を操作する必要がある – Basic

+0

問題は私たちの場合には多くのメソッドと変数があり、ケース+私たちがセッションに入れた新しい変数を追加することを覚えています...:S – VSP

2

あなたのコードをリファクタリングする方が良いでしょう。あなたの関数は、(セッション中に)周囲に存在するデータに頼るのではなく、実際に動作するパラメータを実際に取るようにしてください。現在のユーザーが誰であるかを知る必要がある機能を持っている場合は、現在のユーザーが誰であるかを伝えます。

+2

+1これは短期的には非常に苦痛であり、長期的には非常に有益です。単体テスト、IoC、依存関係注入などを簡単にすることができます。これが遠隔からでも可能であれば、良い考えです。 – Basic

関連する問題