【问题标题】:Prevent duplicate request by the email in .NET C#防止 .NET C# 中的电子邮件重复请求
【发布时间】:2018-07-11 15:56:05
【问题描述】:

我有一个处理POST 请求的API Action。我需要做的是防止重复处理同一封电子邮件,直到第一个过程结束。我看到了两种方法:

  1. 创建一个SQL Transaction 检查表,如果不存在则插入并返回falsetrue 否则。然后我们将在事务结束时从表中删除记录。我不喜欢它,因为如果,比方说,IIS 将在进程表中重新启动,就会有记录,我们需要想办法处理它。
  2. 制作ConcurrentDictionary,以便我们检查记录是否存在,然后拒绝重复请求。我使用 C# 编写的代码ConcurrentDictionary<string, string>:

if (!Singleton.TransactionEmails.TryAdd(email, email))
    // decline        
try
{
    // transaction logic here
}
catch(Exception ex)
{ 
    // catch logic here 
}
finally 
{ 
    string pendingEmail = string.Empty;    
    Singleton.TransactionEmails.TryRemove(email, out pendingEmail);
}

我有几个问题。您看到使用第一种方式的任何优势吗?我的代码看起来不像线程安全的。我需要使用lock 吗?在哪里需要?是否存在更有效的方法来防止重复事务而不锁定表或线程?

【问题讨论】:

  • 如果此 API 基于无状态请求/响应模型,则您的并发字典必须存储在请求之间存在的 ASP.NET 数据结构中。是这样吗? ConcurrentDictionary 本质上是线程安全的,这就是它的全部目的。我认为这里真正的问题是我们如何检测重复的电子邮件?(例如定义一个合适的相等比较器)和我们在哪里防止重复?(我会这样做这使用散列,以及框架的通用IDictionary 实现之一,在Add 上,简单地忽略随后添加散列冲突的尝试。
  • (仅仅为此而去 SQL Server 使用它的事务功能是不必要的,但是如果你的项目中有 SQL Server,那么记录你发送的邮件可能是值得的,所以你可以在同时实现您的邮件队列并在那里强制执行独特的邮件)。
  • @dlatikay 字典现在是单例的一部分,所以它在请求之间存在。我要问的是,假设两个请求线程尝试将相同的电子邮件添加到字典中并且“else”语句将被忽略时的情况。
  • 是的,竞争条件。我建议重新考虑该方法并仅使用TryAdd。如果元素已经存在,它将reliably return false
  • 更好的问题是为什么你的 api 调用要发送两次电子邮件,你在发送确认电子邮件是什么,再解释一下问题?

标签: c# asp.net multithreading


【解决方案1】:

首先对我来说似乎更好。因为每次 IIS 重新启动您的 Web 应用程序时,您的第二种方法中的字典将为空并接受重复项。你在第一种方法中提到的问题实际上属于第二种方法。

【讨论】:

  • 如果 IIS 重新启动则服务器无法处理请求
猜你喜欢
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
  • 2018-10-06
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
相关资源
最近更新 更多