Domanda

Is there a way to set optimistic concurrency to true in Raven.Server.exe.config? Or, can it somehow be applied at the database level? On RavenDB's site, I see a couple of mentions of setting UseOptimisticConcurrency = true, but it looks like it's at the session level within the code:

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();
    }
}

I would like to know if it that setting exists somewhere server-wide, so it doesn't need to be specified for each session in code.

Edit: The code above produces the following error. Trying to find out why...

enter image description here

Edit 2: Ok, I'm making progress. If I retrieve the object, and call GetEtagFor() all within the same session, then I get a valid eTag. So I guess my main question now is: Is the correct way to use a session, within a client UI, to open the session once when the app starts, and then close it at the end? And... What's the correct way to store the eTag? The way it's coded above, the eTag is retrieved right before storing, which I would imagine is the wrong way to do it. I'm guessing the eTag should be retrieved when the object is first retrieved. But when we originally get a list of objects, should we have to loop through each and call GetEtagFor() on them? Doesn't seem right...

È stato utile?

Soluzione

Bob, No, UseOptimisticConcurrency is something that you need to setup when you open the session. And NO, a single session per the entire application is the wrong thing to do. See this article for more details on session management:

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

It talks about NHibernate, but the session management parts applies to ravendb as well.

Altri suggerimenti

Disclaimer: This is not a recommended approach, and in fact bad practice to open an IDocumentSession that will live as long as the client app lives. For an alternate solution, see the answer posted here: RavenDB Catch 22 - Optimistic Concurrency AND Seeing Changes from Other Clients.

It looks like I got optimistic concurrency working, so I thought I'd post this to help any else.

First, in DataAccessLayerBase, I initialize the DocumentStore and IDocumentSession. These will be open and used as long as the client app is running.

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;
    }
}

Next, when retrieving the data, use the existing session:

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

Finally, when saving, get the eTag and save.

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

If another instance of the UI is running, and changes the object, a concurrency exception will occur. And that's what we wanted.

I just looked at the title of this post again, and realized this doesn't answer the question of how to set concurrency in the server config file. However, since it can now be set once in the data layer, that's good enough for me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top