這可能是一個小生境問題,但也許有人可以幫助我。我將我的Web服務從ASMX移植到WCF,但是我完全基於Castle ActiveRecord構建。爲了確保我的配置中沒有某種奇怪的問題,我使用NuGet中所有最新的Castle和NHibernate庫從零開始構建了一個獨立的repro。Castle ActiveRecord沒有初始化WCF會話
我做的第一件事是在Application_Start
中初始化ActiveRecord。通常我會使用一個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));
}
通知我還使用了HybridWebThreadScopeInfo
實現,因爲HttpContext.Current
將在WCF空。
接下來,我實現了我的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
屬性是懶惰的。當我這樣做,我得到異常:
初始化[NHTest.Project#123] -failed懶洋洋地初始化角色的集合: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帶有一個叫做Castle.ActiveRecord.Framework.SessionScopeWebModule
的httpModule。此模塊在每個HTTP請求之前運行,並在ActiveRecord中創建一個默認會話。但是,在WCF HTTP請求之前調用此模塊是而不是。
怎麼樣ASP.NET兼容模式?
可以使用啓用ASP.NET兼容模式:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" ... />
這也將解決這個問題,並提供其他訪問中WCF的HTTP請求管道。這將是一個解決方案。但是,儘管它在Visual Studio測試Web服務器上工作,但我始終無法獲得適用於IIS7的兼容模式。另外,我覺得最好的設計是在WCF基礎架構內完全工作。
我的問題:
確實城堡的ActiveRecord提供了WCF請求中創建會話作用域的能力嗎?如果是這樣,這是如何配置的?
如果你想要*噸*的細節,還寫了一個[博客文章](http://blog.kitchenpc.com/2012/12/06/wcf-and-activerecord-lets-be-friends/) 。 –