简体   繁体   English

电子邮件已发送两次

[英]Emails being sent twice

We have an email queue table in the database. 我们在数据库中有一个电子邮件队列表。 It holds the subject, HTML body, to address, from address etc. 它包含主题,HTML正文,地址,从地址等。

In Global.asax every interval, the Process() function is called which despatches a set number of emails. Global.asax每个间隔中,都会调用Process()函数,该函数将分派一定数量的电子邮件。 Here's the code: 这是代码:

namespace v2.Email.Queue
{
    public class Settings
    {
        // How often process() should be called in seconds
        public const int PROCESS_BATCH_EVERY_SECONDS = 1;

        // How many emails should be sent in each batch.  Consult SES send rates.
        public const int EMAILS_PER_BATCH = 20;
    }

    public class Functions
    {
        private static Object QueueLock = new Object();

        /// <summary>
        /// Process the queue
        /// </summary>
        public static void Process()
        {
            lock (QueueLock)
            {
                using (var db = new MainContext())
                {
                    var emails = db.v2EmailQueues.OrderBy(c => c.ID).Take(Settings.EMAILS_PER_BATCH);
                    foreach (var email in emails)
                    {
                        var sent = Amazon.Emailer.SendEmail(email.FromAddress, email.ToAddress, email.Subject,
                                                                email.HTML);
                        if (sent)
                            db.ExecuteCommand("DELETE FROM v2EmailQueue WHERE ID = " + email.ID);
                        else
                            db.ExecuteCommand("UPDATE v2EmailQueue Set FailCount = FailCount + 1 WHERE ID = " + email.ID);
                    }
                }
            }
        }

The problem is that every now and then it's sending one email twice. 问题在于,它不时地发送两次电子邮件。

Is there any reason from the code above that could explain this double sending? 上面的代码中是否有任何原因可以解释这种双重发送?

Small test as per Matthews suggestion 根据Matthews的建议进行小测试

const int testRecordID = 8296;
using (var db = new MainContext())
{
    context.Response.Write(db.tblLogs.SingleOrDefault(c => c.ID == testRecordID) == null ? "Not Found\n\n" : "Found\n\n");
    db.ExecuteCommand("DELETE FROM tblLogs WHERE ID = " + testRecordID);
    context.Response.Write(db.tblLogs.SingleOrDefault(c => c.ID == testRecordID) == null ? "Not Found\n\n" : "Found\n\n");
}
using (var db = new MainContext())
{
    context.Response.Write(db.tblLogs.SingleOrDefault(c => c.ID == testRecordID) == null ? "Not Found\n\n" : "Found\n\n");
}

Returns when there is a record: 有记录时返回:

Found 发现

Found 发现

Not Found 未找到

If I use this method to clear the context cache after the delete sql query it returns: 如果在删除sql查询后使用此方法清除上下文缓存 ,它将返回:

Found 发现

Not Found 未找到

Not Found 未找到

However still not sure if it's the root cause of the problem though. 但是,仍然不确定这是否是问题的根本原因。 I would of thought the locking would definitely stop double sends. 我认为锁定肯定会停止两次发送。

The issue that your having is due to the way Entity Framework does its internal cache. 您遇到的问题是由于实体框架执行其内部缓存的方式引起的。

In order to increase performance, Entity Framework will cache entities to avoid doing a database hit. 为了提高性能,实体框架将缓存实体,以避免数据库命中。

Entity Framework will update its cache when you are doing certain operations on DbSet . DbSet上执行某些操作时,实体框架将更新其缓存。

Entity Framework does not understand that your "DELETE FROM ... WHERE ..." statement should invalidate the cache because EF is not an SQL engine (and does not know the meaning of the statement you wrote). 实体框架不理解您的"DELETE FROM ... WHERE ..."语句应该使缓存无效,因为EF不是SQL引擎(并且不知道您编写的语句的含义)。 Thus, to allow EF to do its job, you should use the DbSet methods that EF understands. 因此,要允许EF发挥作用,您应该使用EF可以理解的DbSet方法。

for (var email in db.v2EmailQueues.OrderBy(c => c.ID).Take(Settings.EMAILS_PER_BATCH))
{
    // whatever your amazon code was...

    if (sent)
    {
        db.v2EmailQueues.Remove(email);
    }
    else
    {
        email.FailCount++;
    }
}

// this will update the database, and its internal cache.
db.SaveChanges(); 

On a side note, you should leverage the ORM as much as possible, not only will it save time debugging, it makes your code easier to understand. 附带说明,您应该尽可能地利用ORM,不仅可以节省调试时间,还可以使代码更易于理解。

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

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