2012-05-10 148 views
5

对我的MVC应用程序有一个动作,它有一个id并返回一个人的名字。NHibernate - 最佳实践选择

这样做的最佳做法是什么?我遵循NHProf技巧,但代码听起来有点奇怪或对我来说有点意思。

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
{ 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     return session.Query<Person>().Where(x => x.Id == id).Select(x => x.Name).SingleOrDefault(); 
     tran.Rollback(); 
    } 
} 
+0

我不明白为什么它提出一个交易... –

+0

你想知道什么? –

+1

我不会使用'OpenStatelessSession',无状态会话用于批量方案并忽略L1缓存。我只需简单地调用'.Load (1)'或'.Get (1)'表示不仅仅是一个linq查询。 – Andreas

回答

4

的NHProf警报页解释了它相当不错,我认为 -

http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions

基本上它说,如果你不自己管理的事务,数据库将创建一个“隐性交易”和经销商 - 每声明,包括查询,提交。误解是交易仅适用于插入/更新操作。

在上面的示例中,它不是什么大问题,因为您的事务只是执行单个语句。如果您的方法正在运行多个语句,但将它们包装在事务中将是一种很好的做法。

+0

好的,但对于简单的方法,我应该遵循NHProf并创建一个事务吗? – Zote

+1

答案只是部分正确,你应该在事务中__always__扭曲你的数据库查询,并且即使你执行一条语句,事实上也是一个问题。隐式事务很贵! NH不会在没有事务的情况下使用L2高速缓存。 – Andreas

-1

以下是我会怎么处理这个选择:

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     try 
     { 
      string personName = session.Query<Person>() 
      .Where(x => x.Id == id) 
      .Single(x => x.Name); 

      tran.Commit(); 
      return personName; 
     } 
     catch(Exception ex) 
     { 
      // handle exception 
      tran.Rollback(); 
     } 
    } 

这SO答案给出了很好的建议,以处理事务提交:

NHibernate - Is ITransaction.Commit really necessary?

至于你的LINQ这是一个关于如何不使用扩展方法样式语法来进行查询的有趣文章:

http://compiledexperience.com/blog/posts/how-not-to-use-linq

+0

-1捕捉一切,做冗余工作(使用和尝试捕捉)。 – Andreas

+0

@Andreas据我所知使用无法处理抛出的异常,并选择使用冗余尝试或手动处置。此外,在这种情况下你将如何实现错误处理,因为有很多层可能会引发错误(NHibernate,ADO.NET,LINQ)。 –

+2

http://stackoverflow.com/questions/6418992/is-it-a-better-practice-to-explicitly-call-transaction-rollback-or-let-an-except和例外http://stackoverflow.com/questions/426346/is-this-a-bad-practice-to-catch-a-non-specific-exception-such-as-system-exceptio http://stackoverflow.com/questions/114658/catching-base- exception-class-in-net http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx并且不要告诉我你可以正确处理stackoverflows,内存不足用你的'tran.Rollback();'加上。 – Andreas

0

不会通过一个HTTP请求创建多个会话,理想情况下,您需要在请求范围内打开一个会话和一个相应的事务,并在您的所有操作中使用此会话。

这里是一个博客帖子解释如何实现它:http://hackingon.net/post/NHibernate-Session-Per-Request-with-ASPNET-MVC.aspx

我会建议使用IoC容器,并开发出能为您和范围创建会话此类请求范围的一类。

有很多资源在网络上解决这个问题..谷歌它..

+0

虽然每个请求的一个会话是合理的建议,但这不是一条硬性规则,每个请求只有一个事务是不好的建议,很简单。 – Spivonious