2013-07-31 35 views
4

我不断收到一个ConcurrencyException,它试图连续多次更新同一文档。消息是PUT attempted on document '<id>' using a non current etagRavenDB一直抛出ConcurrencyException

从我们的用户界面每次保存时,我们都会使用MassTransit发布一个事件。这个事件发送给用户队列,但是我把事件处理器置于离线状态(测试离线用户)。一旦事件处理程序联机,就会读取队列并按预期处理消息。

但是,由于第一次写入成功时同一个对象在队列中多次出现,下一个不会抛出此并发错误。

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

public static class RavenFactory 
{ 
    public static IDocumentStore CreateDocumentStore() 
    { 
     var store = new DocumentStore() { ConnectionStringName = "RavenDB" }; 

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

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

     // Initialize and return 
     store.Initialize(); 
     return store; 
    } 

    public static IDocumentSession GetSession(IDocumentStore store) 
    { 
     var session = store.OpenSession(); 
     session.Advanced.UseOptimisticConcurrency = false; 
     return session; 
    } 
} 

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

这里是实际的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; 
     } 
    } 
} 

我想暂时忽略任何concurrencyexception,直到我们能够与业务部门一起解决如何解决并发问题。

那么,为什么我会得到ConcurrencyException?无论文档是否已经更新过,我都希望保存发生。

+0

看看这个,它可以帮助你与并发问题http://johnculviner.com/achieving-named -lock-locker-functionality-in-c-4-0/ –

+1

现在已经接近一年了,你找到了解决方案吗? – simonlchilds

+0

有没有人想过这个?它似乎只在我的文档类型中的一个保存在处理程序中 - 所有其他文件似乎都很好保存! – iwayneo

回答

0

我不熟悉Unity的配置,但是你总是想要IDocumentStore的Singleton。下面,我从手工编码的辛格尔顿,但我敢肯定,统一将支持它:

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) 
    // 
} 
相关问题