RavenDB - 一个客户端无法看到来自不同客户端的更改

时间:2011-12-29 17:51:55

标签: ravendb

我正在运行我的应用程序的两个实例。在一个例子中,我保存了我的一个实体。当我检查RavenDB(http:// localhost:8080 / raven)时,我可以看到更改。然后,在我的其他客户端,我这样做(下面),但我没有看到来自其他应用程序的更改。为了获取数据库中的最新数据,我需要做什么?

public IEnumerable<CustomVariableGroup> GetAll()
{
    return Session
        .Query<CustomVariableGroup>()
        .Customize(x => x.WaitForNonStaleResults());
}

编辑:如果我尝试进行更改并获得并发异常,则上述代码有效。之后,当我调用refresh(调用上面的代码)时,它会起作用。

以下是执行保存的代码:

public void Save<T>(T objectToSave)
{
    Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
    Session.Store(objectToSave, eTag);
    Session.SaveChanges();
}

这是包含数据库和会话的类:

public abstract class DataAccessLayerBase
{
    /// <summary>
    /// Gets the database.
    /// </summary>
    protected static DocumentStore Database { get; private set; }

    /// <summary>
    /// Gets the session.
    /// </summary>
    protected static IDocumentSession Session { get; private set; }

    static DataAccessLayerBase()
    {
        if (Database != null) { return; }

        Database = GetDatabase();
        Session = GetSession();
    }        

    private static DocumentStore GetDatabase()
    {
        string databaseUrl = ConfigurationManager.AppSettings["databaseUrl"];            

        DocumentStore documentStore = new DocumentStore();

        try
        {
            //documentStore.ConnectionStringName = "RavenDb";  // See app.config for why this is commented.
            documentStore.Url = databaseUrl;
            documentStore.Initialize();
        }
        catch
        {
            documentStore.Dispose();
            throw;
        }

        return documentStore;
    }

    private static IDocumentSession GetSession()
    {
        IDocumentSession session = Database.OpenSession();

        session.Advanced.UseOptimisticConcurrency = true;

        return session;
    }
}

2 个答案:

答案 0 :(得分:4)

缺乏更详细的信息和一些代码,我只能猜测......

请确保在会话中致电.SaveChanges()。如果没有明确指定ITransaction,您的IDocumentSession将被隔离并在它打开和调用.SaveChanges之间进行事务处理。所有操作都成功或无成功。但是如果你不打电话,你之前的所有.Store电话都会丢失。

如果我错了,请发布有关您的代码的更多详细信息。


编辑:第二个答案(在补充信息之后):

您的问题与RavenDB在客户端缓存的方式有关。默认情况下,RavenDB会在DocumentSession中缓存每个GET请求。普通查询只是GET查询(不,它与您的索引在动态或手动定义的前期无关),因此它们将被缓存。您的应用程序中的解决方案是处置会话并打开一个新会话。

我建议您重新考虑会话生命周期。您的会话似乎过得太长,否则这种并发性不会成为问题。如果您正在构建网络应用程序,我建议您在请求开始和结束时打开和关闭会话。看看RaccoonBlog,看看它是否优雅地实现了。

答案 1 :(得分:2)

鲍勃, 看起来你在应用程序中只有一个会话,这是不对的。以下文章讨论了NHibernate,但会话管理部分也适用于RavenDB:

http://archive.msdn.microsoft.com/mag200912NHibernate

这段代码毫无意义:

Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
Session.Store(objectToSave, eTag);

它基本上是一个没有操作,但看起来很重要。您似乎正在尝试使用模型,您必须手动管理所有保存,不要这样做。您只需在创建新项目时自己管理事物,就是这样。

至于你遇到这个问题的原因,这里有一个例子:

var session = documentStore.OpenSession();
var post1 = session.Load<Post>(1);
// change the post by another client
post2 = session.Load<Post>(1); // will NOT go to the server, will give the same instance as post1

Assert.ReferenceEquals(post1,post2);

会话是短暂的,通常在单个表单/请求的范围内使用。