2012-03-02 48 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;