RavenDB Catch 22-乐观并发性,并看到其他客户端的变化 [英] RavenDB Catch 22 - Optimistic Concurrency AND Seeing Changes from Other Clients

查看:82
本文介绍了RavenDB Catch 22-乐观并发性,并看到其他客户端的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用RavenDB,在应用程序启动时创建一个IDocumentSession(并且直到应用程序关闭后才关闭它),这使我可以使用开放式并发:

With RavenDB, creating an IDocumentSession upon app start-up (and never closing it until the app is closed), allows me to use optimistic concurrency by doing this:

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 user has changed that object, then the save will correctly fail.

但是,当在应用程序的整个生命周期中使用一个会话时,我无法做的是看到该应用程序的其他实例(例如,乔,相隔五个小隔间)对文档所做的更改.当我这样做时,我看不到乔的变化:

But what I can't do, when using one session for the lifetime of an app, is seeing changes, made by other instances of the app (say, Joe, five cubicles away), to documents. When I do this, I don't see Joe's changes:

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

注意:我也尝试过这样做,但是它也没有显示Joe的更改:

Note: I've also tried this, but it didn't display Joe's changes either:

return Session.Query<CustomVariableGroup>().Customize(x => x.WaitForNonStaleResults());

现在,如果我走另一条路,并且在访问数据库的每个方法中都创建一个IDocumentSession,那么我遇到了相反的问题.因为我有一个新的会话,所以我可以看到Joe的更改. Buuuuuuut ...然后我失去了乐观的并发性.当我在保存之前创建新会话时,此行会生成一个空的GUID,因此会失败:

Now, if I go the other way, and create an IDocumentSession within every method that accesses the database, then I have the opposite problem. Because I have a new session, I can see Joe's changes. Buuuuuuut... then I lose optimistic concurrency. When I create a new session before saving, this line produces an empty GUID, and therefore fails:

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

我想念什么?如果不应该在每种方法中都不在应用程序级别中创建会话,那么正确的范围是什么?在执行Session.Query()时,如何获得乐观并发的好处?

What am I missing? If a Session shouldn't be created within each method, nor at the app level, then what is the correct scope? How can I get the benefits of optimistic concurrency and the ability to see others' changes when doing a Session.Query()?

推荐答案

免责声明:我知道这不是长期的方法,因此在这里不会被接受.但是,我只需要现在就可以工作,以后就可以重构了.我也知道有些人会对这种方法感到厌恶,哈哈,但是就这样吧.它似乎正在工作.我在每个查询(新会话)中都获得了新数据,并且乐观并发也可以正常工作.

Disclaimer: I know this can't be the long-term approach, and therefore won't be an accepted answer here. However, I simply need to get something working now, and I can refactor later. I also know some folks will be disgusted with this approach, lol, but so be it. It seems to be working. I get new data with every query (new session), and I get optimistic concurrency working as well.

最重要的是,我每种数据访问方法都返回到一个会话.每当数据访问方法执行某种类型的获取/加载/查询时,我都会将eTag存储在静态字典中:

The bottom line is that I went back to one session per data access method. And whenever a data access method does some type of get/load/query, I store the eTags in a static dictionary:

public IEnumerable<CustomVariableGroup> GetAll()
{
    using (IDocumentSession session = Database.OpenSession())
    {
        IEnumerable<CustomVariableGroup> groups = session.Query<CustomVariableGroup>();
        CacheEtags(groups, session);
        return groups;
    }
}

然后,当我保存数据时,我从缓存中获取了eTag.如果另一个实例修改了数据,这将导致并发异常.

Then, when I'm saving data, I grab the eTag from the cache. This causes a concurrency exception if another instance has modified the data, which is what I want.

public void Save(EntityBase objectToSave)
{
    if (objectToSave == null) { throw new ArgumentNullException("objectToSave"); }

    Guid eTag = Guid.Empty;

    if (objectToSave.Id != null)
    {
        eTag = RetrieveEtagFromCache(objectToSave);
    }

    using (IDocumentSession session = Database.OpenSession())
    {
        session.Advanced.UseOptimisticConcurrency = true;
        session.Store(objectToSave, eTag);
        session.SaveChanges();
        CacheEtag(objectToSave, session);  // We have a new eTag after saving.
    }
}

从长远来看,我绝对想以正确的方式来做,但是我不知道那是什么方式.

I absolutely want to do this the right way in the long run, but I don't know what that way is yet.

在我找到更好的方法之前,我将把它作为公认的答案.

I'm going to make this the accepted answer until I find a better way.

这篇关于RavenDB Catch 22-乐观并发性,并看到其他客户端的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆