2017-05-08 86 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,在一個查詢中沒有機會實現這一點 –