これはおそらくニッチな問題ですが、誰かが私を助けてくれるかもしれません。WebサービスをASMXからWCFに移植していますが、完全にCastleActiveRecord上に構築されています。構成になんらかの奇妙な問題がないことを確認するために、NuGetの最新のCastleライブラリとNHibernateライブラリをすべて使用して、分離された再現を最初から作成しました。
私が最初にすることは、でActiveRecordを初期化することですApplication_Start
。通常はweb.config
インスタンスを使用しますが、これはおそらく問題ではありません。
protected void Application_Start(object sender, EventArgs e)
{
//NHibernate.Driver.OracleClientDriver
IDictionary<string, string> properties = new Dictionary<string, string>();
properties.Add("connection.driver_class", "NHibernate.Driver.OracleClientDriver");
properties.Add("dialect", "NHibernate.Dialect.Oracle10gDialect");
properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("connection.connection_string", "user Id=xxx;password=xxx;server=localhost;persist security info=True");
properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
InPlaceConfigurationSource source = new InPlaceConfigurationSource();
source.IsRunningInWebApp = true;
source.ThreadScopeInfoImplementation = typeof(Castle.ActiveRecord.Framework.Scopes.HybridWebThreadScopeInfo);
source.Add(typeof(ActiveRecordBase), properties);
ActiveRecordStarter.Initialize(source, typeof(Task), typeof(Project));
}
WCFではnullになるHybridWebThreadScopeInfo
ため、実装も使用していることに注意してください。HttpContext.Current
次に、Webサービスを実装します。
public class Service1 : IService1
{
public string GetData(int value)
{
Project p;
p = Project.Find(123M);
var count = p.Tasks.Count(); //Force count query
return p.GoldDate.ToString();
}
}
私が電話するときProject.Find()
、それはうまくいきます。次に、プロパティがレイジーであるため、これを呼び出しp.Tasks.Count()
て新しいクエリを強制します。Tasks
これを行うと、例外が発生します。
Initializing [NHTest.Project#123]-役割のコレクションを遅延初期化できませんでした:NHTest.Project.Tasks、セッションまたはセッションが閉じられていません
これが発生している理由は、セッションスコープがないためです。ActiveRecordBase
内部メソッドは、セッションが存在しない場合などにセッションを作成すると思います。これで、これを使用して手動で作成できます。
public string GetData(int value)
{
Project p;
using (new SessionScope())
{
p = Project.Find(123M);
var count = p.Tasks.Count(); //Force count query
return p.GoldDate.ToString();
}
}
これはうまくいくでしょう。ただし、これはASP.NET Webサービスで完全に機能するため、すべてのコードでこれを行う必要はありません。
では、なぜASP.NETで機能するのでしょうか。
動作する理由は、ActiveRecordに。というhttpModuleが付属しているためCastle.ActiveRecord.Framework.SessionScopeWebModule
です。このモジュールは、すべてのHTTPリクエストの前に実行され、ActiveRecord内にデフォルトのセッションを作成します。ただし、このモジュールはWCFHTTP要求の前に呼び出されません。
ASP.NET互換モードはどうですか?
次を使用してASP.NET互換モードを有効にできます。
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" ... />
これにより、問題が修正されるだけでなく、WCF内のHTTP要求パイプラインへの他のアクセスも提供されます。これは1つの解決策になります。ただし、Visual StudioテストWebサーバーでは機能しますが、IIS7で互換モードを機能させることはできませんでした。さらに、最良の設計はWCFインフラストラクチャ内で完全に機能することだと思います。
私の質問:
Castle ActiveRecordは、WCFリクエスト内にセッションスコープを作成する機能を提供しますか?もしそうなら、これはどのように構成されていますか?