这可能是一个小生境问题,但也许有人可以帮助我。我将我的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/) 。 –