我正在使用 Asp.net MVC 4、NHibernate 和 Session-per-request 进行开发。
我有一个更新多个数据库的服务方法,因此工作包含在 TransactionScope 中。我发现 NHibernate Session 在 TransactionScope 之外不可用,因为它不是线程安全的。
代码与此类似:
public void ProcessItems()
{
var items = itemService.GetAll();
var mailMessages = new List<MailMessage>();
using(var scope = new TransactionScope())
{
foreach(var item in items)
{
itemService.UpdateOne(item);
itemService.UpdateTwo(item);
try
{
mailMessages.Add(itemService.GenerateMailMessage(item));
}
catch(Exception ex)
{
// we don't want exceptions caused be generating email to prevent DB work
if (ex is InvalidOperationException
|| ex is NullReferenceException
|| ex is FormatException
|| ex is ArgumentException
|| ex is ItemNotFoundException)
{
LogError(String.Format("Unable to generate email alert for item.Id:{0} - {1}", item.Id, ex.Message), log);
}
else
{
// For exception types we don't know we can ignore rethrow
throw;
}
}
scope.Complete()
}
mailService.SendMail(mailMessages);
}
数据库更新对于该方法的成功至关重要。电子邮件警报不是。我不希望在生成电子邮件警报时出现问题,以防止发生数据库更新。
我的问题是:
- 考虑到这些限制,这看起来是一种合理的方法吗?
- 我担心在生成电子邮件时可能会抛出我尚未处理的异常。这将导致整个 TransactionScope 被回滚。感觉就像我希望在该 try 代码块中发生的任何异常都被忽略。但是,我很欣赏一个包罗万象的做法是一个禁忌,因此欢迎任何其他使这个更强大的建议。
编辑
只是为了澄清我的问题:
我知道在 TransactionScope 之后生成和发送电子邮件会更好。但是我无法做到这一点,因为 GenerateMailMessage() 使用了 NHibernate Session,在 TransactionScope 块之外使用它是不安全的。
我想我真正要问的是,为了为关键的 UpdateOne() 和 UpdateTwo() 调用提供与可能的?