Concurrency RavenDB不断抛出并发异常

Concurrency RavenDB不断抛出并发异常,concurrency,ravendb,optimistic-concurrency,Concurrency,Ravendb,Optimistic Concurrency,我不断收到一个并发异常,试图连续多次更新同一文档尝试使用非当前etag对文档“”执行PUT操作是消息 每次从UI保存时,我们都会使用MassTransit发布一个事件。此事件被发送到subscriberqueues,但我将EventHandler置于脱机状态(测试脱机订阅者)。一旦eventhandler联机,将读取队列并按预期处理消息 但是,由于同一对象多次出现在队列中,因此第一次写入成功,下一次写入失败,并引发此concurrencyexception 我使用工厂类在所有应用程序中具有一致的

我不断收到一个并发异常,试图连续多次更新同一文档<代码>尝试使用非当前etag对文档“”执行PUT操作是消息

每次从UI保存时,我们都会使用MassTransit发布一个事件。此事件被发送到subscriberqueues,但我将EventHandler置于脱机状态(测试脱机订阅者)。一旦eventhandler联机,将读取队列并按预期处理消息

但是,由于同一对象多次出现在队列中,因此第一次写入成功,下一次写入失败,并引发此concurrencyexception

我使用工厂类在所有应用程序中具有一致的IDocumentStore和IDocumentSession。我在GetSession()方法中专门设置了
UseOptimisticConcurrency=false

公共静态类RavenFactory
{
公共静态IDocumentStore CreateDocumentStore()
{
var store=new DocumentStore(){ConnectionStringName=“RavenDB”};
//设定惯例
store.Conventions.RegisterIdConvention((db,cmd,e)=>e.MyProperty.ToString());
RegisterAsyncIdConvention((db,cmd,e)=>newcompletedtask(e.MyProperty.ToString());
//注册听众
商店
.RegisterListener(新建TakeNewestConflictResolutionListener())
.RegisterListener(新文档转换Listener())
.RegisterListener(新的DocumentStoreListener());
//初始化并返回
store.Initialize();
退货店;
}
公共静态IDocumentSession GetSession(IDocumentStore存储)
{
var session=store.OpenSession();
session.Advanced.UseOptimisticConcurrency=false;
返回会议;
}
}
eventhandler如下所示。IDocumentSession使用依赖项注入进行注入。 下面是获取IDocumentSession实例的逻辑

private static void InitializeRavenDB(IUnityContainer container)
{
    container.RegisterInstance<IDocumentStore>(RavenFactory.CreateDocumentStore(), new ContainerControlledLifetimeManager());
    container.RegisterType<IDocumentSession, DocumentSession>(new PerResolveLifetimeManager(), new InjectionFactory(c => RavenFactory.GetSession(c.Resolve<IDocumentStore>())));
}
private静态无效初始值设定项eravendb(IUnityContainer容器)
{
container.RegisterInstance(RavenFactory.CreateDocumentStore(),新的ContainerControlledLifetimeManager());
RegisterType(new PerResolveLifetimeManager(),new InjectionFactory(c=>RavenFactory.GetSession(c.Resolve()));
}
这里是实际的EventHandler,它具有ConcurrencyException

public class MyEventHandler:Consumes<MyEvent>.All, IConsumer
{
    private readonly IDocumentSession _session;

    public MyEventHandler(IDocumentSession session)
    {
        if (session == null) throw new ArgumentNullException("session");

        _session = session;
    }

    public void Consume(MyEvent message)
    {
        Console.WriteLine("MyEvent received: Id = '{0}'", message.MyProperty);

        try
        {
        _session.Store(message);
    _session.SaveChanges();
        }
        catch (Exception ex)
        {
            var exc = ex.ToString();
            // Deal with concurrent writes ...
            throw;
        }
    }
}
公共类MyEventHandler:Consumes.All,IConsumer
{
私有只读IDocumentSession\u会话;
公共MyEventHandler(IDocumentSession)
{
如果(session==null)抛出新的ArgumentNullException(“session”);
_会话=会话;
}
公共void消费(MyEvent消息)
{
WriteLine(“MyEvent接收到:Id='{0}',message.MyProperty);
尝试
{
_会话存储(消息);
_session.SaveChanges();
}
捕获(例外情况除外)
{
var exc=ex.ToString();
//处理并发写入。。。
投掷;
}
}
}
我想暂时忽略任何并发例外,直到我们能够与业务部门就如何解决并发性进行协调


那么,你知道我为什么会得到ConcurrencyException吗?我希望无论文档之前是否已更新,都能进行保存。

我不熟悉Unity的配置,但您总是希望使用
IDocumentStore的Singleton。下面,我已经手动编写了Singleton,但我相信Unity会支持它:

public static class RavenFactory
{
    private static IDocumentStore store;
    private static object syncLock = new object();

    public static IDocumentStore CreateDocumentStore()
    {
        if(RavenFactory.store != null) 
           return RavenFactory.store;

        lock(syncLock)
        {
           if(RavenFactory.store != null) 
              return RavenFactory.store;

           var localStore = new DocumentStore() { ConnectionStringName = "RavenDB" };

           // Setting Conventions
           localStore .Conventions.RegisterIdConvention<MyType>((db, cmd, e) => e.MyProperty.ToString());
           localStore .Conventions.RegisterAsyncIdConvention<MyType>((db, cmd, e) => new CompletedTask<string>(e.MyProperty.ToString()));

           // Registering Listeners
           localStore 
              .RegisterListener(new TakeNewestConflictResolutionListener())
              .RegisterListener(new DocumentConversionListener())
              .RegisterListener(new DocumentStoreListener());

           // Initialize and return
           localStore.Initialize();
           RavenFactory.store = localStore;
           return RavenFactory.store;
       }
    }

    //      As before
    //     public static IDocumentSession GetSession(IDocumentStore store)
    //
}
公共静态类RavenFactory
{
私人静态IDocumentStore;
私有静态对象syncLock=新对象();
公共静态IDocumentStore CreateDocumentStore()
{
if(RavenFactory.store!=null)
返回RavenFactory.store;
锁定(同步锁定)
{
if(RavenFactory.store!=null)
返回RavenFactory.store;
var localStore=new DocumentStore(){ConnectionStringName=“RavenDB”};
//设定惯例
localStore.Conventions.RegisterIdConvention((db,cmd,e)=>e.MyProperty.ToString());
RegisterAsyncIdConvention((db,cmd,e)=>newcompletedtask(e.MyProperty.ToString());
//注册听众
本地存储
.RegisterListener(新建TakeNewestConflictResolutionListener())
.RegisterListener(新文档转换Listener())
.RegisterListener(新的DocumentStoreListener());
//初始化并返回
localStore.Initialize();
RavenFactory.store=localStore;
返回RavenFactory.store;
}
}
//一如既往
//公共静态IDocumentSession GetSession(IDocumentStore存储)
//
}

看看这个,它可能会帮助您解决近一年来出现的并发问题,您找到解决方案了吗?有人发现了吗?似乎只有一种文档类型保存在处理程序中,其他所有文档类型都保存得很好@GuillaumeSchuermans:这个Unity容器是否为整个应用程序返回一个单例?
public static class RavenFactory
{
    private static IDocumentStore store;
    private static object syncLock = new object();

    public static IDocumentStore CreateDocumentStore()
    {
        if(RavenFactory.store != null) 
           return RavenFactory.store;

        lock(syncLock)
        {
           if(RavenFactory.store != null) 
              return RavenFactory.store;

           var localStore = new DocumentStore() { ConnectionStringName = "RavenDB" };

           // Setting Conventions
           localStore .Conventions.RegisterIdConvention<MyType>((db, cmd, e) => e.MyProperty.ToString());
           localStore .Conventions.RegisterAsyncIdConvention<MyType>((db, cmd, e) => new CompletedTask<string>(e.MyProperty.ToString()));

           // Registering Listeners
           localStore 
              .RegisterListener(new TakeNewestConflictResolutionListener())
              .RegisterListener(new DocumentConversionListener())
              .RegisterListener(new DocumentStoreListener());

           // Initialize and return
           localStore.Initialize();
           RavenFactory.store = localStore;
           return RavenFactory.store;
       }
    }

    //      As before
    //     public static IDocumentSession GetSession(IDocumentStore store)
    //
}