2012-03-02 70 views
4

我們似乎已經證實,即使我們使用各種風格的「WaitForNonStaleResults」,RavenDB也會得到過時的結果。以下是全功能示例代碼(作爲獨立測試編寫,以便您可以複製/粘貼並按原樣運行)。RavenDB在刪除後返回陳舊結果

public class Cart 
{ 
    public virtual string Email { get; set; } 
} 

[Test] 
public void StandaloneTestForPostingOnStackOverflow() 
{ 
    var testDocument = new Cart { Email = "[email protected]" }; 
    var documentStore = new EmbeddableDocumentStore { RunInMemory = true }; 
    documentStore.Initialize(); 

    using (var session = documentStore.OpenSession()) 
    { 
    using (var transaction = new TransactionScope()) 
    { 
     session.Store(testDocument); 
     session.SaveChanges(); 
     transaction.Complete(); 
    } 

    using (var transaction = new TransactionScope()) 
    { 
     var documentToDelete = session 
     .Query<Cart>() 
     .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()) 
     .First(c => c.Email == testDocument.Email); 

     session.Delete(documentToDelete); 
     session.SaveChanges(); 
     transaction.Complete(); 
    } 

    RavenQueryStatistics statistics; 

    var actualCount = session 
     .Query<Cart>() 
     .Statistics(out statistics) 
     .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()) 
     .Count(c => c.Email == testDocument.Email); 

    Assert.IsFalse(statistics.IsStale); 
    Assert.AreEqual(0, actualCount); 
    } 
} 

我們試圖WaitForNonStaleResults的每一種滋味並沒有改變。等待非陳舊的結果似乎適用於更新,但不適用於刪除。

更新

,我嘗試過的一些事情:

  1. 使用每個動作單獨的會話。結果:沒有區別。同樣的成功和失敗。

  2. 在最終查詢之前放置Thread.Current.Sleep(500)。結果:成功。如果我睡了半秒鐘,計數就會回到零。

+0

testDocument聲明在哪裏?你確定documentToDelete不是null嗎?是否有可能需要關閉會話並用新會話進行查詢? – 2012-03-03 00:49:33

+0

testDocument在函數的第一行中初始化。至於新的會話,我不應該打開一個新的會話來獲取當前的查詢結果,但無論如何我已經嘗試過了。我將編輯帖子以包含其他信息觀察。 – 2012-03-03 12:16:47

+0

有趣的是,睡了半秒的作品。我能想到的唯一的另一件事是它是一個錯誤,或者你需要一個更好的索引。你使用的是什麼版本的RavenDB? – 2012-03-03 13:34:06

回答

0

該問題與刪除無關,與使用TransactionScope有關。這裏的問題是DTC事務以異步方式完成。

要解決這個問題,你需要做的就是調用:

session.Advanced.AllowNonAuthoritiveInformation = false; 

這將迫使RavenDB等待交易完成。

+1

非常感謝您關注此問題。我們非常感謝! 不幸的是,添加該行並沒有解決問題。時間之間仍然存在脫節。我們還添加了一個對'ExecuteAllPendingLazyOperations'的調用,希望這可能會有所幫助,但事實並非如此。我知道事務異步完成,但有什麼辦法強制請求等待未決事務完成嗎?我認爲這是'WaitForNonStale ...'功能的目的。 – 2012-03-05 14:34:51

+0

我在這裏也遇到了相反的問題,無論我做什麼,除非我初始化一個新的文檔存儲(完全不可接受的解決方案),否則陳舊的結果會返回。如果添加或刪除了某些內容,則會將其選中,但更新的任何內容只會返回陳舊的內容,就像更新從未發生過直到創建新的文檔存儲一樣。現在浪費了3天...現在... – nathanchere 2012-04-02 02:54:46

1

Re:我的評論上面的陳舊結果,AllowNonAuthoritiveInformation不起作用。需要在每個查詢中放置WaitForNonStaleResults(通常這個問題的「答案」),感覺就像一個巨大的「代碼味道」(儘管我通常討厭這個詞,這裏看起來完全合適)。

唯一能解決問題,到目前爲止,我發現是:

var store = new DocumentStore(); // do whatever 
store.DatabaseCommands.DisableAllCaching(); 

性能相應受到影響,但我認爲較慢的性能遠遠高於不可靠甚至完全不準確的結果少了罪。

1

這是一個老問題,但我最近遇到了這個問題。我能解決它通過改變由會話使用的DocumentStore公約,使其等待非陳舊的最後寫的:

session.DocumentStore.DefaultQueryingConsistency = ConsistencyOptions.AlwaysWaitForNonStaleResultsAsOfLastWrite; 

這使得它讓我沒有定製每查詢後運行。這就是說,我相信這隻適用於查詢。它通過測試發現它絕對不能用於補丁。

我也會小心這個,只能在需要的代碼周圍使用它,因爲它可能會導致性能問題。您可以使用以下方法將商店恢復爲其默認設置:

session.DocumentStore.DefaultQueryingConsistency = ConsistencyOptions.None;