我之前提出过这个问题,但我仍然在努力寻找一个可以让我理解的例子(请不要只是告诉我在没有至少一些指示的情况下查看S#arp架构项目)。< / p>
到目前为止,我已经在我的网络项目中实现了近乎持久的无知。我的存储库类(在我的数据项目中)在构造函数中使用了一个ISession:
public class ProductRepository : IProductRepository
{
private ISession _session;
public ProductRepository(ISession session) {
_session = session;
}
在我的global.asax中,我公开当前会话,并在beginrequest和endrequest上创建和处理会话(这是我对NHibernate的依赖):
public static ISessionFactory SessionFactory = CreateSessionFactory();
private static ISessionFactory CreateSessionFactory() {
return new Configuration()
.Configure()
.BuildSessionFactory();
}
protected MvcApplication() {
BeginRequest += delegate {
CurrentSessionContext.Bind(SessionFactory.OpenSession());
};
EndRequest += delegate {
CurrentSessionContext.Unbind(SessionFactory).Dispose();
};
}
最后我的StructureMap注册表:
public AppRegistry() {
For<ISession>().TheDefault
.Is.ConstructedBy(x => MvcApplication.SessionFactory.GetCurrentSession());
For<IProductRepository>().Use<ProductRepository>();
}
似乎我需要我自己的ISession和ISessionFactory的通用实现,我可以在我的web项目中使用它并注入我的存储库?
所以只是为了澄清 - 我在我的存储库层使用NHibernate并希望使用session-per-(http)请求。因此,我正在向我的存储库构造函数中注入一个ISession(使用structuremap)。目前,为了在每个请求中创建和处理会话,我必须从我的web项目中引用NHibernate。这是我想删除的依赖项。
谢谢, 本
答案 0 :(得分:3)
为什么不创建IHttpModule并在那里执行创建和处理(可能在Begin_Request和End_Request事件中),而是将IHttpModule放在具有NHibernate依赖项的项目中。例如
namespace MyWebApp.Repository.NHibernateImpl
{
public class NHibernateModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Context_BeginRequest);
context.EndRequest += new EventHandler(Context_EndRequest);
}
private void Context_BeginRequest(object sender, EventArgs e)
{
// Create your ISession
}
private void Context_EndRequest(object sender, EventArgs e)
{
// Close/Dispose your ISession
}
public void Dispose()
{
// Perhaps dispose of your ISessionFactory here
}
}
}
也许有更好的方法,我也有兴趣知道这一点,所以有其他建议吗?
答案 1 :(得分:2)
在我看来,你应该接受ISession并直接使用它。许多会话请求实现的问题是它们会延迟提交数据库更改,直到HTTP请求结束。如果事务失败,那么您在此处所能做的就是将用户引导到一般错误页面。在页面上管理事务要好得多,这样您就可以更有效地捕获和处理错误。如果采用这种方式,则需要访问ISession或包装器来控制事务。
此外,在某些时候,您的应用程序可能需要使用ISession公开的属性或方法,尤其是Merge和Load。
答案 2 :(得分:0)
感谢大家的帮助。更多的研究使我进入了NHibernate Burrow项目。
从项目常见问题解答(http://nhforge.org/wikis/burrow/faq.aspx):
Burrow是一个轻量级的中间件,用于支持使用NHibernate的.Net应用程序(在本文中也可称为NH)作为ORM框架。使用带有NHibernate的Asp.net可能是一个挑战,因为NHibernate是一个有状态的环境,而Asp.net是一个无状态框架。 Burrow可以通过提供先进的智能会话/事务管理和其他便利来帮助解决这一冲突。
我不得不跳过一些箍,让它在我的项目中运作。由于当前版本使用旧版本的NHibernate,我必须从主干下载latest source,在VS中打开,添加对最新版NHibernate的引用并重新编译(幸运的是没有错误)。
我以多种方式测试了NHibernate Burrow。
1)继续将ISession注入我的存储库
为此,我必须将对NHibernate,NHibernate.Burrow和NHibernate.Burrow.WebUtil的引用添加到我的MVC项目中。
在web.config中我必须设置Burrow(参见http://nhforge.org/wikis/burrow/get-started.aspx),然后在我的StructureMap注册表中添加以下内容:
For<ISession>()
.TheDefault.Is
.ConstructedBy(x => new NHibernate.Burrow.BurrowFramework().GetSession());
我喜欢这种方法,因为这意味着我的存储库(或控制器)不与Burrow耦合。我不太喜欢我必须在我的web项目中引用这三个程序集的事实,但至少我丢失了管理会话的代码 - 这全部由Burrow处理。
2)第二种方法是在我的存储库构造函数中设置ISession,如下所示:
public ProductRepository() :
this(new BurrowFramework().GetSession()) { }
public ProductRepository(ISession session) {
_session = session;
}
我仍然可以覆盖ISession,使我的存储库可测试。然后,我直接依赖于Burrow,但也许这不是一件坏事?
从好的方面来说,我需要从我的web项目中引用的唯一程序集是NHibernate.Burrow.WebUtils。
有兴趣看看两个人中哪一个会去,为什么。