2017-05-08 84 views
0

我有这将有电子邮件,然后收件人表将有电子邮件Linq查询基于prioirty电子邮件

的收件人EmailMessage

标识

内容

电子邮件消息表

Priority

MessageRecipient

EmailMessageFk

RecipientEmailId

LastError

LastTriedAt

NextTryAt

每个消息可具有1至10个优先其中1是最低和10是最高的。我在C#中创建了一个函数,它将在一定的时间间隔后尝试重新发送所有未决的电子邮件消息。

我想编写能在数据库上运行,并且将根据以下标准

返回最符合条件的记录单LINQ查询

a)如果任何邮件收件人已经过去一直是试图在此之前发送12小时它应该是电子邮件

b)如果根据(a)标准没有找到收件人,那么它应该返回具有最高优先级的电子邮件消息,并且如果有多个具有最高优先级的电子邮件消息,则它应该返回具有最高优先级和最低LastTriedAt日期时间的消息。

请记住,我只想要一个LINQ查询,以满足所有这些要求

我用下面的查询

entities.EmailMessageRecipients.Where(
          p => p.NextAttemptAt <= DateTime.UtcNow) 
          .Select(p => p.Message) 
          .Distinct() 
          .OrderByDescending(p => p.Priority) 
          .ThenBy(p => p.Id) 
          .FirstOrDefault(); 

但这个查询有一个缺陷。如果很多高优先级的消息被卡在表中,那么它将不会尝试先前的低优先级消息。

+0

您不仅需要对NextAttemptAt进行过滤(Where),还要对NextAttemptAt进行排序(OrderBy)。 –

+0

但我不能过滤nextattemptat,因为我需要一个带有nextattemptat> 12小时的消息,如果没有这样的消息存在,那么会得到一个最高优先级的待处理消息 – yrahman

+0

“请记住,我只想要一个linq查询来满足所有这些要求。你想要什么和适合什么不一定是同一件事。 – jmcilhinney

回答

0

如果你想检索一个EmailMessage实体,那么你应该查询EmailMessages而不是EmailMessageRecipients。如果你想要收件人,那么你可以拨打Include。至于查询,如果我正确地解释你的条件那么你的第一个查询应该是这样的:

entities.EmailMessages.Where(em => em.EmailMessageRecipients.Any(emr => emr.NextAttemptAt <= DateTime.UtcNow.AddHours(-12)) 
         .OrderBy(em => em.LastTriedAt) 
         .FirstOrDefault() 

这将得到一个消息,至少有一个收件人,其NextAttemptAt为至少12小时前,如果有是一个。如果有多个匹配,则会得到最老的LastTriedAt值。如果返回null,则可以通过Priority进行查询。

+0

,但正如我在问题中所说的,如果没有找到nextattemptat> 12小时的消息,那么会得到一个具有最高优先级的待处理消息。这种情况不包括 – yrahman

+1

是的,正如我在答案中所说的,如果我提供的查询返回'null',那么您将通过'Priority'进行第二个查询。事实上,你认为一个单一的查询是一个好主意并不意味着它是。 – jmcilhinney

+0

@yrahman,在一个查询中没有机会实现这一点 –