2013-04-04 10 views
7

私は、ASP.NET、つまりMySQL、Oracleなどの異なる(SessionState、Profileなど)プロバイダをテストするプロトタイププログラムで作業しています。 MySQLプロバイダ私はプロバイダ、SessionStateContainer、およびSessionState自体をインスタンス化することができたばかりです。手動でインスタンス化されたSessionStateプロバイダの問題

Type mySqlType = Type.GetType("MySql.Web.SessionState.MySqlSessionStateStore, MySql.Web, Version=6.6.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", true, true); 

SessionStateStoreProviderBase provider = (SessionStateStoreProviderBase)Activator.CreateInstance(mySqlType); 
System.Collections.Specialized.NameValueCollection providerConfig = new System.Collections.Specialized.NameValueCollection(); 
providerConfig.Add("connectionStringName", "LocalMySqlServer"); 
providerConfig.Add("applicationName", "/"); 
providerConfig.Add("autogenerateschema", "True"); 
providerConfig.Add("enableExpireCallback", "False"); 

provider.Initialize("MySqlSessionStateProvider", providerConfig); 

HttpContext context = new HttpContext(
          new HttpRequest("fake", "http://localhost:14359", ""), 
          new HttpResponse(new StringWriter())); 

SessionStateStoreData storeData = provider.CreateNewStoreData(context, 100); 
System.Web.SessionState.HttpSessionStateContainer sessionStateContainer = 
    new System.Web.SessionState.HttpSessionStateContainer(
      "mySession", 
      storeData.Items, 
      storeData.StaticObjects, 
      100, 
      true, 
      System.Web.HttpCookieMode.UseDeviceProfile, 
      SessionStateMode.Custom, 
      false 
    ); 

Type sessionStateType = Type.GetType("System.Web.SessionState.HttpSessionState, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); 
HttpSessionState sessionState = 
    (HttpSessionState)sessionStateType 
     .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(IHttpSessionState) }, null) 
     .Invoke(new object[] { ssessionStateContainer }); 

provider.InitializeRequest(context); 

すべては私が作成したセッションでは、いくつかの値を書き込むことができるよと、正常に動作しているようだ、と私はそこからそれらを読むことができるよ:

sessionStateContainer.Add("SomeKey", "SomeValue"); 
var test = sessionStateContainer["SomeKey"]; 
Console.WriteLine("var test: " + test.ToString()); // outputs "var test: SomeValue" 

sessionState.Add("AnotherKey", "SomeOtherValue"); 
var test2 = sessionState["AnotherKey"]; 
Console.WriteLine("var test2: " + test2.ToString()); // outputs "var test2: SomeOtherValue" 

// End the request 
provider.EndRequest(context); 

ここに来ます興味深い部分 - DB内のmy_aspnet_sessionsテーブルを調べると、そこには何もありません。

私はデータが書かれているか、何か間違っているのでしょうか?

更新:
この問題は、もはやブロッカーですが、私はまだ知って興味ないし、誰もがそれを試しを与えるためにアップしている場合は、ここで私が使用したconnectionStringです:

<connectionStrings> 
    <remove name="LocalMySqlServer" /> 
    <add name="LocalMySqlServer" connectionString="server=localhost;database=session_test;User Id=user;password=pass" providerName="MySql.Data.MySqlClient" /> 
</connectionStrings> 

MySQL Connector NETも必要です。あなたのweb.configファイルで

+0

新しい '.Invoke(新しいオブジェクト[] {ssessionStateContainer}を作成することによって、この行のデータを消去することができます。これ、あなたのような何かを実行する必要があり、データベースにセッションデータを参照するために与えられ

); 'あなたがコードをステップ実行したときに何が起きるのですか? – MethodMan

+0

2つのスニペットは私のコードで同じ順序です。データの書き込みは 'sessionState'のインスタンス化後に行われるので、どのようにクリアできるのか分かりません。コードをステップ実行すると、対応するプロパティで 'SomeKey'と' AnotherKey'キーを見ることができますが、それ以上のものはありません。 – Havelock

答えて

3

SessionStateModuleは、要求終了がコマンドSetAndReleaseItemExclusiveを呼び出すのを待つため、データベースにデータはありません。そのようなコマンドが呼び出されるまで、データはメモリに保持されます。実際のドキュメントの状態:

SessionStateModuleオブジェクトは、データストアに現在のセッションアイテム情報を挿入したり、既存のセッションアイテムの情報を更新するために、たReleaseRequestStateイベント中に、要求の終了時にSetAndReleaseItemExclusiveメソッドを呼び出し現在の値を持つデータストア、アイテムの有効期限を更新したり、データのロックを解除することができます。指定されたセッションIDとlockId値と一致する現在のアプリケーションのセッションデータのみが更新されます。ロックの詳細については、SessionStateStoreProviderBaseクラスの概要の「セッションストアデータのロック」を参照してください。

詳細については、relevant files from the mono codebaseをご覧ください。

object storeLockId = new object(); 
sessionStateContainer.Add("SomeKey", "SomeValue"); 
var test = sessionStateContainer["SomeKey"]; 
Console.WriteLine("var test: " + test.ToString()); 

sessionState.Add("AnotherKey", "SomeOtherValue"); 
var test2 = sessionState["AnotherKey"]; 
Console.WriteLine("var test2: " + test2.ToString()); 

// End the request 
provider.SetAndReleaseItemExclusive (context, sessionStateContainer.SessionID, 
            storeData, storeLockId, true); 
provider.EndRequest(context); 
+0

私はプロバイダのEndRequest()メソッドを呼び出しています。私の質問でコードスニペットを更新しました。 – Havelock

+0

@Havelock [こちら](https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web.SessionState_2.0/SessionSQLServerHandler.cs#l529)でご覧いただけます。 stateproviderのEndRequestは、しばしば空です。 ** SessionStateModule **は、** [OnRequestEnd](https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web.SessionState_2)の** SetAndReleaseItemExclusive **を呼び出します。 0/SessionStateModule.cs#L325)ハンドラー**([OnReleaseRequestState](https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web.SessionState_2.0/SessionStateModule経由) .cs#L278))。 –

+0

明らかに、MS.NETの実装は異なる可能性がありますが、Monoの動作はドキュメントに準拠しているため(移植の問題を最小限に抑えるため) –

0

は、あなたがそれ以外の場合はモード=「カスタム」

<sessionState mode="Custom" customProvider="YourProvider"> 

を設定する必要があり、セッションデータは関係なく、プロバイダのメモリに格納されます。

+0

'Custom'モードは' HttpSessionStateContainer sessionStateContainer'をインスタンス化する際に指定されます(上記のコードを参照)。デバッグ時にフィールドを調べると、実際にはモードが「カスタム」であることがわかりました。問題はありません。 – Havelock

+0

@Havelock - mysqlログを有効にしてみてください。 mysqlに何かが送信されているかどうかを確認してください。多分それはDBに送られていますが、コミットされていません。 –

+0

良いアイデアだが、残念ながら助けにはならなかった。 – Havelock

関連する問題