2012-10-19 136 views
0

我想存儲使用NHibernate在數據庫中接收到的消息。但是,有可能會收到兩次相同的消息,在這種情況下,我不想將副本保存到數據庫中。我的第一個想法是做到以下幾點:在NHibernate中避免重複的條目

// in SaveRange(IEnumerable<Message> messages 
var alreadyStoredMessages = session.Query<Message>().Intersect(messages); 

var newMessages = messages.Except(alreadyStoredMessages); 

但是,似乎NHibernate不支持相交,所以這將導致一個異常。我知道我總是可以獲取所有消息,將它們轉換爲列表或數組,然後執行相交,但這不會非常有效。

Message類實現了IEquatable,它也覆蓋了GetHashCode()和Equals(object obj)。平等取決於幾個屬性(時間戳,幾個字符串等)。

回答

1

如果所有新郵件馬上來使用過濾器:

var alreadyStoredMessages = session.QueryOver<Message>() 
    .WhereRestrictionOn(m => m.timestamp).In(messages.Select(m => m.timeStamp)) 
    .AsEnumerable() 
    .Intersect(messages); 

var newMessages = messages.Except(alreadyStoredMessages).ToList(); 

假設重複消息後,之後彼此很近:保持最後n的緩衝區接收到的消息,並期待放進去。

var lastMessages = new Queue<Message>(100); 
while(true) 
{ 
    var message = GetNextMessage(); 
    if (!lastMessages.Contains(message)) 
    { 
     lastMessages.Enqueue(message); 
     session.Save(message); 
     if (lastMessages.Count >= 100); 
      lastMessages.Dequeue(); 
    } 
} 
+0

難道你不應該檢查一下,以確保你的隊列在離隊之前是「滿的」嗎? –

+0

過濾似乎是一個合理的解決方案。雖然我找到'In'方法有問題。 –

+0

我最終使用'IsInG(messages.Select(m => m.TimeStamp))。List()'而不是'In(messages.Select(m => m.timeStamp))。AsEnumerable()'工作得很好。 –