简体   繁体   English

如何发送电子邮件和回滚更改?

[英]How to send email and roll back changes?

I am creating a complaint registration form for user in asp.net MVC . 我正在为asp.net MVC中的用户创建投诉注册表。 The complaint is send to user email address and complaint is save into SQL server 2017 database. 投诉发送到用户的电子邮件地址,投诉保存到SQL Server 2017数据库中。 I need a suggestion. 我需要一个建议。 my question is, How do I handle email and database? 我的问题是,我如何处理电子邮件和数据库?

condition 1 - what if database fails to save data but email is sending. 条件1 - 如果数据库无法保存数据但电子邮件正在发送,该怎么办?
condition 2 - what if database save data to table but fails to send email. 条件2 - 如果数据库将数据保存到表但无法发送电子邮件,该怎么办?

How I did, 我是怎么做的

public void MyFunction()
{
    try {
       var db = DbContext();
       //some code
       //The number of state entries written to database
       int entities = db.SaveChanges();
       if (entities > 0)
       {
          SendEmail();//what fails to send email and complaint is created. 
       }
    }
    catch(Exception ex)
    {
        //exception is handle
    }
}

When db.SaveChanges() is done, it return how many tables are written to database. db.SaveChanges()完成后,它将返回写入数据库的表数。 From my homework, Second condition is most important. 从我的作业来看,第二个条件是最重要的。

The Result I want is, both process of creation and sending email is handle smoothly. 我想要的结果是,创建和发送电子邮件的过程都顺利处理。

Is I am on right path or not? 我是走在正确的道路上吗?

Any suggestion is appreciated. 任何建议表示赞赏。

What I would do in this case is have the emails saved to a table in the database, and implement a service that reads from that table and sends any unsent emails with a retry count for each entry. 在这种情况下,我要做的是将电子邮件保存到数据库中的表中,并实现从该表读取的服务,并发送任何未发送的电子邮件,并为每个条目重试计数。

That way you can retry sending the email at any time if it fails. 这样,如果失败,您可以随时重试发送电子邮件。

In real life you'll try to handle the email processes to another service (like sendgrind), so your application will store a request to send an email after the save is done. 在现实生活中,您将尝试将电子邮件进程处理到另一个服务(如sendgrind),因此您的应用程序将存储保存完成后发送电子邮件的请求。 This request will be handle by your service whenever it can; 只要有可能,您的服务就会处理此请求; Also, you won't need to be awaiting for the email to be sent in order to finish the user's request. 此外,您无需等待发送电子邮件以完成用户的请求。

Since you're doing a homework you can: 既然你正在做作业,你可以:

1- [Recommended] store that email in a table and have a small service reading from it, once it found a record, send an email and flagged as done . 1- [推荐]将该电子邮件存储在一个表中并从中获取一个小服务,一旦找到记录,发送电子邮件并标记为已done

2- [Not Fancy] Do it exactly as you are doing it. 2- [不喜欢]完全像你那样做。 Save the record and if success send an email. 保存记录,如果success发送电子邮件。

This is an interesting problem because it asks you to consider trade-offs, probabilities, and perfection vs. what's good enough. 这是一个有趣的问题,因为它要求你考虑权衡,概率和完美与足够好的东西。

Here's what's good enough: Update the database. 这就是足够好的:更新数据库。 If it succeeds, put a message in a queue (which could be another database table) that will result in an email being sent. 如果成功,则将消息放入队列(可能是另一个数据库表)中,这将导致发送电子邮件。

You could just send the email directly via SMTP right when the database gets updated, but there's a small chance that due to some odd transient condition the email wouldn't get sent. 您可以在数据库更新时直接通过SMTP发送电子邮件,但由于某些奇怪的瞬态条件,电子邮件将无法发送,因此很可能。 (That happens - maybe SMTP permissions get messed up and the email gets rejected.) Putting it in a queue with a separate process is a reasonable approach to make sure there's some resilience for your emails. (这种情况发生 - 也许SMTP权限搞砸了,电子邮件被拒绝了。)将它放在一个单独进程的队列中是一种合理的方法,可以确保您的电子邮件具有一定的弹性。

Why is that only "good enough?" 为什么那只“足够好”? Because nothing is bulletproof. 因为没有什么是防弹的。 It's still possible that your email might not get sent. 您的电子邮件仍有可能无法发送。 After all, we're concerned that the database update might fail. 毕竟,我们担心数据库更新可能会失败。 But if we're sending the email by inserting a record into another database that some other process monitors, doesn't that mean that could fail too? 但是,如果我们通过将记录插入另一个其他进程监视的数据库来发送电子邮件,那是不是意味着也可能失败? What will we do if the first database update succeeds but the one to send the email fails? 如果第一次数据库更新成功但发送电子邮件的人失败,我们会怎么做?

That's where we start making trade-offs. 这就是我们开始权衡利弊的地方。 It's possible that we might insert a complaint into the database but not send an email. 我们可能会将投诉插入数据库但不会发送电子邮件。 How likely is that, and if it happens, how bad is it? 这有多大可能,如果发生,有多糟糕? And whatever we might consider doing in response to that unlikely scenario, couldn't that fail too? 无论我们考虑采取什么措施来应对这种不太可能的情况,这也不会失败吗?

That's a rabbit hole. 那是一个兔子洞。 We can endlessly make our code more and more complex trying to account for less and less likely scenarios, but it's not worth it. 我们可以无休止地使我们的代码变得越来越复杂,试图考虑越来越不可能的场景,但它不值得。 Eventually bugs in our overly complex code will become the reasons why something doesn't work. 最终我们过于复杂的代码中的错误将成为某些东西无效的原因。

Instead of chasing after that, it makes more sense to realize that sometimes our code will fail because of things we can't control, and to know what that failure will look like. 而不是追逐它,更有意义的是,有时我们的代码会因为我们无法控制的事情而失败,并且知道失败会是什么样子。 Again, this is a question of what's good enough. 同样,这是一个什么是好的问题。

  • The initial database update fails. 初始数据库更新失败。 The user sees a message saying that their complaint was not saved. 用户会看到一条消息,说明他们的投诉未被保存。 Perhaps we can provide them another way to contact us. 也许我们可以为他们提供另一种联系方式。 The exception gets logged so that we can figure out what happened. 记录异常,以便我们弄清楚发生了什么。
  • The initial database update succeeds, then we send the email message to a queue. 初始数据库更新成功,然后我们将电子邮件消息发送到队列。 The email process fails. 电子邮件过程失败。 That should also get logged. 那也应该记录下来。 That might be more urgent, because if one email fails, perhaps lots of them are. 这可能更紧急,因为如果一封电子邮件失败,也许很多都是。 Hopefully that process provides some sort of alert if it's down so someone can fix the problem. 希望这个过程提供某种警报,如果它失败,所以有人可以解决问题。
  • The initial database update fails, and trying to send the email message to the queue fails. 初始数据库更新失败,尝试将电子邮件消息发送到队列失败。 We log that. 我们记录下来。 Again, hopefully there's something to let us know when stuff is failing, even if it's an email digest that someone gets. 再一次,希望有什么能让我们知道什么时候失败,即使这是某人得到的电子邮件摘要。

Even that can fail. 即使这样也会失败。 Our logging and our alerts can fail. 我们的日志记录和警报可能会失败。 We can replace them with something more resilient, like a better message queue. 我们可以用更具弹性的东西替换它们,比如更好的消息队列。 But we could drive ourselves insane trying to account for everything when it's impossible. 但是,当不可能时,我们可能会疯狂地试图解释所有事情。 All we can do is try to make our applications reliable and resilient. 我们所能做的就是尽量使我们的应用程序可靠和有弹性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM