2

有没有办法在 Raven.Server.exe.config 中将乐观并发设置为 true?或者,它可以以某种方式应用于数据库级别吗?在 RavenDB 的网站上,我看到一些提到设置 UseOptimisticConcurrency = true,但它看起来像是在代码中的会话级别:

public void Save<T>(T objectToSave)
{
    using (IDocumentSession session = Database.OpenSession())
    {
        session.Advanced.UseOptimisticConcurrency = true;  // This is the setting
        Guid eTag = (Guid)session.Advanced.GetEtagFor(objectToSave);
        session.Store(objectToSave, eTag);
        session.SaveChanges();
    }
}

我想知道该设置是否存在于服务器范围内的某个地方,因此不需要为代码中的每个会话指定它。

编辑:上面的代码产生以下错误。试图找出原因...

在此处输入图像描述

编辑2:好的,我正在取得进展。如果我检索对象,并在同一个会话中调用 GetEtagFor() ,那么我会得到一个有效的 eTag。所以我想我现在的主要问题是:在客户端 UI 中使用会话的正确方法是在应用程序启动时打开会话一次,然后在最后关闭它?并且... 存储 eTag 的正确方法是什么?按照上面的编码方式,在存储之前就检索了 eTag,我想这是错误的做法。我猜应该在第一次检索对象时检索 eTag。但是当我们最初得到一个对象列表时,我们是否必须遍历每个对象并在它们上调用 GetEtagFor() ?好像不太对...

4

2 回答 2

1

免责声明:这不是推荐的方法,实际上打开 IDocumentSession 的做法与客户端应用程序存在的时间一样长。有关替代解决方案,请参阅此处发布的答案:RavenDB Catch 22 - Optimistic Concurrency AND Seeing Changes from Other Clients

看起来我得到了乐观的并发工作,所以我想我会发布这个来帮助其他任何人。

首先,在 DataAccessLayerBase 中,我初始化 DocumentStore 和 IDocumentSession。只要客户端应用程序正在运行,它们就会打开并使用。

public abstract class DataAccessLayerBase
{
    protected static DocumentStore Database { get; private set; }

    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.Url = databaseUrl;
            documentStore.Initialize();
        }
        catch
        {
            documentStore.Dispose();
            throw;
        }

        return documentStore;
    }

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

        session.Advanced.UseOptimisticConcurrency = true;

        return session;
    }
}

接下来,在检索数据时,使用现有会话:

public class CustomVariableGroupData : DataAccessLayerBase, ICustomVariableGroupData
{
    public IEnumerable<CustomVariableGroup> GetAll()
    {
        return Session.Query<CustomVariableGroup>();
    }
}

最后,保存时,获取eTag并保存。

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

如果 UI 的另一个实例正在运行,并且更改了对象,则会发生并发异常。这就是我们想要的。

我刚刚又看了一遍这篇文章的标题,意识到这并没有回答如何在服务器配置文件中设置并发的问题。但是,由于现在可以在数据层中设置一次,这对我来说已经足够了。

于 2011-12-29T15:38:48.903 回答
1

Bob,不,UseOptimisticConcurrency 是您在打开会话时需要设置的东西。不,每个应用程序的单个会话是错误的做法。有关会话管理的更多详细信息,请参阅本文:

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

它谈到了 NHibernate,但会话管理部分也适用于 ravendb。

于 2011-12-30T09:08:36.367 回答