我不断收到一个ConcurrencyException,它试图连续多次更新同一文档。消息是PUT attempted on document '<id>' using a non current etag
。RavenDB一直抛出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?无论文档是否已经更新过,我都希望保存发生。
看看这个,它可以帮助你与并发问题http://johnculviner.com/achieving-named -lock-locker-functionality-in-c-4-0/ –
现在已经接近一年了,你找到了解决方案吗? – simonlchilds
有没有人想过这个?它似乎只在我的文档类型中的一个保存在处理程序中 - 所有其他文件似乎都很好保存! – iwayneo