[英]Catch-all better alternative
I'm developing using Asp.net MVC 4, NHibernate and Session-per-request. 我正在使用Asp.net MVC 4,NHibernate和每次请求会话进行开发。
I have a service method which updates multiple databases so the work is wrapped in a TransactionScope. 我有一个更新多个数据库的服务方法,因此工作包装在TransactionScope中。 I have discovered that the NHibernate Session is not usable outside the TransactionScope due to it not being thread safe.
我发现NHibernate会话在TransactionScope之外不可用,因为它不是线程安全的。
The code is similar to this: 代码类似于以下内容:
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);
}
The database updates are critical to the success of the method. 数据库更新对于该方法的成功至关重要。 The email alerts are not.
电子邮件警报不是。 I don't want problems with the generation of the email alerts to prevent the database updates taking place.
我不希望在生成电子邮件警报时出现问题,以防止发生数据库更新。
My questions are: 我的问题是:
EDIT 编辑
Just to clarify my question: 只是为了澄清我的问题:
I know it would be better to generate and send the email after the TransactionScope. 我知道最好在TransactionScope之后生成并发送电子邮件。 However I am unable to do this as GenerateMailMessage() makes use of the NHibernate Session which is not safe to use outside of the TransactionScope block.
但是,我无法执行此操作,因为GenerateMailMessage()使用NHibernate会话,因此在TransactionScope块之外无法安全使用。
I guess what I was really asking is would it be defensible to change the catch statement above to a geniune catch-all (still with logging taking place) in order to provide as much protection to the critical UpdateOne() and UpdateTwo() calls as possible? 我想我真正要问的是将上面的catch语句更改为真正的catch-all(仍然进行日志记录),以便为关键的UpdateOne()和UpdateTwo()调用提供尽可能多的保护,这是合理的吗?可能?
Update 更新资料
My advice would be to try to prevent the exception from occurring. 我的建议是尝试防止异常的发生。 Failing that, a catch-all is likely the only option you have remaining.
否则,包罗万象可能是您剩下的唯一选择。 Logging all exceptions is going to be critical here.
记录所有异常在这里至关重要。
2nd question: I would completely remove the generation of email from the scope if it is liable to fail. 第二个问题:如果可能会失败,我将从作用域中完全删除电子邮件的生成。 Once the transaction rolls back, all items will be rolled back too.
交易回滚后,所有项目也会回滚。 Create and send all the emails on successful commit.
成功提交后创建并发送所有电子邮件。
public void ProcessItems() { var items = itemService.GetAll(); var mailMessages = new List<MailMessage>(); bool committed = false; using(var scope = new TransactionScope()) { foreach(var item in items) { itemService.UpdateOne(item); itemService.UpdateTwo(item); } scope.Complete() committed = true; } if (committed) { // Embed creation code and exception handling here. mailService.SendMail(mailMessages); } }
I'd suggest changing this around. 我建议改变这一点。 Instead of generating the email there and then... keep a list of the successfully processed items in a local List and then do all the mail sends at the end after you've committed.
而不是在那里生成电子邮件,然后...将成功处理的项目的列表保留在本地列表中,然后在提交后在末尾执行所有邮件发送。
public void ProcessItems()
{
var items = itemService.GetAll();
var successItems = new List<Item>();
var mailMessages = new List<MailMessage>();
using(var scope = new TransactionScope())
{
foreach(var item in items)
{
itemService.UpdateOne(item);
itemService.UpdateTwo(item);
successItems.Add(item);
// you still need try/catch handling for DB updates that fail... or maybe you want it all to fail.
}
scope.Complete()
}
mailMessages = successItems.Select(i => itemService.GenerateMailMessage).ToList();
//Do stuff with mail messages
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.