我不断收到 ConcurrencyException 尝试连续多次更新同一个文档。PUT attempted on document '<id>' using a non current etag
是消息。
在我们的 UI 中每次保存时,我们都会使用 MassTransit 发布一个事件。此事件被发送到订阅者队列,但我将事件处理程序置于离线状态(测试离线订阅者)。一旦事件处理程序上线,就会读取队列并按预期处理消息。
但是,由于同一个对象多次在队列中,第一次写入成功,下一次写入失败并抛出此并发异常。
我使用工厂类在我的所有应用程序中拥有一致的 IDocumentStore 和 IDocumentSession。我专门UseOptimisticConcurrency = false
在 GetSession() 方法中设置了。
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;
}
}
事件处理程序看起来像这样。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>())));
}
这是具有 ConcurrencyException 的实际 EventHandler。
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 吗?无论文档之前是否已更新,我都希望进行保存。